Dr.Godfried-Willem RAES

Kursus Experimentele Muziek: Boekdeel 1: Algoritmische Kompositie

Hogeschool Gent : Departement Muziek & Drama


<Terug naar inhoudstafel kursus>

   

Dit hoofdstuk mag vandaag achterhaald heten. Binnen de nu in de klas gebruikte programeeromgeving (PowerBasic en de Windows API) stelt gebruik van de muis geen problemen. Niettemin bewaarden we dit hoofstuk toch hier, omdat het een low-level aanpak omvat voor de besturing van hardware interfaces.

1140

Muizen, Muizevallen, Muizenissen...

De muis als input-device heeft pas laat haar intrede gedaan in de wereld van de Intel personal komputers. Dit verklaart waarom het ding niet wordt ondersteund door het gros van de DOS programmas, inklusief kompilers en interpreters. Op PC's kennen we vandaag 2 verschillende muistypes: seriele muizen en bus muizen. De eerste soort maakt gebruik van een van de standaard seriele poorten op de PC (RS232), de tweede van een eigen en specifiek interface via een afzonderlijke I/O poort. Konden we vroeger muizen in onze eigen Basic programmas eigenlijk slechts gebruiken door rechtstreekse adressering van de hardware -iets wat steeds voor kompatibiliteitsproblemen zorgde, dan kunnen we nu gebruik maken van een reeks specifieke DOS-funkties die sedert DOS 6.0 vast deel zijn gaan uitmaken van het operating system. Helaas werden de beschikbare DOS interpreters voor Basic niet aan deze nieuwe situatie aangepast zodat we geen intrinsieke Basic funkties ter beschikking hebben waardoor de muis kan worden geintegreerd in onze eigen programmas.

Dit betekent echter niet dat we aan muizenissen moeten verzaken! Basic beschikt immers over de mogelijkheid via een interrupt call routine rechtstreeks alle DOS-funkties te gebruiken. In QBX-PDS moeten daartoe de specifieke libraries met de interpreter opgeladen worden bij het opstarten. Dit gebeurt via het kommando QBX /L. Vervolgens moeten de funkties via een include bestand in het programma opgenomen worden.

We geven een voorbeeld van een programma waarmee 'slider'-controllers ook binnen DOS kunnen worden ontworpen:

' This demonstration program contains all procedures required for mouse

' support under QBX - PDS version 7.1

' For compilation start up with the /L command: QBS /L

' The slider controllers as implemented here have advantages over the

' windows-silder controls: you can instantaneously input changes (no need

' to drag a knob) and they perform very fast draws. The code is suitable

' for use in multitaskers. Make sure you do not exagarate in the rsi's for

' the controls. Humans are'nt all that fast...

'$DYNAMIC

TYPE RegType

ax AS INTEGER

bx AS INTEGER

cx AS INTEGER

dx AS INTEGER

bp AS INTEGER

si AS INTEGER

di AS INTEGER

flags AS INTEGER

END TYPE

TYPE RegTypeX

ax AS INTEGER

bx AS INTEGER

cx AS INTEGER

dx AS INTEGER

bp AS INTEGER

si AS INTEGER

di AS INTEGER

flags AS INTEGER

ds AS INTEGER

es AS INTEGER

END TYPE

TYPE ControllerBlok

x1 AS INTEGER ' linkeronderhoek koordinaten

y1 AS INTEGER

x2 AS INTEGER ' rechterbovenboek koordinaten

y2 AS INTEGER

label AS STRING * 8 ' opschrift boven het sliderblok

rangelow AS INTEGER ' lowest returnvalue

rangehigh AS INTEGER ' highest returnvalue

nr AS INTEGER

retval(0 TO 127) AS INTEGER ' return values, slider-positions

END TYPE

CONST False = 0

CONST True = NOT False

DECLARE SUB Interrupt (intnum AS INTEGER, inreg AS RegType, outreg AS RegType)

DECLARE SUB InterruptX (intnum AS INTEGER, inreg AS RegTypeX, outreg AS RegTypeX)

DECLARE SUB Absolute (address AS INTEGER)

DECLARE SUB InitMuis ()

DECLARE SUB Muis (h%, v%, b%)

DECLARE SUB Slider (funktienummer%, h%, v%, button%, ctrl%, bt%)

DIM SHARED regs AS RegType

DIM SHARED Colums AS INTEGER, Lines AS INTEGER

DECLARE FUNCTION GetVideoMode! ()

Colums = 80

Lines = 60

SCREEN 12

WIDTH Colums, Lines

InitMuis

' kreeer 16 sliders:

horpos% = 100

verpos% = 256

breedte% = 4

afstand% = 10

aantal% = 16

Slider 1, horpos%, verpos%, aantal%, breedte%, afstand%

' gebruik ze:

DO

Muis h%, v%, b%

Slider 0, h%, v%, b%, controllernr%, value%

' onderschrift voor sliderblok:

LOCATE 2 + (verpos% \ 8), 2 + (horpos% \ 8)

