midiloop.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #!/usr/bin/env python3
  2. import mido
  3. from sys import stdout
  4. from pythonosc import udp_client
  5. # will spit exception when server unavaliable
  6. atem = udp_client.SimpleUDPClient("spass.local", 3333)
  7. amp = udp_client.SimpleUDPClient("pig.local", 9137)
  8. ovly = udp_client.SimpleUDPClient("xuj.local", 9137)
  9. msg_matrix = {
  10. # OVERLAY
  11. 0o00: (atem, "/atem/mini/preview", 1),
  12. 0o30: (ovly, "/party/screen/bar/t/reset", 0),
  13. # RETROTINK
  14. 0o01: (atem, "/atem/mini/preview", 2),
  15. 0o11: (amp, "/party/amp/input/dvd", 0),
  16. 0o21: (amp, "/party/amp/input/video", 0),
  17. 0o31: (amp, "/party/amp/input/tape", 0),
  18. 0o41: (amp, "/party/amp/input/cd", 0),
  19. 0o51: (amp, "/party/amp/vol/up", 0),
  20. 0o61: (amp, "/party/amp/vol/down", 0),
  21. 0o71: (amp, "/party/amp/power/on", 0),
  22. # 0o1: (amp, "/party/amp/power/off", 0),
  23. # CAMERA ZOOM
  24. 0o02: (atem, "/atem/mini/preview", 3),
  25. # CAMERA WIDE
  26. 0o03: (atem, "/atem/mini/preview", 4),
  27. # STILLS
  28. 0o04: (atem, "/atem/mini/preview", 3010),
  29. # BLACK
  30. 0o05: (atem, "/atem/mini/preview", 0),
  31. # PREVIEW / VIEW
  32. 0o06: (atem, "/atem/mini/transition/cut", 0),
  33. 0o16: (ovly, "/party/emu/xl/stop", 0),
  34. 0o26: (ovly, "/party/media/stop", 0),
  35. #
  36. 0o07: (atem, "/atem/mini/transition/auto", 0),
  37. 0o17: (atem, "/atem/mini/usk/1/on-air", 0),
  38. 0o27: (atem, "/atem/mini/usk/1/on-air", 1),
  39. # 0o17: (atem, "/atem/transition/type/dve", 0),
  40. # 0o27: (atem, "/atem/transition/type/dve", 1),
  41. 0o37: (atem, "/atem/mini/usk/1/type/dve", 0),
  42. 0o47: (atem, "/atem/mini/usk/1/type/dve", 1),
  43. 0o57: (atem, "/atem/mini/transition/type/dve", 1),
  44. 0o67: (atem, "/atem/mini/me/1/transition/dve/style", "pushbottom"),
  45. }
  46. audio_controls = {
  47. 48: "audio/input/1",
  48. 49: "audio/input/2",
  49. 50: "audio/input/3",
  50. 51: "audio/input/4",
  51. 52: "audio/input/1301",
  52. 53: "audio/input/1302",
  53. 54: "audio/output",
  54. }
  55. for i in range(7):
  56. msg_matrix[0o14+(i<<3)] = (atem, "/atem/mini/mplayer/1/still", i+1)
  57. def get_controller(device_name):
  58. """Select device and open for input control"""
  59. for device in mido.get_input_names():
  60. if device.rsplit(' ', 1)[0] == device_name:
  61. return (mido.open_input(device), mido.open_output(device))
  62. return None
  63. def get_float(v):
  64. return v * 258.01574 / 32768
  65. def event_loop(apc_in, apc_out):
  66. last = 0
  67. direction = 1
  68. while True:
  69. msg = apc_in.receive()
  70. if msg.type == "note_on" and msg_matrix.get(msg.note):
  71. osc, addr, value = msg_matrix[msg.note]
  72. osc.send_message(addr, value)
  73. print(msg, 'sent', value, 'to:', addr)
  74. # turn on led of pressed button and clear previous one for a feedback
  75. apc_out.send(mido.Message('note_on', channel=6, note=last, velocity=0))
  76. apc_out.send(mido.Message('note_on', channel=6, note=msg.note, velocity=5))
  77. last = msg.note
  78. if msg.type == "control_change" and msg.control == 56:
  79. # full range
  80. v = get_float(msg.value) * direction
  81. atem.send_message("/atem/mini/transition/position", abs(v))
  82. # atem.send_message("/atem/mini/transition/bar", 0.9999-v)
  83. if msg.value == 0:
  84. #direction *= -1
  85. atem.send_message("/atem/mini/transition/position", 0.9999999999)
  86. atem.send_message("/atem/mini/transition/cut", abs(v))
  87. print("fade", msg.value)
  88. if msg.type == "control_change" and msg.control == 55:
  89. # full range
  90. ovly.send_message("/party/media/volume", get_float(msg.value))
  91. elif msg.type == "control_change" and msg.control in audio_controls:
  92. # full range
  93. atem.send_message(f"/atem/mini/{audio_controls[msg.control]}/gain",
  94. get_float(msg.value) * 110. - 100.)
  95. else:
  96. print(msg)
  97. stdout.flush()
  98. if __name__ == "__main__":
  99. apc = get_controller('APC mini mk2:APC mini mk2 APC mini mk2 Contr')
  100. if not apc:
  101. print("MIDI Controller not found")
  102. exit(1)
  103. event_loop(*apc)