|
@@ -0,0 +1,121 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+
|
|
|
+import mido
|
|
|
+from sys import stdout
|
|
|
+from pythonosc import udp_client
|
|
|
+
|
|
|
+# will spit exception when server unavaliable
|
|
|
+atem = udp_client.SimpleUDPClient("spass.local", 3333)
|
|
|
+amp = udp_client.SimpleUDPClient("pig.local", 9137)
|
|
|
+ovly = udp_client.SimpleUDPClient("xuj.local", 9137)
|
|
|
+
|
|
|
+msg_matrix = {
|
|
|
+ # OVERLAY
|
|
|
+ 0o00: (atem, "/atem/mini/preview", 1),
|
|
|
+ 0o30: (ovly, "/party/screen/bar/t/reset", 0),
|
|
|
+
|
|
|
+ # RETROTINK
|
|
|
+ 0o01: (atem, "/atem/mini/preview", 2),
|
|
|
+ 0o11: (amp, "/party/amp/input/dvd", 0),
|
|
|
+ 0o21: (amp, "/party/amp/input/video", 0),
|
|
|
+ 0o31: (amp, "/party/amp/input/tape", 0),
|
|
|
+ 0o41: (amp, "/party/amp/input/cd", 0),
|
|
|
+ 0o51: (amp, "/party/amp/vol/up", 0),
|
|
|
+ 0o61: (amp, "/party/amp/vol/down", 0),
|
|
|
+ 0o71: (amp, "/party/amp/power/on", 0),
|
|
|
+ # 0o1: (amp, "/party/amp/power/off", 0),
|
|
|
+
|
|
|
+ # CAMERA ZOOM
|
|
|
+ 0o02: (atem, "/atem/mini/preview", 3),
|
|
|
+
|
|
|
+ # CAMERA WIDE
|
|
|
+ 0o03: (atem, "/atem/mini/preview", 4),
|
|
|
+
|
|
|
+ # STILLS
|
|
|
+ 0o04: (atem, "/atem/mini/preview", 3010),
|
|
|
+
|
|
|
+ # BLACK
|
|
|
+ 0o05: (atem, "/atem/mini/preview", 0),
|
|
|
+
|
|
|
+ # PREVIEW / VIEW
|
|
|
+ 0o06: (atem, "/atem/mini/transition/cut", 0),
|
|
|
+ 0o16: (ovly, "/party/emu/xl/stop", 0),
|
|
|
+ 0o26: (ovly, "/party/media/stop", 0),
|
|
|
+
|
|
|
+ #
|
|
|
+ 0o07: (atem, "/atem/mini/transition/auto", 0),
|
|
|
+
|
|
|
+ 0o17: (atem, "/atem/mini/usk/1/on-air", 0),
|
|
|
+ 0o27: (atem, "/atem/mini/usk/1/on-air", 1),
|
|
|
+ # 0o17: (atem, "/atem/transition/type/dve", 0),
|
|
|
+ # 0o27: (atem, "/atem/transition/type/dve", 1),
|
|
|
+ 0o37: (atem, "/atem/mini/usk/1/type/dve", 0),
|
|
|
+ 0o47: (atem, "/atem/mini/usk/1/type/dve", 1),
|
|
|
+ 0o57: (atem, "/atem/mini/transition/type/dve", 1),
|
|
|
+ 0o67: (atem, "/atem/mini/me/1/transition/dve/style", "pushbottom"),
|
|
|
+}
|
|
|
+
|
|
|
+audio_controls = {
|
|
|
+ 48: "audio/input/1",
|
|
|
+ 49: "audio/input/2",
|
|
|
+ 50: "audio/input/3",
|
|
|
+ 51: "audio/input/4",
|
|
|
+ 52: "audio/input/1301",
|
|
|
+ 53: "audio/input/1302",
|
|
|
+ 54: "audio/output",
|
|
|
+}
|
|
|
+for i in range(7):
|
|
|
+ msg_matrix[0o14+(i<<3)] = (atem, "/atem/mini/mplayer/1/still", i+1)
|
|
|
+
|
|
|
+def get_controller(device_name):
|
|
|
+ """Select device and open for input control"""
|
|
|
+ for device in mido.get_input_names():
|
|
|
+ if device.rsplit(' ', 1)[0] == device_name:
|
|
|
+ return (mido.open_input(device), mido.open_output(device))
|
|
|
+ return None
|
|
|
+
|
|
|
+def get_float(v):
|
|
|
+ return v * 258.01574 / 32768
|
|
|
+
|
|
|
+def event_loop(apc_in, apc_out):
|
|
|
+ last = 0
|
|
|
+ direction = 1
|
|
|
+ while True:
|
|
|
+ msg = apc_in.receive()
|
|
|
+ if msg.type == "note_on" and msg_matrix.get(msg.note):
|
|
|
+ osc, addr, value = msg_matrix[msg.note]
|
|
|
+ osc.send_message(addr, value)
|
|
|
+ print(msg, 'sent', value, 'to:', addr)
|
|
|
+
|
|
|
+ # turn on led of pressed button and clear previous one for a feedback
|
|
|
+ apc_out.send(mido.Message('note_on', channel=6, note=last, velocity=0))
|
|
|
+ apc_out.send(mido.Message('note_on', channel=6, note=msg.note, velocity=5))
|
|
|
+ last = msg.note
|
|
|
+ if msg.type == "control_change" and msg.control == 56:
|
|
|
+ # full range
|
|
|
+ v = get_float(msg.value) * direction
|
|
|
+ atem.send_message("/atem/mini/transition/position", abs(v))
|
|
|
+ # atem.send_message("/atem/mini/transition/bar", 0.9999-v)
|
|
|
+ if msg.value == 0:
|
|
|
+ #direction *= -1
|
|
|
+ atem.send_message("/atem/mini/transition/position", 0.9999999999)
|
|
|
+ atem.send_message("/atem/mini/transition/cut", abs(v))
|
|
|
+ print("fade", msg.value)
|
|
|
+ if msg.type == "control_change" and msg.control == 55:
|
|
|
+ # full range
|
|
|
+ ovly.send_message("/party/media/volume", get_float(msg.value))
|
|
|
+ elif msg.type == "control_change" and msg.control in audio_controls:
|
|
|
+ # full range
|
|
|
+ atem.send_message(f"/atem/mini/{audio_controls[msg.control]}/gain",
|
|
|
+ get_float(msg.value) * 110. - 100.)
|
|
|
+ else:
|
|
|
+ print(msg)
|
|
|
+ stdout.flush()
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ apc = get_controller('APC mini mk2:APC mini mk2 APC mini mk2 Contr')
|
|
|
+ if not apc:
|
|
|
+ print("MIDI Controller not found")
|
|
|
+ exit(1)
|
|
|
+
|
|
|
+ event_loop(*apc)
|