The idea here is to have an array of buttons on an HTML page which, when pressed, cause OSC messages to be sent somewhere (like Reaper). See also this simple tabbed pages example for how to get more buttons than will fit on a screen.
This is my second attempt.
Server
#!/usr/bin/env python3
# Python 3 server example
from http.server import BaseHTTPRequestHandler, HTTPServer
from subprocess import run, PIPE
import time
import sys
import re
from datetime import datetime
from threading import Thread
hostName = ""
serverPort = 4041
from myosc import Osc
osc = Osc("localhost",2708)
class MyServer(BaseHTTPRequestHandler):
def homepage(self):
self.homepage_html = open("homepage.html").read()
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes(self.homepage_html, "utf-8"))
def do_GET(self):
if self.path == "/favicon.ico":
self.send_response(404)
self.end_headers()
self.wfile.write(b"No favicon")
return
if self.path.strip("/") == "":
return self.homepage()
if self.path.lstrip("/").startswith("send/"):
x = self.path.lstrip("/")
x = x[len("send/"):]
osc.send(x)
self.send_response(200)
self.end_headers()
self.wfile.write(b"OK")
self.send_response(404)
self.end_headers()
self.wfile.write(b"Not Found")
return
if __name__ == "__main__":
webServer = HTTPServer((hostName, serverPort), MyServer)
print("Server started http://%s:%s" % (hostName, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")
OSC helper
You need pip install python-osc for this.
#!/usr/bin/env python3
import socket
from pythonosc import udp_client
class Osc:
def __init__(self,host,port):
self.host = host
self.port = port
self.client = udp_client.SimpleUDPClient(self.host, self.port, family=socket.AF_INET)
def send(self,addr,params=None):
if params is None:
params = []
addr = "/"+addr.lstrip("/")
self.client.send_message(addr,params)
html homepage
<!DOCTYPE html>
<html>
<head>
<meta charset='utf8'/>
<title>OSC Buttons</title>
<style>
span.button {
display: inline-block;
padding: 1rem;
border: 1px solid black;
background-color: #007;
color: white;
cursor: pointer;
font-size: 1.5rem;
font-family: sans-serif;
}
span.button.clicked {
background-color: #ff0;
color: black;
}
</style>
</head>
<body>
<table class="control-panel">
<tr>
<td><span class="button" osc="flibble">flibble</td>
<td><span class="button" osc="f1">f1</td>
<td><span class="button" osc="f2">f2</td>
<td><span class="button" osc="f3">f3</td>
<td><span class="button" osc="f4">f4</td>
</tr>
<tr>
<td><span class="button" osc="glibble">glibble</td>
<td><span class="button" osc="g1">g1</td>
<td><span class="button" osc="g2">g2</td>
<td><span class="button" osc="g3">g3</td>
<td><span class="button" osc="g4">g4</td>
</tr>
<tr>
<td><span class="button" osc="plibble">Plibble</td>
<td><span class="button" osc="p1">P1</td>
<td><span class="button" osc="p2">P2</td>
<td><span class="button" osc="p3">P3</td>
<td><span class="button" osc="p4">P4</td>
</tr>
</table>
</body>
<script>
window.q = (x,y=document) => y.querySelector(x)
const qq = window.qq = (x,y=document) => Array.from(y.querySelectorAll(x))
const clicked_duration = 300
function sig(button) {
button.classList.add("clicked")
setTimeout(_ => {
button.classList.remove("clicked")
},clicked_duration)
}
function send(msg) {
fetch(`/send/${msg}`)
}
qq("table.control-panel span.button").forEach(button => {
button.addEventListener("click",e => {
e.preventDefault()
let x = button.getAttribute("osc")
if( x ) {
send(x)
sig(button)
}
})
})
</script>
</html>