i’ve just got some code working that emulates the midifighter 4bank mode. the code might not be any use to anyone but the logic and note info in it might be.
the function:
any2mf_4banks_map = {
["select"] = {
["0,0"] = { ["note"] = "C-1", ["bank"] = 1 },
["1,0"] = { ["note"] = "C#-1", ["bank"] = 2 },
["2,0"] = { ["note"] = "D-1", ["bank"] = 3 },
["3,0"] = { ["note"] = "D#-1", ["bank"] = 4 }
},
["banks"] = {
{
["0,1"] = "G#2", ["1,1"] = "A2", ["2,1"] = "A#2", ["3,1"] = "B2",
["0,2"] = "E2", ["1,2"] = "F2", ["2,2"] = "F#2", ["3,2"] = "G2",
["0,3"] = "C2", ["1,3"] = "C#2", ["2,3"] = "D2", ["3,3"] = "D#2"
},
{
["0,1"] = "G#3", ["1,1"] = "A3", ["2,1"] = "A#3", ["3,1"] = "B3",
["0,2"] = "E3", ["1,2"] = "F3", ["2,2"] = "F#3", ["3,2"] = "G3",
["0,3"] = "C3", ["1,3"] = "C#3", ["2,3"] = "D3", ["3,3"] = "D#3"
},
{
["0,1"] = "G#4", ["1,1"] = "A4", ["2,1"] = "A#4", ["3,1"] = "B4",
["0,2"] = "E4", ["1,2"] = "F4", ["2,2"] = "F#4", ["3,2"] = "G4",
["0,3"] = "C4", ["1,3"] = "C#4", ["2,3"] = "D4", ["3,3"] = "D#4"
},
{
["0,1"] = "G#5", ["1,1"] = "A5", ["2,1"] = "A#5", ["3,1"] = "B5",
["0,2"] = "E5", ["1,2"] = "F5", ["2,2"] = "F#5", ["3,2"] = "G5",
["0,3"] = "C5", ["1,3"] = "C#5", ["2,3"] = "D5", ["3,3"] = "D#5"
}
}
}
-- map mf notes back to our surface
mf2any_4banks_map = {}
for k,v in pairs(any2mf_4banks_map["select"]) do
mf2any_4banks_map[v["note"]] = k
for k2, v2 in ipairs(any2mf_4banks_map["banks"]) do
for k3, v3 in pairs(any2mf_4banks_map["banks"][k2]) do
mf2any_4banks_map[v3] = k3
end
end
end
mf_4banks_curr_bank = {}
function create_midifighter_4banks(rdev, rdevpage, vdev, off_color, on_color)
-- set our current bank to 1
local mf_4banks_id = #mf_4banks_curr_bank + 1
mf_4banks_curr_bank[mf_4banks_id] = 1
for x=0,3 do
for y=0,3 do
btn = y..","..x
-- init off color
send_event(rdev, btn, off_color)
-- map input to the virtual midifighter
capture_event(rdev, btn, rdevpage, function(d, e, p, v)
local curr_bank = mf_4banks_curr_bank[mf_4banks_id];
if any2mf_4banks_map["select"][e] ~= nil then
-- save bank number and send message out to virtual mf
mf_4banks_curr_bank[mf_4banks_id] = any2mf_4banks_map["select"][e]["bank"]
send_event(vdev, any2mf_4banks_map["select"][e]["note"], v, 3)
elseif any2mf_4banks_map["banks"][curr_bank][e] ~= nil then
-- send the message out from a multi bank row (2,3,4)
send_event(vdev, any2mf_4banks_map["banks"][curr_bank][e], v, 3)
end
end)
-- route mf input back to real surface
capture_event(vdev, any2mf_map[btn], 0, function(d, e, p, v)
if mf2any_4banks_map[e] ~= nil then
if v == 0 then
send_event(rdev, mf2any_4banks_map[e], off_color)
else
send_event(rdev, mf2any_4banks_map[e], on_color)
end
end
end)
end
end
end
then i just use these lines to set it up using lo red for off and green for lit up leds:
open_midi_device("traktor", "traktor", "Traktor Output", "Traktor Input");
open_midi_device("launchpad", "launchpad", "Launchpad", "Launchpad", 8)
open_midi_device("midifighter", "midifighter", "MidiFighter Input", "MidiFighter Output")
create_midifighter_4banks("launchpad", 0, "midifighter", lp_lo_red, lp_hi_green)
seems to work ok - but it’s going to take me a while to understand this midifighter IG mapping 
the plan is to add the ability to offset the virtual fighters and then have 2 normal mode MF’ers and two 4bank mode MF’ers on one launchpad page.
edit: the code looks a bit complicated but 99% of it is run at startup time - only small snippets of code (the functions passed to capture_event()) actually get run when a button is pressed or traktor sends an event.