\ midi utilities menu & gui
\
\ midi_menu
\ generic, mac specific, menu bar items for testing and configuring midi io.
\ Note that a good deal of the code is dependent on mac's gui and will not
\ be easy to port.
\
\ note: this component requires the resource file "midi menu res".
\
\
\ description of words:
\
\ midi.menu.init ( -- , initialize system )
\ midi.menu.term ( -- , terminate & restore menubar )
\
\ call the above words before and after use, respectively.
\
\ midi.menu.default ( -- , sets variables to default )
\
\ called internally by MIDI.MENU.INIT. The word restores internal variables
\ to their default state, but does not affect the state of the menu.
\
\ draw.midi.menu ( -- , add the midi menu to the menubar )
\ undraw.midi.menu ( -- , removes the midi menu from the menubar )
\
\ these words add and remove, respectively, the midi menu to the menubar.
\
\ enable.midi.menu ( item# -- , enable one midi menu item )
\ disable.midi.menu ( item# -- , disable one midi menu item )
\
\ midi.menu.on ( -- , enables the entire midi menu )
\ midi.menu.off ( -- , disables the entire midi menu )
\
\ ENABLE.MIDI.MENU and DISABLE.MIDI.MENU, respectively, turns on and off the
\ given item of the midi menu. MIDI.MENU.OFF diables the entire menu, while
\ MIDI.MENU.ON turns the menu back to its previous state (i.e. any individual
\ items that have been disabled, will remain disabled).
\
\ midi.menu.play ( -- , only enable items useful when MIDI is active )
\ midi.menu.idle ( -- , have all items available for use )
\
\ These are for quick and easy changing of the midi menu from a state in
\ which all items are active to one in which only those useful in performance
\ are active (panic & alloff).
\
\
\ code: Han-earl Park
\ copyright 2004 buster & friends' C-ALTO Labs
\ (Southampton, May 2000 -
\
\ MOD: HeP 05/23/00 Started project.
\ MOD: HeP 07/12/00 Add the "which-part @ 15 AND" line...!?!
\ MOD: HeP 07/15/00 Add words to enable/disable menu and menu items.
\ MOD: HeP 07/24/00 Preliminary test of the "modeless" dialog box.
\ MOD: HeP 07/26/00 Doesn't seem to be an easy way of keeping the dialog box
\ at front due to the way the H4th event tracker works!
\ Add menu for changing buffer size (i.e. time-advance).
\ MOD: HeP 08/07/00 MIDI.MENU.ON and MIDI.MENU.OFF respectively enables and
\ disables midi menu instead of each and every menu item.
\ MOD: HeP 08/26/00 Change resource id numbers. Note that hmsl restricts menu
\ id numbers to between 128 and 143.
\ MOD: HeP 08/26/00 Change the dialog boxs' procID from 5 to 4 to prevent
\ possible problems w/ earlier system software.
\ MOD: HeP 09/03/00 Add MENUS.ON and MENUS.OFF which enable and disable all
\ of hmsl's (and user defined) menus.
\ MOD: HeP 09/08/00 Test out the midi dialog. Works, although in terms of Mac
\ human interface guidelines, a bit funky :-/
\ MENUS.ON and MENUS.OFF enables/disables the entire apple
\ menu, not just the "about..." item.
\ MIDI.DIALOG.START and MIDI.DIALOG.STOP are called from
\ MDLOG.OPEN and MDLOG.CLOSE.
\ Implement DRAW.MIDI.MENU and UNDRAW.MIDI.MENU and tested.
\ Add "parent" words to words that alter the appearance of
\ the menubar. The words are the same except the "parent"
\ words do not call DrawMenuBar().
\ MOD: HeP 09/11/00 Setup default values for buffer, port and driver menus.
\ BUFFER.MENU.FUNC checks current menu item and unchecks
\ previously selected item.
\ MOD: HeP 09/12/00 Stop the driver selector from retriggering (eg. when the
\ custom driver is called twice).
\ MOD: HeP 09/14/00 Buffer Size dialog box specifies time in milliseconds.
\ Buffer Size menu and dialog box implemented and tested.
\ Change MDLOG. prefix to MTDLOG. and BDLOG. to BTDLOG.
\ Trash MIDI.DIALOG.START and MIDI.DIALOG.STOP.
\ MOD: HeP 09/15/00 Provisional (?) implementation of MIDIM.AVAILABLE? to
\ check whether apple midi manager is installed.
\ Moved commonly used dialog support code to myt:dialog.
\ MOD: HeP 09/19/00 Fix bug involving code in myt:dialog closing dialogs.
\ Reintroduce the user specified dialog start/stop words.
\ MOD: HeP 09/22/00 Fix bug in MBDLOG.HANDLE.OK that left a zero on the stack.
\ MOD: HeP 10/23/00 Fix another bug in MBDLOG.HANDLE.OK that left a number
\ on the stack!
\ MOD: HeP 11/20/00 midi test uses duration based on current RTC.RATE@.
\ MOD: HeP 11/22/00 Change command key for Panic menu item from ascii ! to P.
\ MOD: HeP 03/22/01 Use DLOG.CLICK.BUTTON when EOL in dialog windows.
\ MOD: HeP 03/23/01 Rewrite MBDLOG.GET.NUMBER based on DLOG.GET.INT.
\ Fix: Selecting the other_sec_item# menu item used to
\ update the buffer size value, even when dialog window was
\ already open.
\ MOD: HeP 05-06-04 allot 256 bytes for buffer-item-text.
\ MOD: HeP 05-24-04 Fix (MIDI.MENU.ON) and (MIDI.MENU.OFF) which used to call
\ DrawMenuBar().
\ MIDI.MENU.PLAY and MIDI.MENU.IDLE not longer have a
\ redundant call to DrawMenuBar().
include? task-dialog myt:dialog
anew task-midi_menu
.NEED ticks>msec
: TICKS>MSEC ( ticks -- msec , convert ticks to milliseconds )
1000 * rtc.rate@ /
;
: MSEC>TICKS ( msec -- ticks , convert milliseconds to ticks )
rtc.rate@ * 1000 /
;
.THEN
\ resource id#
140 constant test_dlog_id
141 constant buffer_dlog_id
140 constant midi_menu_id
141 constant buffer_menu_id
142 constant port_menu_id
143 constant driver_menu_id
\ menu handles
variable midi-menu-handle
variable buffer-menu-handle
variable port-menu-handle
variable driver-menu-handle
\ menu item#
1 constant midi_test_item#
2 constant midi_thru_item#
4 constant midi_panic_item#
5 constant midi_alloff_item#
7 constant midi_buffer_item#
8 constant midi_port_item#
9 constant midi_driver_item#
1 constant 0.0_sec_item#
2 constant 0.5_sec_item#
3 constant 1.0_sec_item#
4 constant 1.5_sec_item#
5 constant 2.0_sec_item#
7 constant other_sec_item#
1 constant modem_item#
2 constant printer_item#
1 constant apple_midi_item#
2 constant custom_midi_item#
\ menu state
variable mmenu-buffer
variable mmenu-port
variable mmenu-driver
1.0_sec_item# value mmenu_default_buffer
modem_item# value mmenu_default_port
custom_midi_item# value mmenu_default_driver
\ draw & undraw midi menu
: (DRAW.MIDI.MENU) ( -- )
midi-menu-handle @ 0 InsertMenu() \ menuHandle beforeID --
buffer-menu-handle @ -1 InsertMenu()
port-menu-handle @ -1 InsertMenu()
driver-menu-handle @ -1 InsertMenu()
;
: (UNDRAW.MIDI.MENU) ( -- )
midi-menu-handle @
IF
midi_menu_id DeleteMenu()
buffer_menu_id DeleteMenu()
port_menu_id DeleteMenu()
driver_menu_id DeleteMenu()
THEN
;
: DRAW.MIDI.MENU ( -- )
(draw.midi.menu) DrawMenuBar()
;
: UNDRAW.MIDI.MENU ( -- )
(undraw.midi.menu) DrawMenuBar()
;
\ disable & enable menu
: (ENABLE.MIDI.MENU) ( item# -- )
midi-menu-handle @ swap EnableItem()
;
: (DISABLE.MIDI.MENU) ( item# -- )
midi-menu-handle @ swap DisableItem()
;
: ENABLE.MIDI.MENU ( item# -- , enable one midi menu item )
(enable.midi.menu) DrawMenuBar()
;
: DISABLE.MIDI.MENU ( item# -- , disable item )
(disable.midi.menu) DrawMenuBar()
;
: (MIDI.MENU.ON) ( -- )
0 (enable.midi.menu) \ *** used to call enable.midi.menu ***
;
: (MIDI.MENU.OFF) ( -- )
0 (disable.midi.menu) \ *** used to call disable.midi.menu ***
;
: MIDI.MENU.ON ( -- , enable midi menu )
(midi.menu.on) DrawMenuBar()
;
: MIDI.MENU.OFF ( -- , disable midi menu )
(midi.menu.off) DrawMenuBar()
;
\ disable & enable all hmsl's menus
: (MENUS.ON) ( -- )
144 128
DO i GetMHandle() \ -- handle | 0
?dup
IF 0 EnableItem()
THEN
LOOP
;
: (MENUS.OFF) ( -- )
144 128
DO i GetMHandle() \ -- handle | 0
?dup
IF 0 DisableItem()
THEN
LOOP
;
: MENUS.ON ( -- , enable all of hmsl's menus )
(menus.on) DrawMenuBar()
;
: MENUS.OFF ( -- , diable all of hmsl's menus )
(menus.off) DrawMenuBar()
;
\ midi dialogs
variable midi-dlog
defer MTDLOG.START ( -- , user specified procedure )
defer MTDLOG.STOP ( -- )
'c noop is mtdlog.start
'c noop is mtdlog.stop
: (MTDLOG.START) ( -- )
\ menus.off
;
: (MTDLOG.STOP) ( -- )
\ menus.on
;
: MTDLOG.OPEN ( -- , open non-modal dialog box )
midi-dlog test_dlog_id dlog.open
MTDLOG.START
;
: MTDLOG.CLOSE ( -- , close midi dialog box )
midi-dlog dlog.close
MTDLOG.STOP
;
: MTDLOG.SET.TEXT ( $ -- , set static text of the dialog box )
midi-dlog @ 2 dlog.item.handle@
swap
SetIText() \ itemHandle string --
;
: MIDI.DIALOG ( $ -- , set text and open dialog box )
mtdlog.open
mtdlog.set.text
;
\ dialog event handling
\
\ We use an custom event loop instead of ?TERMINAL to prevent another window
\ (eg. the HMSL or H4th window) from becoming active. We should ignore the
\ any mouse clicks that activate other windows, but allows other apps to
\ continue running in the background.
-1 constant every_event \ mac event filter
: MTDLOG.CLOSE.EVENT? ( -- flag , has user closed dialog box )
last-event ..@ er_what
keyDwnEvt =
IF
last-event ..@ er_message $ FF and
EOL= \ -- flag
dup
IF midi-dlog 1 dlog.click.button \ dlogVar item# --
THEN
ELSE
last-event midi-dlog item-hit DialogSelect() \ -- flag
THEN
;
: MTDLOG.HANDLE.EVENT ( -- , handle non-dialog events )
\ handle other events here?
last-event ..@ er_what
updatEvt =
IF last-event ..@ er_message BeginUpdate()
last-event ..@ er_message EndUpdate()
THEN
;
: (MTDLOG.EVENT) ( -- flag , event tracker for semi-modeless operation )
last-event IsDialogEvent()
IF
mtdlog.close.event? \ -- flag
dup
IF mtdlog.close \ close dialog box
THEN
ELSE
mtdlog.handle.event false
THEN
;
: MTDLOG.EVENT ( -- flag , non-MultiFinder dialog event tracker )
SystemTask()
\
every_event last-event GetNextEvent() \ eventmask event -- 0|1
IF
(MTDLOG.EVENT) \ -- flag
ELSE
false
THEN
;
: MTDLOG.MF.EVENT ( -- flag , MultiFinder dialog event tracker )
every_event last-event 0 null
WaitNextEvent() \ eventmask event sleep mouseRgn -- 0|1
IF
(MTDLOG.EVENT) \ -- flag
ELSE
false
THEN
;
\ midi test dialog
: (MIDI.TEST.DIALOG) { last_time -- curr_time , run test }
time@ last_time - rtc.rate@ 4/ >
IF
time@ -> last_time
\
17 1
DO i midi.channel!
midi.lastoff
61 choose 36 + 80 midi.noteon
LOOP
THEN
\
last_time
;
: MIDI.TEST.DIALOG ( -- )
" Sending random(ish) MIDI note on messages on all 16 channels."
midi.dialog
\
{ | last_time -- } time@ 20 + -> last_time
\
IfMulti \ -- flag , MultiFinder available?
IF
BEGIN
last_time (midi.test.dialog) -> last_time
mtdlog.mf.event \ -- flag , has dialog box been closed?
UNTIL
ELSE
BEGIN
last_time (midi.test.dialog) -> last_time
mtdlog.event \ -- flag , has dialog box been closed?
UNTIL
THEN
\
17 1
DO i midi.channel!
midi.lastoff
LOOP
;
\ midi thru dialog
: (MIDI.THRU.DIALOG) ( -- )
8 0
DO midi.recv
IF midi.xmit midi.flush
THEN
LOOP
;
: MIDI.THRU.DIALOG ( -- )
" Echoing MIDI messages recieved on input port to output port."
midi.dialog
\
midi.clear
\
IfMulti \ -- flag , MultiFinder available?
IF
BEGIN
(midi.thru.dialog)
mtdlog.mf.event \ -- flag , has dialog box been closed?
UNTIL
ELSE
BEGIN
(midi.thru.dialog)
mtdlog.event \ -- flag , has dialog box been closed?
UNTIL
THEN
;
\ midi menu functions
: MIDI.MENU.FUNC ( -- , midi menu handler )
which-part @ 15 AND
CASE
midi_test_item# OF midi.test.dialog ENDOF
midi_thru_item# OF midi.thru.dialog ENDOF
\ ------------------------
midi_panic_item# OF midi.clear midi.panic ENDOF
midi_alloff_item# OF midi.clear midi.killall ENDOF
ENDCASE
;
\ midi buffer dialog
variable buffer-dlog
windowTracker buffer-tracker
create buffer-item-text 256 allot
\ handle dialog text
: MBDLOG.SET.TEXT ( addr count -- , set user text of the dialog box )
buffer-item-text off
buffer-item-text $append \ setup buffer-item-text
\
buffer-dlog @ 4 dlog.item.handle@
buffer-item-text
SetIText() \ itemHandle $ --
\
buffer-dlog @
4
0
buffer-item-text c@
SeLIText() \ the-dialog itemno strtsel endsel --
;
: MBDLOG.GET.TEXT ( -- addr count , get user text of the dialog box )
buffer-dlog @ 4 dlog.item.handle@
buffer-item-text
GetIText() \ itemHandle varText --
\
buffer-item-text count
;
: MBDLOG.SET.NUMBER ( n -- )
n>text mbdlog.set.text
;
: MBDLOG.GET.NUMBER ( -- n flag , true if valid number )
mbdlog.get.text text>string
\
number? \ -- d true | false
IF
drop \ just want 32 bit precision
\
dpl @ \ decimal point location
dup 0>
IF 0
DO 10 /
LOOP
ELSE
drop
THEN
\
TRUE \ -- n true
ELSE
0 FALSE \ -- 0 false
THEN
;
\ open/close dialog
: MBDLOG.OPEN ( -- , open modeless MIDI buffer dialog box )
buffer-dlog @ 0=
IF
buffer-dlog buffer_dlog_id dlog.open
buffer-dlog @ buffer-tracker link.window<->tracker
\
time-advance @ ticks>msec mbdlog.set.number
ELSE
buffer-dlog buffer_dlog_id dlog.open
THEN
;
: MBDLOG.CLOSE ( -- , close midi dialog box )
buffer-dlog dlog.close
;
\ dialog event handling
: MBDLOG.HANDLE.OK ( -- )
mbdlog.get.number
IF
msec>ticks
dup 0 rtc.rate@ 4* within?
IF
dup time-advance !
\
CASE
0 OF 0.0_sec_item# ENDOF
rtc.rate@ 2/ OF 0.5_sec_item# ENDOF
rtc.rate@ OF 1.0_sec_item# ENDOF
rtc.rate@ dup 2/ + OF 1.5_sec_item# ENDOF
rtc.rate@ 2* OF 2.0_sec_item# ENDOF
\
other_sec_item# swap
ENDCASE
\
buffer-menu-handle @ mmenu-buffer @ FALSE checkitem()
buffer-menu-handle @ over TRUE checkitem()
mmenu-buffer !
\
mbdlog.close
ELSE
drop
" Buffer size must be between 0 and 4000 milliseconds." dialog.a
THEN
ELSE
drop
" Invalid number!" dialog.a
THEN
;
: MBDLOG.HANDLE.CANCEL ( -- )
mbdlog.close
;
: MBDLOG.HANDLE.DEFAULT ( -- )
mmenu_default_buffer
CASE
0.0_sec_item# OF " 0" count mbdlog.set.text ENDOF
0.5_sec_item# OF " 500" count mbdlog.set.text ENDOF
1.0_sec_item# OF " 1000" count mbdlog.set.text ENDOF
1.5_sec_item# OF " 1500" count mbdlog.set.text ENDOF
2.0_sec_item# OF " 2000" count mbdlog.set.text ENDOF
ENDCASE
;
: MBDLOG.HANDLE.HIT ( item# -- )
CASE
1 OF mbdlog.handle.ok ENDOF
2 OF mbdlog.handle.cancel ENDOF
3 OF mbdlog.handle.default ENDOF
ENDCASE
;
: (MBDLOG.HANDLE.EVENT) ( -- processed? )
last-event IsDialogEvent()
IF
last-event ..@ er_what keyDwnEvt =
IF
last-event ..@ er_message $ FF and
EOL=
IF
buffer-dlog 1 dlog.click.button \ dlogVar item# --
mbdlog.handle.ok true
ELSE
false
THEN
ELSE
false
THEN
0=
IF last-event buffer-dlog item-hit DialogSelect()
IF item-hit w@ mbdlog.handle.hit
THEN
THEN
true
ELSE
false
THEN
;
: MBDLOG.HANDLE.EVENT ( -- )
(mbdlog.handle.event) drop
;
: MBDLOG.WINDOW.CONTENT ( -- )
FrontWindow() which-window @ -
IF which-window @ SelectWindow()
THEN
;
: MBDLOG.WINDOW.DRAG ( -- )
which-window @ last-event ..@ er_where DragRect DragWindow()
;
: MBDLOG.HANDLE.DOWN ( -- )
(mbdlog.handle.event) 0=
IF which-part @
CASE
InContent OF mbdlog.window.content ENDOF
InDrag OF mbdlog.window.drag ENDOF
ENDCASE
THEN
;
: MIDI.BUFFER.DIALOG ( -- )
mbdlog.open
;
\ buffer size submenu function
: BUFFER.MENU.FUNC ( -- )
which-part @ 15 AND
\
dup other_sec_item# =
IF
drop
midi.buffer.dialog
ELSE
dup
CASE
0.0_sec_item# OF 0 time-advance ! ENDOF
0.5_sec_item# OF rtc.rate@ 2/ time-advance ! ENDOF
1.0_sec_item# OF rtc.rate@ time-advance ! ENDOF
1.5_sec_item# OF rtc.rate@ dup 2/ + time-advance ! ENDOF
2.0_sec_item# OF rtc.rate@ 2* time-advance ! ENDOF
ENDCASE
\
buffer-menu-handle @ mmenu-buffer @ FALSE checkitem()
buffer-menu-handle @ over TRUE checkitem()
mmenu-buffer !
\
buffer-dlog @
IF time-advance @ ticks>msec mbdlog.set.number
THEN
THEN
;
\ serial port submenu function
: PORT.MENU.FUNC ( -- )
which-part @ 15 AND
\
dup
CASE
modem_item# OF modem_port midi-port ! ENDOF
printer_item# OF printer_port midi-port ! ENDOF
ENDCASE
\
port-menu-handle @ mmenu-port @ FALSE checkitem()
port-menu-handle @ over TRUE checkitem()
mmenu-port !
;
\ driver submenu functions
: MIDI.DRIVER.DIALOG ( -- flag )
" Are you sure you want to switch MIDI drivers?"
dialog.a/b
;
: MIDI.MANAGER.DIALOG ( -- )
" The Apple MIDI Manger is not present in your system. Install the driver, and restart your computer."
dialog.a
;
\ check for midi manager
\
\ note: I couldn't find any documentation regarding the apple midi manager
\ or SndDispVersion(). I'm relying on the code used in hmsl to infer the
\ working of the system. The joys of using legacy software :-)
: MIDIM.AVAILABLE? ( -- flag , check if Apple MIDI Manager is installed )
MIDIToolNum SndDispVersion()
;
: MIDIM.PORTS.INIT+ ( -- flag , initialize ports for MIDI )
midim-if-on @ 0=
IF
midim.available?
IF
." Apple MIDI Manager Initialized!" cr
midim.signin
midim.add.ports
midim-if-on on
midim.connect.ports
\
TRUE
ELSE
MIDI.MANAGER.DIALOG
\
FALSE
THEN
ELSE
TRUE
THEN
;
: DRIVER.MENU.APPLE ( -- )
mmenu-driver @ custom_midi_item# =
IF
midi.driver.dialog
IF
midi-port @ \ save current port setting
use.midi.manager
\
MIDIM.PORTS.INIT+
IF
midi.init \ ??? is this the correct .INIT word ???
\
driver-menu-handle @ apple_midi_item# TRUE checkitem()
driver-menu-handle @ custom_midi_item# FALSE checkitem()
\
apple_midi_item# mmenu-driver !
ELSE
use.custom.midi
\
driver-menu-handle @ apple_midi_item# DisableItem()
THEN
\
midi-port ! \ restore port setting
THEN
THEN
;
: DRIVER.MENU.CUSTOM ( -- )
mmenu-driver @ apple_midi_item# =
IF
midi.driver.dialog
IF
midi-port @ \ save current port setting
\
use.custom.midi
midi.init \ ??? is this the correct .INIT word ???
\
driver-menu-handle @ apple_midi_item# FALSE checkitem()
driver-menu-handle @ custom_midi_item# TRUE checkitem()
\
custom_midi_item# mmenu-driver !
\
midi-port ! \ restore port setting
THEN
THEN
;
: DRIVER.MENU.FUNC ( -- , driver selector )
which-part @ 15 AND
CASE
apple_midi_item# OF driver.menu.apple ENDOF
custom_midi_item# OF driver.menu.custom ENDOF
ENDCASE
;
\ simple menu state control
\
\ note: for consistency with other words here, we define "parent" words
: (MIDI.MENU.PLAY) ( -- )
midi_test_item# (disable.midi.menu)
midi_thru_item# (disable.midi.menu)
midi_panic_item# (enable.midi.menu) \ enable panic item
midi_alloff_item# (enable.midi.menu) \ enable alloff items
midi_buffer_item# (disable.midi.menu)
midi_port_item# (disable.midi.menu)
midi_driver_item# (disable.midi.menu)
\
mtdlog.close
mbdlog.close
;
: (MIDI.MENU.IDLE) ( -- )
midi_test_item# (enable.midi.menu)
midi_thru_item# (enable.midi.menu)
midi_panic_item# (enable.midi.menu)
midi_alloff_item# (enable.midi.menu)
midi_buffer_item# (enable.midi.menu)
midi_port_item# (enable.midi.menu)
midi_driver_item# (enable.midi.menu)
;
: MIDI.MENU.PLAY ( -- , only enable items useful when MIDI is active )
(midi.menu.play)
;
: MIDI.MENU.IDLE ( -- , have all items available for use )
(midi.menu.idle)
;
\ setup & clearup
: MIDI.MENU.DEFAULT ( -- )
mmenu_default_buffer mmenu-buffer !
mmenu_default_port mmenu-port !
mmenu_default_driver mmenu-driver !
;
: MIDI.MENU.INIT ( -- )
midi.menu.default
\
0 midi-dlog !
'c (mtdlog.start) is MTDLOG.START
'c (mtdlog.stop) is MTDLOG.STOP
\
0 buffer-dlog !
'c mbdlog.handle.event buffer-tracker ..! wt_evhandler
'c mbdlog.handle.down buffer-tracker ..! wt_MDHandler
\
midi_menu_id GetMenu() midi-menu-handle !
buffer_menu_id GetMenu() buffer-menu-handle !
port_menu_id GetMenu() port-menu-handle !
driver_menu_id GetMenu() driver-menu-handle !
\
'c midi.menu.func midi_menu_id ev.menu.func!
'c buffer.menu.func buffer_menu_id ev.menu.func!
'c port.menu.func port_menu_id ev.menu.func!
'c driver.menu.func driver_menu_id ev.menu.func!
\
midim.available? NOT
IF driver-menu-handle @ apple_midi_item# DisableItem()
custom_midi_item# -> mmenu_default_driver
THEN
;
: MIDI.MENU.TERM ( -- )
mtdlog.close
\
mbdlog.close
\
undraw.midi.menu
\
midi-menu-handle @
IF
midi-menu-handle @ DisposeMenu()
buffer-menu-handle @ DisposeMenu()
port-menu-handle @ DisposeMenu()
driver-menu-handle @ DisposeMenu()
\
0 midi-menu-handle !
0 buffer-menu-handle !
0 port-menu-handle !
0 driver-menu-handle !
THEN
;
if.forgotten midi.menu.term
cr ." Remember to include the 'midi menu res' resource file." cr cr