\ io \ \ io_ui \ midi and qwerty based user interface for io. \ \ \ see the file io_top for more information. \ \ \ constructor: Han-earl Park \ copyright 2008 buster & friends' C-ALTO Labs \ \ www.busterandfriends.com/io \ \ (Edinburgh, November 1996 - \ (London, August 1997 - \ (Den Haag, October 1997 - \ (Valencia, March 1999 - \ (Southampton, May 2000 - \ (Cork, April 2006 - \ \ (Cork, October 2008 - \ \ REV: 0.0.1 alpha (Southampton, October 2000) \ REV: 0.0.1 beta (Southampton, November 2000) \ REV: 0.0.1 alpha++ (Southampton, July 2004) \ REV: 0.0.1 beta++ (Cork, May 2010) \ \ \ MOD: HeP 03/05/99 Started project afresh! \ This version keeps most of the "intelligence" in the \ objects, while the piece specific elements are kept to a \ minimum. It is also a test for the "laurie" project. \ MOD: HeP 06/20/00 Split off io_ui from io_screen and io_input. \ MOD: HeP 06/21/00 Redesign ui function so that they are state dependent \ (eg. "start" is only available when idle). \ MOD: HeP 06/22/00 Add "state safe" global control words ?IO.START/STOP \ ?IO.PAUSE/RESUME and ?IO.RESET. \ MOD: HeP 06/24/00 Remove half the IO.GR... words. Note that these words now \ call the corresponding global control procedures in \ addition to changing the gui state. \ MOD: HeP 09/22/00 Use EOL=. \ MOD: HeP 09/26/00 Adding provisions for running while io_screen? is false. \ MOD: HeP 10/10/00 Implement ui control via midi song control. \ MOD: HeP 10/13/00 Rename of methods of ob.gr.text (see myt:gr_view). \ MOD: HeP 10/19/00 midi parser is kept on for io_ui. \ REV: 0.0.1 alpha __________________________________________________________ \ MOD: HeP 11/14/00 Move START/STOP and PAUSE/RESUME to io_glob. \ MOD: HeP 11/15/00 More sophisticated user control. The "stop" command will \ stop performance or put system in "nearly finished" mode \ depending on current state. \ REV: 0.0.1 beta __________________________________________________________ \ MOD: HeP 01/21/01 Check that midi controller value is greater than 63 in \ (UI.CTRL.VECTOR) to prevent double triggering. \ MOD: HeP 04-15-04 Trash io_script? which wasn't being used. \ MOD: HeP 05-23-04 The new version of FADE.OUT (in modules:io_interp) results \ in STOP:ing GRTEXT-JOB in GR.STOPPED.TEXT instead of \ IO.UI.STOP. \ MOD: HeP 07-03-04 Each component's .INIT function no longer calls the \ corresponding .DEFAULT function. Instead these are all \ called at the end of IO.INIT. See file io_top. \ REV: 0.0.1 a ++ __________________________________________________________ \ REV: 0.0.1 b ++ __________________________________________________________ \ Version for performance at Blackrock Castle Observatory, \ Cork, Ireland, May 25, 2010. \ \ \ ToDo: Multi-channel midi ui control? Provisions for more than one ui \ controller at a time? \ ToDo: Default ui function? START when idle, STOP when playing? anew task-io_ui .NEED eol= : EOL= ( char -- flag , true if return of enter key ) dup EOL = swap 3 = OR ; .THEN \ status text display io_screen? .IF ob.gr.text status-grtext : GR.STATUS.TEXT ( $ -- ) put.string: status-grtext ; .ELSE : GR.STATUS.TEXT ( $ -- ) >newline ." " tab $. ; .THEN io_screen? .IF ob.job grtext-job : GR.TEXT.JOB.FUNC ( job -- ) dup get.data: [] dup 1+ rot put.data: [] \ -- indx \ " itŐs finished it must be finished it must be nearly finished itŐs finished it mu" \ count \ -- indx addr count 18 - rot swap mod \ -- addr offset + \ -- addr+ 18 \ -- addr+ count+ \ put.text: status-grtext ; .THEN : GR.PANIC.TEXT ( -- ) " Panic..." gr.status.text ; : GR.RESET.TEXT ( -- ) " Reset..." gr.status.text ; : GR.STOPPED.TEXT ( -- ) [ io_screen? .IF ] stop: grtext-job \ MOD: 05-23-04 moved from IO.UI.STOP [ .THEN ] \ " Finishing..." gr.status.text ; io_screen? .IF variable prev-status-string : GR.SAVE.TEXT ( -- , save current string for later ) get.string: status-grtext prev-status-string ! ; : GR.RESTORE.TEXT ( -- , restore to previous status text ) prev-status-string @ put.string: status-grtext ; .ELSE : GR.SAVE.TEXT ( -- ) ; : GR.RESTORE.TEXT ( -- ) ; .THEN \ command strings $rom ui-strings ," " \ zero length string ," Start" ," Stop" ," Pause" ," Resume" ," Panic!" io_screen? .IF ob.gr.text ui-grtext : GR.UI.TEXT ( $ -- ) put.string: ui-grtext ; .ELSE : GR.UI.TEXT ( $ -- ) >newline tab ." [ui]" tab $. ; .THEN \ selectors 5 constant ui_#ctrl 0 constant ui_noop 1 constant ui_start 2 constant ui_stop 3 constant ui_pause 4 constant ui_resume 5 constant ui_panic \ functions variable ui-indx# ob.elmnts ui-func-list : UI.EXEC ( -- , execute current function ) [ io_screen? .IF ] 2 put.color: ui-grtext [ .THEN ] \ ui-indx# @ 0 ed.at: ui-func-list \ -- cfa execute \ [ io_screen? .IF ] 1 put.color: ui-grtext [ .THEN ] ; : UI.SELECT ( indx -- , set current function to given indx ) dup ui-indx# ! \ 1 ed.at: ui-func-list \ -- $ gr.ui.text ; : UI.NEXT ( -- , select next function ) ui-indx# @ 1+ many: ui-func-list mod UI.SELECT ; : UI.ZERO ( -- , select null function ) 0 ui-indx# ! 0 gr.ui.text ; \ midi parser \ \ system control via midi controllers : (UI.CTRL.VECTOR) ( ctrl# value -- ) 63 > IF dup io-ui-c1 @ = IF drop \ ui-indx# @ 1+ many: ui-func-list mod dup UI.SELECT ui-indx# ! ELSE io-ui-c2 @ = IF UI.EXEC THEN THEN ELSE drop THEN ; : UI.CTRL.VECTOR ( ctrl# value -- ) mp.channel@ io-ui-chan# @ = IF 2dup (UI.CTRL.VECTOR) THEN \ PARSER.CTRL.VECTOR \ ctrl# value -- ; \ system control via midi preset message variable ui-preset# : UI.PRESET.VECTOR ( pr# -- ) mp.channel@ io-ui-chan# @ = IF dup ui-preset# @ 1+ 128 mod = IF UI.EXEC ELSE UI.NEXT THEN ui-preset# ! ELSE drop THEN ; \ system control via midi song/sequence transport : UI.START.VECTOR ( -- ) safe.play ; : UI.STOP.VECTOR ( -- ) imbnf/stop ; : UI.CONT.VECTOR ( -- ) pause/resume ; : UI.PANIC.VECTOR ( ctrl# value -- ) mp.channel@ io-ui-chan# @ = IF over $ 7B = IF IO.PANIC THEN THEN \ PARSER.CTRL.VECTOR \ ctrl# value -- ; \ select midi message type : UI.MP.RESET ( -- ) 'c 2drop mp-control-vector ! 'c drop mp-program-vector ! 'c noop mp-start-vector ! 'c noop mp-stop-vector ! 'c noop mp-continue-vector ! ; : UI.USE.CONTROL ( -- ) ui.mp.reset 'c (ui.ctrl.vector) mp-control-vector ! ; : UI.USE.PRESET ( -- ) ui.mp.reset 'c ui.preset.vector mp-program-vector ! \ -2 ui-preset# ! ; : UI.USE.SONG ( -- ) ui.mp.reset 'c ui.start.vector mp-start-vector ! 'c ui.stop.vector mp-stop-vector ! 'c ui.cont.vector mp-continue-vector ! ; : SET.UI.CTRL ( type -- , select midi message type ) dup io-ui-ctrl ! CASE io_ui_control OF ui.use.control ENDOF io_ui_preset OF ui.use.preset ENDOF io_ui_song OF ui.use.song ENDOF ENDCASE ; \ qwerty parser : UI.QWERTY.HELP ( -- , print qwerty commands ) [ io_turnkey? io_test? NOT AND .IF ] cls [ .ELSE ] cr cr cr [ .THEN ] \ ." [ space ] Select Function" cr ." [ return] Execute" cr cr ." [ S ] Start/Stop" cr ." [ P ] Pause/Resume" cr ." [ ! ] Panic" cr ." [ Q ] Quit" cr ; : UI.QWERTY.VECTOR ( char -- ) CASE BL OF ui.next ENDOF dup EOL= ?OF ui.exec ENDOF \ ascii ! OF io.panic ENDOF ascii 1 OF io.panic ENDOF \ ascii S OF start/stop ENDOF ascii P OF pause/resume ENDOF \ ui.qwerty.help ENDCASE ; : UI.QWERTY.FUNC ( char screen -- , called by screen ) drop ui.qwerty.vector ; \ system control : IO.UI.DEFAULT ( -- ) io_ui set.ui.ctrl UI.ZERO ; : IO.UI.RESET ( -- ) test" IO.UI.RESET" ; : IO.UI.UPDATE ( -- ) ; : IO.UI.PANIC ( -- ) ; : IO.UI.STANDBY ( -- ) empty: ui-func-list 'c noop ui_noop ui-strings add: ui-func-list 'c imbnf/stop ui_stop ui-strings add: ui-func-list 'c io.gr.pause ui_pause ui-strings add: ui-func-list 'c io.panic ui_panic ui-strings add: ui-func-list \ UI.ZERO \ " Standby..." gr.status.text \ io-ui-ctrl @ io_ui_control = IF 'c ui.ctrl.vector ELSE 'c parser.ctrl.vector THEN mp-control-vector ! ; : IO.UI.START ( -- ) " Playing..." gr.status.text ; : UI.IMBNF ( -- , it must be nearly finished ) [ io_screen? .IF ] start: grtext-job [ .ELSE ] ." It must be nearly finished." gr.status.text [ .THEN ] ; : IO.UI.STOP ( -- ) empty: ui-func-list 'c noop ui_noop ui-strings add: ui-func-list 'c io.gr.play ui_start ui-strings add: ui-func-list 'c io.panic ui_panic ui-strings add: ui-func-list \ UI.ZERO \ " Idle." gr.status.text \ io-ui-ctrl @ io_ui_control = IF 'c (ui.ctrl.vector) ELSE 'c 2drop THEN mp-control-vector ! ; : IO.UI.PAUSE ( -- ) [ io_screen? .IF ] io.imbnf? IF stop: grtext-job THEN [ .THEN ] \ empty: ui-func-list 'c noop ui_noop ui-strings add: ui-func-list 'c io.gr.stop ui_stop ui-strings add: ui-func-list 'c io.gr.resume ui_resume ui-strings add: ui-func-list 'c io.panic ui_panic ui-strings add: ui-func-list \ 2 UI.SELECT \ " Paused." gr.status.text ; : IO.UI.RESUME ( -- ) empty: ui-func-list 'c noop ui_noop ui-strings add: ui-func-list 'c imbnf/stop ui_stop ui-strings add: ui-func-list 'c io.gr.pause ui_pause ui-strings add: ui-func-list 'c io.panic ui_panic ui-strings add: ui-func-list \ 2 UI.SELECT \ [ io_screen? .IF ] io.imbnf? IF start: grtext-job ELSE " Resume playing..." gr.status.text THEN [ .ELSE ] " Resume playing..." gr.status.text [ .THEN ] ; \ setup & clearup : IO.UI.INIT ( -- ) test" IO.UI.INIT" \ [ io_screen? .IF ] 04 put.font: status-grtext \ stuff{ 'c gr.text.job.func }stuff: grtext-job io_rtc_rate 7 / put.duration: grtext-job [ .THEN ] \ " Idle." gr.status.text \ ui_#ctrl 2 new: ui-func-list 'c noop ui_noop ui-strings add: ui-func-list 'c io.gr.play ui_start ui-strings add: ui-func-list 'c io.panic ui_panic ui-strings add: ui-func-list \ \ io.ui.default \ removed MOD: 07-03-04 ; : IO.UI.TERM ( -- ) test" IO.UI.TERM" \ [ io_screen? .IF ] free: grtext-job [ .THEN ] \ free: ui-func-list ; if.forgotten io.ui.term io_test? .IF : IO.UI.PRINT ( -- ) >newline ." IO_UI" cr ; .THEN