Compare commits
3 commits
15c7b69ef7
...
577a5c0141
Author | SHA1 | Date | |
---|---|---|---|
|
577a5c0141 | ||
|
a33aff4866 | ||
|
25e56cb61a |
|
@ -1,63 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
import websockets
|
||||
from mmelodies_pb2 import UpdateRequest, Update, Parameter
|
||||
|
||||
|
||||
async def handler(ws):
|
||||
print(f"connection on {ws.path}")
|
||||
while True:
|
||||
try:
|
||||
message = await ws.recv()
|
||||
|
||||
request = UpdateRequest()
|
||||
request.ParseFromString(message)
|
||||
print(request)
|
||||
|
||||
response = Update()
|
||||
|
||||
if request.scope_samples:
|
||||
response.scope_samples = b"\n" * 512
|
||||
|
||||
for param in request.param_changes:
|
||||
print(f"param {param.id} {param.value}")
|
||||
p = response.params.add()
|
||||
p.id = param.id
|
||||
p.value = param.value
|
||||
|
||||
print(response)
|
||||
|
||||
await ws.send(response.SerializeToString())
|
||||
except websockets.ConnectionClosedOK:
|
||||
break
|
||||
except websockets.ConnectionClosedError as e:
|
||||
print(repr(e))
|
||||
break
|
||||
|
||||
|
||||
async def _main(port=8001, unix=None):
|
||||
if unix is not None:
|
||||
print(f"listening on {unix}")
|
||||
ws = websockets.unix_serve(handler, path=unix)
|
||||
else:
|
||||
print(f"listening on localhost:{port}")
|
||||
ws = websockets.serve(handler, "localhost", port=port)
|
||||
async with ws:
|
||||
await asyncio.Future() # run forever
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-U", "--unix", type=Path)
|
||||
parser.add_argument("-p", "--port", type=int, default=8001)
|
||||
args = parser.parse_args()
|
||||
|
||||
asyncio.run(_main(**vars(args)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
125
backend/mmelodies/backend.py
Normal file
125
backend/mmelodies/backend.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from collections import namedtuple
|
||||
from functools import partial
|
||||
|
||||
import websockets
|
||||
from .mmelodies_pb2 import UpdateRequest, Update, Parameter
|
||||
|
||||
|
||||
CONNECTIONS = []
|
||||
|
||||
|
||||
async def request_handler(ws, writer):
|
||||
print(f"connection on {ws.path}")
|
||||
CONNECTIONS.append(ws)
|
||||
while True:
|
||||
try:
|
||||
message = await ws.recv()
|
||||
|
||||
request = UpdateRequest()
|
||||
request.ParseFromString(message)
|
||||
print(request)
|
||||
|
||||
if request.scope_samples:
|
||||
writer.write("scope;".encode())
|
||||
|
||||
for param in request.param_changes:
|
||||
writer.write(f"set {param.id} {param.value};".encode())
|
||||
|
||||
writer.write("params;\n".encode())
|
||||
|
||||
await writer.drain()
|
||||
except TypeError as e:
|
||||
print(e)
|
||||
except websockets.ConnectionClosedOK:
|
||||
CONNECTIONS.remove(ws)
|
||||
break
|
||||
except websockets.ConnectionClosedError as e:
|
||||
print(e)
|
||||
CONNECTIONS.remove(ws)
|
||||
break
|
||||
|
||||
|
||||
async def update_handler(reader):
|
||||
print("pd connected!")
|
||||
while True:
|
||||
try:
|
||||
message = (await reader.readline()).decode().strip(";\n")
|
||||
update = Update()
|
||||
parts = message.split(" ")
|
||||
|
||||
if parts[0] == "params":
|
||||
for param_id, value in enumerate(parts[1:]):
|
||||
param = update.params.add()
|
||||
param.id = param_id
|
||||
param.value = int(value)
|
||||
|
||||
if parts[0] == "scope":
|
||||
update.scope_samples.extend([int(part) for part in parts[1:]])
|
||||
|
||||
print(repr(update))
|
||||
|
||||
websockets.broadcast(CONNECTIONS, update.SerializeToString())
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
async def _main(listen_port, pd_port):
|
||||
if pd_port[0] == "unix":
|
||||
path = pd_port[1]
|
||||
print(f"connecting to Pd on {path.absolute()}")
|
||||
pd_reader, pd_writer = await asyncio.open_unix_connection(
|
||||
path=path, happy_eyeballs_delay=0.25
|
||||
)
|
||||
if pd_port[0] == "tcp":
|
||||
host, port = pd_port[1]
|
||||
print(f"connecting to Pd on {host}:{port}")
|
||||
pd_reader, pd_writer = await asyncio.open_connection(
|
||||
host=host, port=port, happy_eyeballs_delay=0.25
|
||||
)
|
||||
|
||||
ws_handler = partial(request_handler, writer=pd_writer)
|
||||
|
||||
if listen_port[0] == "unix":
|
||||
path = listen_port[1]
|
||||
print(f"listening on {path.absolute()}")
|
||||
ws = websockets.unix_serve(ws_handler, path=path)
|
||||
if listen_port[0] == "tcp":
|
||||
host, port = listen_port[1]
|
||||
print(f"listening on {host}:{port}")
|
||||
ws = websockets.serve(ws_handler, host=host, port=port)
|
||||
|
||||
async with ws:
|
||||
await update_handler(pd_reader)
|
||||
|
||||
|
||||
def port(arg: str):
|
||||
kind, address = arg.split(":", maxsplit=1)
|
||||
if kind == "tcp":
|
||||
host, port = address.rsplit(":", maxsplit=1)
|
||||
port = int(port)
|
||||
if host == "":
|
||||
host = "localhost"
|
||||
return kind, (host, port)
|
||||
|
||||
if kind == "unix":
|
||||
path = Path(address)
|
||||
assert path.parent.exists()
|
||||
return kind, path
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-l", "--listen-port", type=port, default="tcp:localhost:8001")
|
||||
parser.add_argument("-p", "--pd-port", type=port, default="tcp:localhost:10234")
|
||||
args = parser.parse_args()
|
||||
|
||||
asyncio.run(_main(**vars(args)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fmmelodies.proto\"&\n\tParameter\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r\"`\n\rUpdateRequest\x12\x1a\n\rscope_samples\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12!\n\rparam_changes\x18\x02 \x03(\x0b\x32\n.ParameterB\x10\n\x0e_scope_samples\"R\n\x06Update\x12\x1a\n\rscope_samples\x18\x01 \x01(\x0cH\x00\x88\x01\x01\x12\x1a\n\x06params\x18\x02 \x03(\x0b\x32\n.ParameterB\x10\n\x0e_scope_samplesb\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fmmelodies.proto\"&\n\tParameter\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r\"`\n\rUpdateRequest\x12\x1a\n\rscope_samples\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12!\n\rparam_changes\x18\x02 \x03(\x0b\x32\n.ParameterB\x10\n\x0e_scope_samples\";\n\x06Update\x12\x15\n\rscope_samples\x18\x01 \x03(\x11\x12\x1a\n\x06params\x18\x02 \x03(\x0b\x32\n.Parameterb\x06proto3')
|
||||
|
||||
|
||||
|
||||
|
@ -50,5 +50,5 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|||
_UPDATEREQUEST._serialized_start=59
|
||||
_UPDATEREQUEST._serialized_end=155
|
||||
_UPDATE._serialized_start=157
|
||||
_UPDATE._serialized_end=239
|
||||
_UPDATE._serialized_end=216
|
||||
# @@protoc_insertion_point(module_scope)
|
|
@ -1,5 +1,5 @@
|
|||
[tool.poetry]
|
||||
name = "backend"
|
||||
name = "mmelodies"
|
||||
version = "0.1.0"
|
||||
description = "Connects everything."
|
||||
authors = []
|
||||
|
@ -12,7 +12,7 @@ protobuf = "^4.24.3"
|
|||
[tool.poetry.dev-dependencies]
|
||||
|
||||
[tool.poetry.scripts]
|
||||
backend = "backend:main"
|
||||
mmelodies = "mmelodies.backend:main"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
|
|
|
@ -7,7 +7,30 @@
|
|||
sslCertificate = "/etc/ssl/snakeoil.crt";
|
||||
sslCertificateKey = "/etc/ssl/snakeoil.key";
|
||||
root = pkgs.mmelodies.frontend;
|
||||
locations."/api" = {
|
||||
proxyPass = "http://unix:/run/mmelodies/backend.sock";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
|
||||
systemd.services.mmelodies = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
before = [ "nignx.target" ];
|
||||
serviceConfig = {
|
||||
User = "nginx";
|
||||
Group = "nginx";
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.mmelodies.backend}/bin/mmelodies -l unix:/run/mmelodies/backend.sock";
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /run/mmelodies 0755 nginx nginx 12h -"
|
||||
];
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,6 @@ message UpdateRequest {
|
|||
}
|
||||
|
||||
message Update {
|
||||
optional bytes scope_samples = 1;
|
||||
repeated sint32 scope_samples = 1;
|
||||
repeated Parameter params = 2;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import * as THREE from 'three';
|
|||
// @ts-ignore
|
||||
import { UpdateRequest, Update } from "/proto/mmelodies.proto";
|
||||
|
||||
const url = new URL("/api/controller", location.href);
|
||||
const url = new URL("/api", location.href);
|
||||
const send = document.querySelector("#send");
|
||||
|
||||
url.protocol = "ws";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { UpdateRequest, Update } from "/proto/mmelodies.proto";
|
||||
|
||||
const url = new URL("/api/display", location.href);
|
||||
const url = new URL("/api", location.href);
|
||||
const send = document.querySelector("#send");
|
||||
|
||||
url.protocol = "ws";
|
||||
|
@ -14,7 +14,7 @@ socket.binaryType = 'arraybuffer';
|
|||
socket.addEventListener("message", (event) => {
|
||||
send.value = "Pong";
|
||||
const message = Update.decode(new Uint8Array(event.data));
|
||||
console.log(message.scope_samples);
|
||||
console.log(message.scopeSamples);
|
||||
});
|
||||
|
||||
send.addEventListener("click", function () {
|
||||
|
|
Loading…
Reference in a new issue