From 0319be21855f9c9f4d618552ddde2a852d56869a Mon Sep 17 00:00:00 2001
From: Florian Zeitz <florob@babelmonkeys.de>
Date: Tue, 16 Aug 2016 01:57:01 +0200
Subject: Add voctomidi for controlling voctocore via MIDI

---
 example-scripts/voctomidi/README.md          | 10 ++++
 example-scripts/voctomidi/default-config.ini | 19 ++++++
 example-scripts/voctomidi/lib/config.py      | 16 ++++++
 example-scripts/voctomidi/voctomidi.py       | 86 ++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+)
 create mode 100644 example-scripts/voctomidi/README.md
 create mode 100644 example-scripts/voctomidi/default-config.ini
 create mode 100644 example-scripts/voctomidi/lib/config.py
 create mode 100755 example-scripts/voctomidi/voctomidi.py

(limited to 'example-scripts/voctomidi')

diff --git a/example-scripts/voctomidi/README.md b/example-scripts/voctomidi/README.md
new file mode 100644
index 0000000..b171f8a
--- /dev/null
+++ b/example-scripts/voctomidi/README.md
@@ -0,0 +1,10 @@
+# Voctomidi - Control Voctocore from a MIDI controller
+
+## Configuration
+Set the `device` option in the `midi` section to the device
+you want to connect to. This can be either a device name, or port.
+If this is unset or the device can't be found a list of connected devices will
+be provided for you to choose from.
+
+In the `eventmap` section MIDI NOTE ON events are mapped to Voctocore layouts.
+The syntax is `<note>=<srcA> <srcB> <mode>`.
diff --git a/example-scripts/voctomidi/default-config.ini b/example-scripts/voctomidi/default-config.ini
new file mode 100644
index 0000000..8e68bf3
--- /dev/null
+++ b/example-scripts/voctomidi/default-config.ini
@@ -0,0 +1,19 @@
+[server]
+host=localhost
+
+[midi]
+device=nanoPAD
+
+# nanoPAD Layout:
+#   Scene 1:
+#     39, 48, 45, 43, 51, 49,
+#     36, 38, 40, 42, 44, 46
+[eventmap]
+39=grabber cam1 side_by_side_preview
+48=grabber cam2 side_by_side_preview
+45=grabber cam1 side_by_side_equal
+43=grabber cam2 side_by_side_equal
+51=cam1 cam2 side_by_side_equal
+36=cam1 * fullscreen
+38=cam2 * fullscreen
+40=grabber * fullscreen
diff --git a/example-scripts/voctomidi/lib/config.py b/example-scripts/voctomidi/lib/config.py
new file mode 100644
index 0000000..44dd8da
--- /dev/null
+++ b/example-scripts/voctomidi/lib/config.py
@@ -0,0 +1,16 @@
+import os.path
+from configparser import SafeConfigParser
+
+__all__ = ['Config']
+
+modulepath = os.path.dirname(os.path.realpath(__file__))
+files = [
+    os.path.join(modulepath, '../default-config.ini'),
+    os.path.join(modulepath, '../config.ini'),
+    '/etc/voctomix/voctomidi.ini',
+    '/etc/voctomidi.ini',
+    os.path.expanduser('~/.voctomidi.ini'),
+]
+
+Config = SafeConfigParser()
+Config.read(files)
diff --git a/example-scripts/voctomidi/voctomidi.py b/example-scripts/voctomidi/voctomidi.py
new file mode 100755
index 0000000..b21f529
--- /dev/null
+++ b/example-scripts/voctomidi/voctomidi.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+import atexit
+import socket
+import sys
+import time
+from rtmidi.midiutil import open_midiport
+
+from lib.config import Config
+
+NOTE_ON = 144
+
+host = Config.get("server", "host")
+port = 9999
+
+device = Config.get("midi", "device")
+
+event_map = dict(map(lambda x: (int(x[0]), x[1]), Config.items("eventmap")))
+
+
+class MidiInputHandler(object):
+    def __init__(self, port):
+        self.port = port
+
+    def __call__(self, event, data=None):
+        global conn
+        message, _deltatime = event
+        if message[0] != NOTE_ON:
+            return
+        if message[1] in event_map:
+            note = message[1]
+            msg = "set_videos_and_composite " + event_map[note]
+            print("Sending: '{}'".format(msg))
+            try:
+                conn.sendall(msg.encode('ascii') + b"\n")
+            except BrokenPipeError:
+                print("voctocore disconnected, trying to reconnect")
+                try:
+                    conn = socket.create_connection((host, port))
+                    print("Reconnected to voctocore")
+                except:
+                    pass
+        else:
+            print("[{}]: Unhandled NOTE ON event {}".format(self.port,
+                                                            message[1]))
+
+
+@atexit.register
+def kthxbye():
+    print("Exit")
+
+conn, midiin = None, None
+
+try:
+    conn = socket.create_connection((host, port))
+except (ConnectionRefusedError, KeyboardInterrupt):
+    print("Could not connect to voctocore")
+    sys.exit()
+
+
+@atexit.register
+def close_conn():
+    global conn
+    conn and conn.close()
+
+try:
+    midiin, port_name = open_midiport(device)
+except (EOFError, KeyboardInterrupt):
+    print("Opening midi port failed")
+    sys.exit()
+
+
+@atexit.register
+def close_midi():
+    global midiin
+    midiin and midiin.close_port()
+    del midiin
+
+midiin.set_callback(MidiInputHandler(port_name))
+
+print("Entering main loop. Press Control-C to exit.")
+try:
+    # just wait for keyboard interrupt in main thread
+    while True:
+        time.sleep(1)
+except KeyboardInterrupt:
+    print("")
-- 
cgit v1.2.3