{===========================} { channel router } { by SzcZ (c) 2014 } { www.fairlyconfusing.net } {===========================} on init set_script_title("Channel router") set_ui_height_px(110) message(" ") {--- declare calculation variables} {-----------------} declare $count declare $count2 declare $head declare $end declare $value declare $route_pass declare $check declare $new declare $out_port_old {--- declare gui positioning coordinates} {-----------------} declare const $width := 30 declare const $spacing := 36 declare const $spacing_y := 25 declare const $x_pos := 60 declare const $y_pos := 5 {--- declare engine variables} {-----------------} declare %map[16] declare $solo_ch {number of channel to route to} %map[0] := 1 {--- GUI controls} {-----------------} declare ui_switch $c00 declare ui_switch $c01 declare ui_switch $c02 declare ui_switch $c03 declare ui_switch $c04 declare ui_switch $c05 declare ui_switch $c06 declare ui_switch $c07 declare ui_switch $c08 declare ui_switch $c09 declare ui_switch $c10 declare ui_switch $c11 declare ui_switch $c12 declare ui_switch $c13 declare ui_switch $c14 declare ui_switch $c15 $c00 := 1 set_control_par(get_ui_id($c00),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c01),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c02),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c03),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c04),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c05),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c06),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c07),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c08),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c09),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c10),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c11),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c12),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c13),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c14),$CONTROL_PAR_WIDTH,$width) set_control_par(get_ui_id($c15),$CONTROL_PAR_WIDTH,$width) move_control_px($c00, $x_pos + $spacing *0, $y_pos) move_control_px($c01, $x_pos + $spacing *1, $y_pos) move_control_px($c02, $x_pos + $spacing *2, $y_pos) move_control_px($c03, $x_pos + $spacing *3, $y_pos) move_control_px($c04, $x_pos + $spacing *4, $y_pos) move_control_px($c05, $x_pos + $spacing *5, $y_pos) move_control_px($c06, $x_pos + $spacing *6, $y_pos) move_control_px($c07, $x_pos + $spacing *7, $y_pos) move_control_px($c08, $x_pos + $spacing *8, $y_pos) move_control_px($c09, $x_pos + $spacing *9, $y_pos) move_control_px($c10, $x_pos + $spacing *10, $y_pos) move_control_px($c11, $x_pos + $spacing *11, $y_pos) move_control_px($c12, $x_pos + $spacing *12, $y_pos) move_control_px($c13, $x_pos + $spacing *13, $y_pos) move_control_px($c14, $x_pos + $spacing *14, $y_pos) move_control_px($c15, $x_pos + $spacing *15, $y_pos) set_text ($c00,"c01") set_text ($c01,"c02") set_text ($c02,"c03") set_text ($c03,"c04") set_text ($c04,"c05") set_text ($c05,"c06") set_text ($c06,"c07") set_text ($c07,"c08") set_text ($c08,"c09") set_text ($c09,"c10") set_text ($c10,"c11") set_text ($c11,"c12") set_text ($c12,"c13") set_text ($c13,"c14") set_text ($c14,"c15") set_text ($c15,"c16") declare ui_menu $mode add_menu_item ($mode, "single channel",1) add_menu_item ($mode, "multi channel",2) set_control_par(get_ui_id($mode),$CONTROL_PAR_WIDTH,$spacing *3 -6) move_control_px($mode, $x_pos + $spacing *2, $y_pos + $spacing_y) declare ui_menu $in_port add_menu_item ($in_port, "input: any port",-1) add_menu_item ($in_port, "input: port A",0) add_menu_item ($in_port, "input: port B",1) add_menu_item ($in_port, "input: port C",2) add_menu_item ($in_port, "input: port D",3) set_control_par(get_ui_id($in_port),$CONTROL_PAR_WIDTH,$spacing *3 -6) move_control_px($in_port, $x_pos + $spacing *5, $y_pos + $spacing_y) declare ui_menu $in_aut add_menu_item ($in_aut, "any port",-1) add_menu_item ($in_aut, "port A",0) add_menu_item ($in_aut, "port B",1) add_menu_item ($in_aut, "port C",2) add_menu_item ($in_aut, "port D",3) set_control_par(get_ui_id($in_aut),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($in_aut, $x_pos + $spacing *5, $y_pos + $spacing_y *2) declare ui_menu $out_port add_menu_item ($out_port, "output: port A",0) add_menu_item ($out_port, "output: port B",1) add_menu_item ($out_port, "output: port C",2) add_menu_item ($out_port, "output: port D",3) set_control_par(get_ui_id($out_port),$CONTROL_PAR_WIDTH,$spacing *3 -6) move_control_px($out_port, $x_pos + $spacing *11, $y_pos + $spacing_y) declare ui_menu $in_ch add_menu_item ($in_ch, "input: any channel",-1) add_menu_item ($in_ch, "input: channel 1",0) add_menu_item ($in_ch, "input: channel 2",1 ) add_menu_item ($in_ch, "input: channel 3",2 ) add_menu_item ($in_ch, "input: channel 4",3 ) add_menu_item ($in_ch, "input: channel 5",4 ) add_menu_item ($in_ch, "input: channel 6",5 ) add_menu_item ($in_ch, "input: channel 7",6 ) add_menu_item ($in_ch, "input: channel 8",7 ) add_menu_item ($in_ch, "input: channel 9",8 ) add_menu_item ($in_ch, "input: channel 10",9 ) add_menu_item ($in_ch, "input: channel 11",10) add_menu_item ($in_ch, "input: channel 12",11) add_menu_item ($in_ch, "input: channel 13",12) add_menu_item ($in_ch, "input: channel 14",13) add_menu_item ($in_ch, "input: channel 15",14) add_menu_item ($in_ch, "input: channel 16",15) set_control_par(get_ui_id($in_ch),$CONTROL_PAR_WIDTH,$spacing *3 -6) move_control_px($in_ch, $x_pos + $spacing *8, $y_pos + $spacing_y) declare ui_menu $in_ach add_menu_item ($in_ach, "any chan.",-1) add_menu_item ($in_ach, "channel 1",0) add_menu_item ($in_ach, "channel 2",1 ) add_menu_item ($in_ach, "channel 3",2 ) add_menu_item ($in_ach, "channel 4",3 ) add_menu_item ($in_ach, "channel 5",4 ) add_menu_item ($in_ach, "channel 6",5 ) add_menu_item ($in_ach, "channel 7",6 ) add_menu_item ($in_ach, "channel 8",7 ) add_menu_item ($in_ach, "channel 9",8 ) add_menu_item ($in_ach, "channel 10",9 ) add_menu_item ($in_ach, "channel 11",10) add_menu_item ($in_ach, "channel 12",11) add_menu_item ($in_ach, "channel 13",12) add_menu_item ($in_ach, "channel 14",13) add_menu_item ($in_ach, "channel 15",14) add_menu_item ($in_ach, "channel 16",15) set_control_par(get_ui_id($in_ach),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($in_ach, $x_pos + $spacing *7, $y_pos + $spacing_y *2) declare ui_label $monitor (1,1) set_control_par(get_ui_id($monitor),$CONTROL_PAR_WIDTH,$spacing *7 -6) move_control_px($monitor, $x_pos + $spacing *0, $y_pos + $spacing_y *3) set_text ($monitor,"Channel router www.fairlyconfusing.net") declare ui_label $info_r (1,1) set_control_par(get_ui_id($info_r),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($info_r, $x_pos + $spacing *0, $y_pos + $spacing_y) set_text ($info_r,"routing:") declare ui_label $info_a (1,1) set_control_par(get_ui_id($info_a),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($info_a, $x_pos + $spacing *0, $y_pos + $spacing_y *2) set_text ($info_a,"automation:") declare ui_label $info_v (1,1) set_control_par(get_ui_id($info_v),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($info_v, $x_pos + $spacing *14, $y_pos + $spacing_y *3) set_text ($info_v," version 1") declare ui_menu $auto add_menu_item ($auto, "use keys",0) add_menu_item ($auto, "use multi CC",1) add_menu_item ($auto, "use single CC",2) add_menu_item ($auto, "no automation",-1) set_control_par(get_ui_id($auto),$CONTROL_PAR_WIDTH,$spacing *3 -6) move_control_px($auto, $x_pos + $spacing *2, $y_pos + $spacing_y *2) declare ui_value_edit $start_from(0,110,1) set_control_par(get_ui_id($start_from),$CONTROL_PAR_WIDTH,$spacing *3 -6) move_control_px($start_from, $x_pos + $spacing *9, $y_pos + $spacing_y *2) declare ui_switch $learn set_control_par(get_ui_id($learn),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($learn, $x_pos + $spacing *12, $y_pos + $spacing_y *2) declare ui_value_edit $size(2,16,1) set_control_par(get_ui_id($size),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($size, $x_pos + $spacing *14, $y_pos + $spacing_y *2) $size := 16 declare ui_switch $clear set_control_par(get_ui_id($clear),$CONTROL_PAR_WIDTH,$spacing *2 -6) move_control_px($clear, $x_pos + $spacing *14, $y_pos + $spacing_y) set_text ($clear,"clear matrix") {--- save values} {-----------------} make_persistent ($c00) make_persistent ($c01) make_persistent ($c02) make_persistent ($c03) make_persistent ($c04) make_persistent ($c05) make_persistent ($c06) make_persistent ($c07) make_persistent ($c08) make_persistent ($c09) make_persistent ($c10) make_persistent ($c11) make_persistent ($c12) make_persistent ($c13) make_persistent ($c14) make_persistent ($c15) make_persistent (%map) make_persistent ($solo_ch) make_persistent ($mode) make_persistent ($auto) make_persistent ($start_from) make_persistent ($size) make_persistent ($in_port) make_persistent ($out_port) make_persistent ($in_ch) make_persistent ($in_ach) make_persistent ($in_aut) {--- sync} {-----------------} read_persistent_var ($out_port) $out_port_old := $out_port {--- help} {-----------------} set_control_help($mode,"Single channel mode: route data to selected channel. Multi channel mode: route data multiple channels.") set_control_help($auto,"Select means of automation. You can automate channel matrix with keys, which will toggle switches on and off; multi CC - series of CC controllers, one controller per switch, turns it on and off; single CC - use one controller to select output channel, which is only useful in single channel mode.") set_control_help($in_port,"Select input port for routing, if you select specific port, other port will be unaffected.") set_control_help($in_aut,"Select input port for automation, if you select specific port, only data from this port will be used for automation.") set_control_help($in_ch,"Select MIDI channel for routing, if you pick a channel, data on other channels will be unaffected.") set_control_help($in_ach,"Select MIDI channel for automation, if you pick a channel, only data from this channel will be used for automation.") set_control_help($start_from,"Pick the number for the first key or controller to use for automation. Selected key/controller will automate first channel switch in the matrix. Following keys/controllers will be used to the rest of matrix switches, according to 'size' setting.") set_control_help($learn,"MIDI learn button for 'start_from' setting.") set_control_help($size,"Set how many keys/controllers use for automation. Those assigned for automation are blocked, so if you don't need to automate all 16 channels, you can free some of keys/controllers.") set_control_help($clear,"Reset channel matrix.") end on {-----------------} { functions } {-----------------} function clear_switches $c00 := 0 $c01 := 0 $c02 := 0 $c03 := 0 $c04 := 0 $c05 := 0 $c06 := 0 $c07 := 0 $c08 := 0 $c09 := 0 $c10 := 0 $c11 := 0 $c12 := 0 $c13 := 0 $c14 := 0 $c15 := 0 end function function multi_switches $c00 := %map[00] $c01 := %map[01] $c02 := %map[02] $c03 := %map[03] $c04 := %map[04] $c05 := %map[05] $c06 := %map[06] $c07 := %map[07] $c08 := %map[08] $c09 := %map[09] $c10 := %map[10] $c11 := %map[11] $c12 := %map[12] $c13 := %map[13] $c14 := %map[14] $c15 := %map[15] end function function set_switches select ($solo_ch) case 0 $c00 := 1 case 1 $c01 := 1 case 2 $c02 := 1 case 3 $c03 := 1 case 4 $c04 := 1 case 5 $c05 := 1 case 6 $c06 := 1 case 7 $c07 := 1 case 8 $c08 := 1 case 9 $c09 := 1 case 10 $c10 := 1 case 11 $c11 := 1 case 12 $c12 := 1 case 13 $c13 := 1 case 14 $c14 := 1 case 15 $c15 := 1 end select end function function get_value select ($head) case 0 $value := $c00 case 1 $value := $c01 case 2 $value := $c02 case 3 $value := $c03 case 4 $value := $c04 case 5 $value := $c05 case 6 $value := $c06 case 7 $value := $c07 case 8 $value := $c08 case 9 $value := $c09 case 10 $value := $c10 case 11 $value := $c11 case 12 $value := $c12 case 13 $value := $c13 case 14 $value := $c14 case 15 $value := $c15 end select $value := ($value +1) mod 2 end function function set_value select ($head) case 0 $c00 := $value case 1 $c01 := $value case 2 $c02 := $value case 3 $c03 := $value case 4 $c04 := $value case 5 $c05 := $value case 6 $c06 := $value case 7 $c07 := $value case 8 $c08 := $value case 9 $c09 := $value case 10 $c10 := $value case 11 $c11 := $value case 12 $c12 := $value case 13 $c13 := $value case 14 $c14 := $value case 15 $c15 := $value end select end function {send note off to a channel} function notes_off $count2 := $out_port *16 $count := 0 while ($count < 128) set_midi($end + $count2,$MIDI_COMMAND_NOTE_OFF,$count,0) inc($count) end while end function function multi_notes_off $end := 0 while ($end < 16) if(%map[$end] =1) call notes_off end if inc($end) end while end function function set_notes_off select($mode) case 1 $end := $solo_ch call notes_off case 2 call multi_notes_off end select end function {process switches} function handle_switches select($mode) case 1 call clear_switches $end := $solo_ch $solo_ch := $head $value := 1 call notes_off case 2 %map[$head] := $value if($value =0) $end := $head call notes_off end if end select end function {----------------------------} { process incoming midi data } {----------------------------} on midi_in $route_pass := 1 {display incoming data} $count := $MIDI_CHANNEL /16 select ($count) case 0 set_text ($monitor,"incoming: port A, channel " & $MIDI_CHANNEL mod 16 +1 & ", data " & $MIDI_COMMAND & ", " & $MIDI_BYTE_1 & ", " & $MIDI_BYTE_2) case 1 set_text ($monitor,"incoming: port B, channel " & $MIDI_CHANNEL mod 16 +1 &", data " & $MIDI_COMMAND & ", " & $MIDI_BYTE_1 & ", " & $MIDI_BYTE_2) case 2 set_text ($monitor,"incoming: port C, channel " & $MIDI_CHANNEL mod 16 +1 &", data " & $MIDI_COMMAND & ", " & $MIDI_BYTE_1 & ", " & $MIDI_BYTE_2) case 3 set_text ($monitor,"incoming: port D, channel " & $MIDI_CHANNEL mod 16 +1 &", data " & $MIDI_COMMAND & ", " & $MIDI_BYTE_1 & ", " & $MIDI_BYTE_2) end select {check if incoming data matches automation input settings} $check := 0 if($in_aut = -1) if($in_ach = -1) $check := 1 else if($MIDI_CHANNEL mod 16 = $in_ach) $check := 1 end if end if else if($in_ach = -1 and $in_aut = $MIDI_CHANNEL /16) $check := 1 else if($MIDI_CHANNEL mod 16 = $in_ach and $in_aut = $MIDI_CHANNEL /16) $check := 1 end if end if end if if($check =1) {learn functionality} if($learn =1) select ($auto) case 0 if ($MIDI_COMMAND = $MIDI_COMMAND_NOTE_ON) $learn := 0 $start_from := $MIDI_BYTE_1 ignore_midi $route_pass := 0 end if case 1 to 2 if ($MIDI_COMMAND = $MIDI_COMMAND_CC) $learn := 0 $start_from := $MIDI_BYTE_1 ignore_midi $route_pass := 0 end if end select end if {automation functionality} select($auto) case 0 {keyboard automation} if ($MIDI_COMMAND = $MIDI_COMMAND_NOTE_ON and $MIDI_BYTE_2 #0) if(in_range($MIDI_BYTE_1,$start_from,$start_from + $size -1)) $head := $MIDI_BYTE_1 - $start_from call get_value call handle_switches call set_value ignore_midi $route_pass := 0 end if end if case 1 {multi CC automation} if ($MIDI_COMMAND = $MIDI_COMMAND_CC) if(in_range($MIDI_BYTE_1,$start_from,$start_from + $size -1)) $head := $MIDI_BYTE_1 - $start_from $value := $MIDI_BYTE_2 /64 call handle_switches call set_value ignore_midi $route_pass := 0 end if end if case 2 {single CC automation} if ($MIDI_COMMAND = $MIDI_COMMAND_CC) if($MIDI_BYTE_1 = $start_from) $head := $MIDI_BYTE_2 /8 call get_value call handle_switches call set_value ignore_midi $route_pass := 0 end if end if end select end if {check if incoming data matches routing input settings} $check := 0 if($in_port = -1) if($in_ch = -1) $check := 1 else if($MIDI_CHANNEL mod 16 = $in_ch) $check := 1 end if end if else if($in_ch = -1 and $in_port = $MIDI_CHANNEL /16) $check := 1 else if($MIDI_CHANNEL mod 16 = $in_ch and $in_port = $MIDI_CHANNEL /16) $check := 1 end if end if end if if($check =1) {routing functionality} if($route_pass = 1) $head := $out_port *16 select($mode) case 1 set_event_par($EVENT_ID,$EVENT_PAR_MIDI_CHANNEL,$solo_ch + $head) case 2 ignore_midi $count := 0 while ($count < 16) if(%map[$count] =1) set_midi($count + $head,$MIDI_COMMAND,$MIDI_BYTE_1,$MIDI_BYTE_2) end if inc ($count) end while end select end if end if end on {-------------------} { GUI controls } {-------------------} { mode switch } on ui_control ($mode) select($mode) case 1 call multi_notes_off call clear_switches call set_switches case 2 $end := $solo_ch call notes_off call multi_switches end select end on on ui_control ($clear) call set_notes_off select($mode) case 1 $solo_ch := 0 call clear_switches call set_switches case 2 $count := 1 while ($count < 16) %map[$count] := 0 inc($count) end while %map[0] := 1 call multi_switches end select $clear := 0 end on on ui_control ($out_port) $new := $out_port $out_port := $out_port_old call set_notes_off $out_port := $new $out_port_old := $new end on on ui_control ($in_port) call set_notes_off end on on ui_control ($in_ch) call set_notes_off end on {switches functionality} on ui_control ($c00) $head := 0 $value := $c00 call handle_switches $c00 := $value end on on ui_control ($c01) $head := 1 $value := $c01 call handle_switches $c01 := $value end on on ui_control ($c02) $head := 2 $value := $c02 call handle_switches $c02 := $value end on on ui_control ($c03) $head := 3 $value := $c03 call handle_switches $c03 := $value end on on ui_control ($c04) $head := 4 $value := $c04 call handle_switches $c04 := $value end on on ui_control ($c05) $head := 5 $value := $c05 call handle_switches $c05 := $value end on on ui_control ($c06) $head := 6 $value := $c06 call handle_switches $c06 := $value end on on ui_control ($c07) $head := 7 $value := $c07 call handle_switches $c07 := $value end on on ui_control ($c08) $head := 8 $value := $c08 call handle_switches $c08 := $value end on on ui_control ($c09) $head := 9 $value := $c09 call handle_switches $c09 := $value end on on ui_control ($c10) $head := 10 $value := $c10 call handle_switches $c10 := $value end on on ui_control ($c11) $head := 11 $value := $c11 call handle_switches $c11 := $value end on on ui_control ($c12) $head := 12 $value := $c12 call handle_switches $c12 := $value end on on ui_control ($c13) $head := 13 $value := $c13 call handle_switches $c13 := $value end on on ui_control ($c14) $head := 14 $value := $c14 call handle_switches $c14 := $value end on on ui_control ($c15) $head := 15 $value := $c15 call handle_switches $c15 := $value end on