/usr/share/ardour5/scripts/midimon.lua is in ardour-data 1:5.12.0-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | ardour {
["type"] = "dsp",
name = "a-MIDI Monitor",
category = "Visualization",
license = "GPLv2",
author = "Ardour Team",
description = [[Display recent MIDIĀ events inline in the mixer strip]]
}
local maxevents = 20
local ringsize = maxevents * 3
local evlen = 3
local hpadding, vpadding = 4, 2
function dsp_ioconfig ()
return { { midi_in = 1, midi_out = 1, audio_in = -1, audio_out = -1}, }
end
function dsp_params ()
return
{
{ ["type"] = "input",
name = "Font size",
doc = "Text size used by the monitor to display midi events",
min = 4, max = 12, default = 7, integer = true },
{ ["type"] = "input",
name = "Line count",
doc = "How many events will be shown at most",
min = 1, max = maxevents, default = 6, integer = true },
{ ["type"] = "input",
name = "Hexadecimal",
doc = "If enabled, values will be printed in hexadecimal notation",
min = 0, max = 1, default = 0, toggled = true },
{ ["type"] = "input",
name = "System messages",
doc = "If enabled, the monitor will show System Control and Real-Time messages",
min = 0, max = 1, default = 0, toggled = true },
{ ["type"] = "input",
name = "Numeric Notes",
doc = "If enabled, note-events displayed numerically",
min = 0, max = 1, default = 0, toggled = true },
}
end
function dsp_init (rate)
-- create a shmem space to hold latest midi events
-- a int representing the index of the last event, and
-- a C-table as storage for events.
self:shmem():allocate(1 + ringsize*evlen)
self:shmem():atomic_set_int(0, 1)
local buffer = self:shmem():to_int(1):array()
for i = 1, ringsize*evlen do
buffer[i] = -1 -- sentinel for empty slot
end
end
function dsp_runmap (bufs, in_map, out_map, n_samples, offset)
local pos = self:shmem():atomic_get_int(0)
local buffer = self:shmem():to_int(1):array()
-- passthrough all data
ARDOUR.DSP.process_map (bufs, in_map, out_map, n_samples, offset, ARDOUR.DataType ("audio"))
ARDOUR.DSP.process_map (bufs, in_map, out_map, n_samples, offset, ARDOUR.DataType ("midi"))
-- then fill the event buffer
local ib = in_map:get (ARDOUR.DataType ("midi"), 0) -- index of 1st midi input
if ib ~= ARDOUR.ChanMapping.Invalid then
local events = bufs:get_midi (ib):table () -- copy event list into a lua table
-- iterate over all MIDI events
for _, e in pairs (events) do
local ev = e:buffer():array()
pos = pos % ringsize + 1
-- copy the data
for j = 1, math.min(e:size(),evlen) do
buffer[(pos-1)*evlen + j] = ev[j]
end
-- zero unused slots
for j = e:size()+1, evlen do
buffer[(pos-1)*evlen + j] = 0
end
end
end
self:shmem():atomic_set_int(0, pos)
self:queue_draw ()
end
local txt = nil -- a pango context
local cursize = 0
local hex = nil
local format_note = nil
local show_scm = nil
function format_note_name(b)
return string.format ("%5s", ARDOUR.ParameterDescriptor.midi_note_name (b))
end
function format_note_num(b)
return string.format (hex, b)
end
function show_midi(ctx, x, y, buffer, event)
local base = (event - 1) * evlen
if buffer[base+1] == -1 then return false end
local evtype = buffer[base + 1] >> 4
local channel = (buffer[base + 1] & 15) + 1 -- for System Common Messages this has no use
if evtype == 8 then
txt:set_text(string.format("%02u \u{2669}Off%s" .. hex, channel, format_note(buffer[base+2]), buffer[base+3]))
elseif evtype == 9 then
txt:set_text(string.format("%02u \u{2669}On %s" .. hex, channel, format_note(buffer[base+2]), buffer[base+3]))
elseif evtype == 10 then
txt:set_text(string.format("%02u \u{2669}KP %s" .. hex, channel, format_note(buffer[base+2]), buffer[base+3]))
elseif evtype == 11 then
txt:set_text(string.format("%02u CC " .. hex .. hex, channel, buffer[base+2], buffer[base+3]))
elseif evtype == 12 then
txt:set_text(string.format("%02u PRG " .. hex, channel, buffer[base+2]))
elseif evtype == 13 then
txt:set_text(string.format("%02u KP " .. hex, channel, buffer[base+2]))
elseif evtype == 14 then
txt:set_text(string.format("%02u PBnd" .. hex, channel, buffer[base+2] | buffer[base+3] << 7))
elseif show_scm > 0 then -- System Common Message
local message = buffer[base + 1] & 15
if message == 0 then
txt:set_text("-- SysEx")
elseif message == 1 then
txt:set_text(string.format("-- Time Code" .. hex, buffer[base+2]))
elseif message == 2 then
txt:set_text(string.format("-- Song Pos" .. hex, buffer[base+2] | buffer[base+3] << 7))
elseif message == 3 then
txt:set_text(string.format("-- Select Song" .. hex, buffer[base+2]))
elseif message == 6 then
txt:set_text("-- Tune Rq")
elseif message == 8 then
txt:set_text("-- Timing")
elseif message == 10 then
txt:set_text("-- Start")
elseif message == 11 then
txt:set_text("-- Continue")
elseif message == 12 then
txt:set_text("-- Stop")
elseif message == 14 then
txt:set_text("-- Active")
elseif message == 15 then
txt:set_text("-- Reset")
else
return false
end
else
return false
end
ctx:move_to (x, y)
txt:show_in_cairo_context (ctx)
return true
end
function render_inline (ctx, displaywidth, max_h)
local ctrl = CtrlPorts:array ()
local pos = self:shmem():atomic_get_int(0)
local buffer = self:shmem():to_int(1):array()
local count = ctrl[2]
if not txt or cursize ~= ctrl[1] then
cursize = math.floor(ctrl[1])
txt = Cairo.PangoLayout (ctx, "Mono " .. cursize)
end
if ctrl[3] > 0 then hex = " %02X" else hex = " %3u" end
show_scm = ctrl[4]
if ctrl[5] > 0 then
format_note = format_note_num
else
format_note = format_note_name
end
-- compute the size of the display
txt:set_text("0")
local _, lineheight = txt:get_pixel_size()
local displayheight = math.min(vpadding + (lineheight + vpadding) * count, max_h)
-- compute starting position (pango anchors text at north-west corner)
local x, y = hpadding, displayheight - lineheight - vpadding
-- clear background
ctx:rectangle (0, 0, displaywidth, displayheight)
ctx:set_source_rgba (.2, .2, .2, 1.0)
ctx:fill ()
-- color of latest event
ctx:set_source_rgba (1.0, 1.0, 1.0, 1.0)
-- print events
for i = pos, 1, -1 do
if y < 0 then break end
if show_midi(ctx, x, y, buffer, i) then
y = y - lineheight - vpadding
ctx:set_source_rgba (.8, .8, .8, 1.0)
end
end
for i = ringsize, pos+1, -1 do
if y < 0 then break end
if show_midi(ctx, x, y, buffer, i) then
y = y - lineheight - vpadding
ctx:set_source_rgba (.8, .8, .8, 1.0)
end
end
return {displaywidth, displayheight}
end
|