diff options
author | Robin Gareus <robin@gareus.org> | 2020-02-23 20:48:02 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2020-02-23 20:48:02 +0100 |
commit | 180843f9bd28b191c7404245ba0a121107992511 (patch) | |
tree | c60312dc09f76c2f55ba2383245c427e15c38dea /share/scripts/midimon.lua | |
parent | bf649cd68ad46c34a656700aa6cb89416d648c64 (diff) |
Also move Lua scripts to share subfolder
Diffstat (limited to 'share/scripts/midimon.lua')
-rw-r--r-- | share/scripts/midimon.lua | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/share/scripts/midimon.lua b/share/scripts/midimon.lua new file mode 100644 index 0000000000..7f58fd34de --- /dev/null +++ b/share/scripts/midimon.lua @@ -0,0 +1,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 |