Freeze harvid/xjadeo PPC version
[ardour.git] / scripts / midimon.lua
index 9c8df8bf8c77681b332641557d37fed5853b9423..7f58fd34de74de8b38c21b566164d3fa1b13760e 100644 (file)
@@ -1,6 +1,6 @@
 ardour {
        ["type"]    = "dsp",
-       name        = "MIDI Monitor",
+       name        = "a-MIDI Monitor",
        category    = "Visualization",
        license     = "GPLv2",
        author      = "Ardour Team",
@@ -13,12 +13,9 @@ local evlen = 3
 local hpadding, vpadding = 4, 2
 
 function dsp_ioconfig ()
-       return { { audio_in = 0, audio_out = 0}, }
+       return { { midi_in = 1, midi_out = 1, audio_in = -1, audio_out = -1}, }
 end
 
-function dsp_has_midi_input () return true end
-function dsp_has_midi_output () return true end
-
 function dsp_params ()
        return
        {
@@ -37,7 +34,11 @@ function dsp_params ()
                { ["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 }
+                       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
 
@@ -53,23 +54,32 @@ function dsp_init (rate)
        end
 end
 
-function dsp_run (_, _, n_samples)
-       assert (type(midiin) == "table")
-       assert (type(midiout) == "table")
-
+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 midi data, and fill the event buffer
-       for i, d in pairs(midiin) do
-               local ev = d["data"]
-               midiout[i] = { time = d["time"], data = ev }
-               pos = pos % ringsize + 1
-               for j = 1, math.min(#ev,evlen) do
-                       buffer[(pos-1)*evlen + j] = ev[j]
-               end
-               for j = #ev+1, evlen do
-                       buffer[(pos-1)*evlen + j] = 0
+       -- 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
 
@@ -81,19 +91,29 @@ 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 end
+       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" .. hex .. hex, channel, buffer[base+2], buffer[base+3]))
+               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 " .. hex .. hex, channel, buffer[base+2], buffer[base+3]))
+               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 " .. hex .. hex, channel, buffer[base+2], buffer[base+3]))
+               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
@@ -126,10 +146,15 @@ function show_midi(ctx, x, y, buffer, event)
                        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)
@@ -143,9 +168,15 @@ function render_inline (ctx, displaywidth, max_h)
                txt = Cairo.PangoLayout (ctx, "Mono " .. cursize)
        end
 
-       if ctrl[3] > 0 then hex = " %2X" else hex = " %3u" 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()
@@ -159,22 +190,23 @@ function render_inline (ctx, displaywidth, max_h)
        ctx:set_source_rgba (.2, .2, .2, 1.0)
        ctx:fill ()
 
-       -- print latest event
+       -- color of latest event
        ctx:set_source_rgba (1.0, 1.0, 1.0, 1.0)
-       show_midi(ctx, x, y, buffer, pos)
-       y = y - lineheight - vpadding
 
-       -- and remaining events
-       ctx:set_source_rgba (.8, .8, .8, 1.0)
-       for i = pos-1, 1, -1 do
+       -- print events
+       for i = pos, 1, -1 do
                if y < 0 then break end
-               show_midi(ctx, x, y, buffer, i)
-               y = y - lineheight - vpadding
+               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
-               show_midi(ctx, x, y, buffer, i)
-               y = y - lineheight - vpadding
+               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}