PRINT "Slider:"; controllernr%; " ="; value%

k$ = INKEY$

SELECT CASE k$

CASE CHR$(27), "*"

END

CASE "+"

' test for rescaling of sliders whilst preserving contents

Slider 2, (horpos%), (verpos%), 16, (breedte% * 2), (afstand% * 2)

CASE "-"

' reset original

' with the brackets we force a call by value!

Slider 2, (horpos%), (verpos%), 16, breedte%, afstand%

CASE " "

' delete sliders

Slider -1, 0, 0, 0, 0, 0

EXIT DO

END SELECT

LOOP

REM $STATIC

FUNCTION GetVideoMode

DIM register AS RegType

' test-kode:

FOR i% = 0 TO 12

SELECT CASE i%

CASE 0, 1, 2, 7, 8, 9, 10, 11, 12

SCREEN i%

' use dos irq call to get current video mode:

register.ax = &HF00

CALL Interrupt(&H10, register, register)

SELECT CASE register.ax MOD 256

CASE &H11, &H12: SCREEN i%: WIDTH 80, 60

END SELECT

PRINT "Basic SCREEN"; i%; "= BIOS video mode="; regs.ax MOD 256

'SLEEP 3

CASE ELSE

' illegal

END SELECT

NEXT i%

GetVideoMode = register.ax MOD 256

END FUNCTION

SUB InitMuis

regs.ax = &H1

CALL Interrupt(&H33, regs, regs)

END SUB

SUB Muis (h%, v%, b%)

regs.ax = &H1

CALL Interrupt(&H33, regs, regs): ' show mouse pointer

regs.ax = &H3

CALL Interrupt(&H33, regs, regs)

h% = regs.cx: ' 0->639

v% = regs.dx: ' 0->479

b% = regs.bx: ' 0= no button

' 1= left button d0

' 2= right button d1

' 3= both buttons

' 4= middle button d2

'Task(13).rsi = Lps% / 20: ' 20 x per sec.

END SUB

SUB MuisHandler (hor%, ver%)

Khor% = (hor% \ 8) + 1

Kver% = (ver% \ 8) + 1

' -> locate-compatible coordinates for 80x60 screen

END SUB

SUB Slider (FuncNumber%, h%, v%, but%, ctrl%, retval%)

STATIC Sliderareas() AS INTEGER, Slidervalues() AS INTEGER, Toggle%

CONST sliderlengte% = 127: ' in pixels (7-bit resolution) - this is a constant!!!

' this also limits retval% to this value

CONST SliderBackColor = 10: ' green

CONST SliderBorderColor = 13: ' purple

CONST SliderHotColor = 12: ' red

IF Toggle% = 0 THEN

Toggle% = True: ' reset by deleting sliders.

DIM Sliderareas(0 TO 3, 0 TO 7) AS INTEGER

DIM Slidervalues(0 TO 7) AS INTEGER: ' pro forma

END IF

' Users-guide:

' FuncNumber% -1: removes sliders

' FuncNumber% 1: creates sliders

' the parameters then are:

' h% = leftmost horizontal position for sliderblock

' v% = vertical coordinate for this same point of the sliderblock

' but% = number of sliders to create

' ctrl% = width of sliders

' retval% = distance (spacing) between sliders

' FuncNumber% 0 : pass mouse params en returns active slider and its newest position

' h% = horizontal mouse coordinate

' v% = vertical mouse coordinate

' but% = switches byte (left button activates sliders)

' ctrl% = returns the number of the moved slider

' If -1, no slider was moved

' retval% = returns the value of the moved slider

' This is a 7-bit number 0 to 127, (Midi compatible)

' FuncNumber% = 2:

' redraw the sliders but keep the positions intact

' FuncNumber% =3

' return the active area for the slider box in absolute coordinates

' x1% = hor%

' y1% = ver%

' but% = irrelevant

' x2% = ctrl%

' y2% = retval%

' FuncNumber = 4

' return the most recenty position of a given slider control

' hor%= irrelevant

' ver% = irrelevant

' but% = irrelevant

' ctr% = number of the requested controller

' retval% = the requested value

SELECT CASE FuncNumber%

CASE -1

' this removes all sliders from the screen

x1% = Sliderareas(0, 1)

y1% = Sliderareas(1, 1)

x2% = Sliderareas(2, UBOUND(Sliderareas, 2))

y2% = Sliderareas(3, UBOUND(Sliderareas, 2))

LINE (x1% - 1, y1% + 1)-(x2% + 1, y2% - 1), False, BF

' the +1/-1's are because without them, the border is not

' removed properly.

ERASE Sliderareas

' as now it keeps Slidervalues()

' we could also erase this one...

Toggle% = False

CASE 0

' here we make the sliders react on mouse movement

' first we check mouse horizontal position

Sliderhit% = False

FOR i% = 1 TO UBOUND(Sliderareas, 2)

IF h% >= Sliderareas(0, i%) AND h% <= Sliderareas(2, i%) THEN

