#!/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)