' check vertical within range condition...

FOR j% = 1 TO UBOUND(Sliderareas, 2)

IF v% >= Sliderareas(3, i%) AND v% <= Sliderareas(1, i%) THEN

' now the mouse must be at slider i%

Sliderhit% = True

' for debug : LOCATE 50, 10: PRINT "Slider"; i%

IF but% = 1 THEN

' if left button is down...

' hide the mouse cursor...

regs.ax = 2

CALL Interrupt(&H33, regs, regs)

LINE (Sliderareas(0, i%) + 1, Sliderareas(1, i%) - 1)-(Sliderareas(2, i%) - 1, v%), SliderHotColor, BF

LINE -(Sliderareas(0, i%) + 1, Sliderareas(3, i%) - 1), SliderBackColor, BF

' show cursus again:

regs.ax = 1

CALL Interrupt(&H33, regs, regs)

ctrl% = i%

retval% = Sliderareas(1, i%) - v%

Slidervalues(i%) = retval%

END IF

EXIT FOR

END IF

NEXT j%

IF Sliderhit% = True THEN EXIT FOR

END IF

NEXT i%

CASE 1

' this case creates sliders

sliderhor% = h%: ' horizontaal vertrekpunt van de reeks sliders

sliderbottom% = v%: 'laagste punt op scherm in absolute koordinaten

sliderafstand% = retval%

sliderbreedte% = ctrl%:

Slideraantal% = but%

REDIM Sliderareas(0 TO 3, 1 TO Slideraantal%) AS INTEGER:

REDIM Slidervalues(1 TO Slideraantal%) AS INTEGER

' needed to remember the positions of the

' sliders for later calls...

FOR i% = 1 TO Slideraantal%

stap% = (i% - 1) * sliderafstand%

Sliderareas(0, i%) = sliderhor% + stap%

Sliderareas(1, i%) = sliderbottom%

Sliderareas(2, i%) = sliderhor% + sliderbreedte% + stap%

Sliderareas(3, i%) = sliderbottom% - sliderlengte%

' here we 'misuse' Basic VIEW to draw boxes...

VIEW (Sliderareas(0, i%), Sliderareas(1, i%))-(Sliderareas(2, i%), Sliderareas(3, i%)),SliderBackColor, SliderBorderColor

NEXT i%

' now we remember where the sliders are on the screen

' the values/setting are kept in Slidervalues()

VIEW: ' reset to full screen view

CASE 2

' redraw/rescale sliders but save slider positions!

' the number of sliders should of course be the same than

' at the time of their original creation

' First we delete the existing sliderbox:

x2% = Sliderareas(2, UBOUND(Sliderareas, 2))

y2% = Sliderareas(3, UBOUND(Sliderareas, 2))

LINE (Sliderareas(0, 1) - 1, Sliderareas(1, 1) + 1)-(x2% + 1, y2% - 1), False, BF

' the +1/-1's are because without them, the border is not

' removed properly.

' then we create the new resized one:

sliderhor% = h%: ' new horizontal starting point for sliderblock

sliderbottom% = v%: 'lowest point in screen in absolute coordinates

sliderafstand% = retval%

sliderbreedte% = ctrl%:

Slideraantal% = UBOUND(Sliderareas, 2)

FOR i% = 1 TO Slideraantal%

stap% = (i% - 1) * sliderafstand%

Sliderareas(0, i%) = sliderhor% + stap%

Sliderareas(1, i%) = sliderbottom%

Sliderareas(2, i%) = sliderhor% + sliderbreedte% + stap%

Sliderareas(3, i%) = sliderbottom% - sliderlengte%

' here we again 'misuse' Basic VIEW to draw boxes...

VIEW (Sliderareas(0, i%), Sliderareas(1, i%))-(Sliderareas(2, i%), Sliderareas(3, i%)),SliderBackColor, SliderBorderColor

VIEW

' replace the previous slider positions:

' recalculate the vertical position:

v% = Sliderareas(1, i%) - Slidervalues(i%)

LINE (Sliderareas(0, i%) + 1, Sliderareas(1, i%) - 1)-(Sliderareas(2, i%) - 1, v%), 12, BF

LINE -(Sliderareas(0, i%) + 1, Sliderareas(3, i%) - 1), 10, BF

NEXT i%

CASE 3

' returns the active area for the sliderbox

h% = Sliderareas(0, LBOUND(Sliderareas, 2))

v% = Sliderareas(1, LBOUND(Sliderareas, 2))

ctrl% = Sliderareas(2, UBOUND(Sliderareas, 2))

retval% = Sliderareas(3, UBOUND(Sliderareas, 2))

CASE 4

' returns the most recent position of a slider in the box.

' the slider must be passed in ctrl%

retval% = Slidervalues%(ctrl%)

END SELECT

END SUB

Deze kode moge dienen als een vertrekpunt voor eigen implementaties.


Filedate: 971104

Terug naar inhoudstafel kursus: <Index Kursus>

Naar homepage dr.Godfried-Willem RAES