Compare commits

...

6 Commits

15 changed files with 412 additions and 114 deletions

1
backend/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.pyc

1
backend/README.md Normal file
View File

@ -0,0 +1 @@
Run `protoc -I=../proto/ --python_out=. ../proto/mmelodies.proto` to update generated protobuf api.

63
backend/backend.py Normal file
View File

@ -0,0 +1,63 @@
#!/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()

4
backend/default.nix Normal file
View File

@ -0,0 +1,4 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.poetry2nix.mkPoetryApplication {
projectDir = ./.;
}

54
backend/mmelodies_pb2.py Normal file
View File

@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: mmelodies.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import descriptor_pool as _descriptor_pool
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_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')
_PARAMETER = DESCRIPTOR.message_types_by_name['Parameter']
_UPDATEREQUEST = DESCRIPTOR.message_types_by_name['UpdateRequest']
_UPDATE = DESCRIPTOR.message_types_by_name['Update']
Parameter = _reflection.GeneratedProtocolMessageType('Parameter', (_message.Message,), {
'DESCRIPTOR' : _PARAMETER,
'__module__' : 'mmelodies_pb2'
# @@protoc_insertion_point(class_scope:Parameter)
})
_sym_db.RegisterMessage(Parameter)
UpdateRequest = _reflection.GeneratedProtocolMessageType('UpdateRequest', (_message.Message,), {
'DESCRIPTOR' : _UPDATEREQUEST,
'__module__' : 'mmelodies_pb2'
# @@protoc_insertion_point(class_scope:UpdateRequest)
})
_sym_db.RegisterMessage(UpdateRequest)
Update = _reflection.GeneratedProtocolMessageType('Update', (_message.Message,), {
'DESCRIPTOR' : _UPDATE,
'__module__' : 'mmelodies_pb2'
# @@protoc_insertion_point(class_scope:Update)
})
_sym_db.RegisterMessage(Update)
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
_PARAMETER._serialized_start=19
_PARAMETER._serialized_end=57
_UPDATEREQUEST._serialized_start=59
_UPDATEREQUEST._serialized_end=155
_UPDATE._serialized_start=157
_UPDATE._serialized_end=239
# @@protoc_insertion_point(module_scope)

107
backend/poetry.lock generated Normal file
View File

@ -0,0 +1,107 @@
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
[[package]]
name = "protobuf"
version = "4.24.3"
description = ""
optional = false
python-versions = ">=3.7"
files = [
{file = "protobuf-4.24.3-cp310-abi3-win32.whl", hash = "sha256:20651f11b6adc70c0f29efbe8f4a94a74caf61b6200472a9aea6e19898f9fcf4"},
{file = "protobuf-4.24.3-cp310-abi3-win_amd64.whl", hash = "sha256:3d42e9e4796a811478c783ef63dc85b5a104b44aaaca85d4864d5b886e4b05e3"},
{file = "protobuf-4.24.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:6e514e8af0045be2b56e56ae1bb14f43ce7ffa0f68b1c793670ccbe2c4fc7d2b"},
{file = "protobuf-4.24.3-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:ba53c2f04798a326774f0e53b9c759eaef4f6a568ea7072ec6629851c8435959"},
{file = "protobuf-4.24.3-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:f6ccbcf027761a2978c1406070c3788f6de4a4b2cc20800cc03d52df716ad675"},
{file = "protobuf-4.24.3-cp37-cp37m-win32.whl", hash = "sha256:1b182c7181a2891e8f7f3a1b5242e4ec54d1f42582485a896e4de81aa17540c2"},
{file = "protobuf-4.24.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b0271a701e6782880d65a308ba42bc43874dabd1a0a0f41f72d2dac3b57f8e76"},
{file = "protobuf-4.24.3-cp38-cp38-win32.whl", hash = "sha256:e29d79c913f17a60cf17c626f1041e5288e9885c8579832580209de8b75f2a52"},
{file = "protobuf-4.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:067f750169bc644da2e1ef18c785e85071b7c296f14ac53e0900e605da588719"},
{file = "protobuf-4.24.3-cp39-cp39-win32.whl", hash = "sha256:2da777d34b4f4f7613cdf85c70eb9a90b1fbef9d36ae4a0ccfe014b0b07906f1"},
{file = "protobuf-4.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:f631bb982c5478e0c1c70eab383af74a84be66945ebf5dd6b06fc90079668d0b"},
{file = "protobuf-4.24.3-py3-none-any.whl", hash = "sha256:f6f8dc65625dadaad0c8545319c2e2f0424fede988368893ca3844261342c11a"},
{file = "protobuf-4.24.3.tar.gz", hash = "sha256:12e9ad2ec079b833176d2921be2cb24281fa591f0b119b208b788adc48c2561d"},
]
[[package]]
name = "websockets"
version = "11.0.3"
description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)"
optional = false
python-versions = ">=3.7"
files = [
{file = "websockets-11.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3ccc8a0c387629aec40f2fc9fdcb4b9d5431954f934da3eaf16cdc94f67dbfac"},
{file = "websockets-11.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d67ac60a307f760c6e65dad586f556dde58e683fab03323221a4e530ead6f74d"},
{file = "websockets-11.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d27a4832cc1a0ee07cdcf2b0629a8a72db73f4cf6de6f0904f6661227f256f"},
{file = "websockets-11.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffd7dcaf744f25f82190856bc26ed81721508fc5cbf2a330751e135ff1283564"},
{file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7622a89d696fc87af8e8d280d9b421db5133ef5b29d3f7a1ce9f1a7bf7fcfa11"},
{file = "websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bceab846bac555aff6427d060f2fcfff71042dba6f5fca7dc4f75cac815e57ca"},
{file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54c6e5b3d3a8936a4ab6870d46bdd6ec500ad62bde9e44462c32d18f1e9a8e54"},
{file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41f696ba95cd92dc047e46b41b26dd24518384749ed0d99bea0a941ca87404c4"},
{file = "websockets-11.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:86d2a77fd490ae3ff6fae1c6ceaecad063d3cc2320b44377efdde79880e11526"},
{file = "websockets-11.0.3-cp310-cp310-win32.whl", hash = "sha256:2d903ad4419f5b472de90cd2d40384573b25da71e33519a67797de17ef849b69"},
{file = "websockets-11.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:1d2256283fa4b7f4c7d7d3e84dc2ece74d341bce57d5b9bf385df109c2a1a82f"},
{file = "websockets-11.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e848f46a58b9fcf3d06061d17be388caf70ea5b8cc3466251963c8345e13f7eb"},
{file = "websockets-11.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa5003845cdd21ac0dc6c9bf661c5beddd01116f6eb9eb3c8e272353d45b3288"},
{file = "websockets-11.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b58cbf0697721120866820b89f93659abc31c1e876bf20d0b3d03cef14faf84d"},
{file = "websockets-11.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:660e2d9068d2bedc0912af508f30bbeb505bbbf9774d98def45f68278cea20d3"},
{file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c1f0524f203e3bd35149f12157438f406eff2e4fb30f71221c8a5eceb3617b6b"},
{file = "websockets-11.0.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:def07915168ac8f7853812cc593c71185a16216e9e4fa886358a17ed0fd9fcf6"},
{file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b30c6590146e53149f04e85a6e4fcae068df4289e31e4aee1fdf56a0dead8f97"},
{file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:619d9f06372b3a42bc29d0cd0354c9bb9fb39c2cbc1a9c5025b4538738dbffaf"},
{file = "websockets-11.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:01f5567d9cf6f502d655151645d4e8b72b453413d3819d2b6f1185abc23e82dd"},
{file = "websockets-11.0.3-cp311-cp311-win32.whl", hash = "sha256:e1459677e5d12be8bbc7584c35b992eea142911a6236a3278b9b5ce3326f282c"},
{file = "websockets-11.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:e7837cb169eca3b3ae94cc5787c4fed99eef74c0ab9506756eea335e0d6f3ed8"},
{file = "websockets-11.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9f59a3c656fef341a99e3d63189852be7084c0e54b75734cde571182c087b152"},
{file = "websockets-11.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2529338a6ff0eb0b50c7be33dc3d0e456381157a31eefc561771ee431134a97f"},
{file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:34fd59a4ac42dff6d4681d8843217137f6bc85ed29722f2f7222bd619d15e95b"},
{file = "websockets-11.0.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:332d126167ddddec94597c2365537baf9ff62dfcc9db4266f263d455f2f031cb"},
{file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6505c1b31274723ccaf5f515c1824a4ad2f0d191cec942666b3d0f3aa4cb4007"},
{file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f467ba0050b7de85016b43f5a22b46383ef004c4f672148a8abf32bc999a87f0"},
{file = "websockets-11.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9d9acd80072abcc98bd2c86c3c9cd4ac2347b5a5a0cae7ed5c0ee5675f86d9af"},
{file = "websockets-11.0.3-cp37-cp37m-win32.whl", hash = "sha256:e590228200fcfc7e9109509e4d9125eace2042fd52b595dd22bbc34bb282307f"},
{file = "websockets-11.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:b16fff62b45eccb9c7abb18e60e7e446998093cdcb50fed33134b9b6878836de"},
{file = "websockets-11.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fb06eea71a00a7af0ae6aefbb932fb8a7df3cb390cc217d51a9ad7343de1b8d0"},
{file = "websockets-11.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8a34e13a62a59c871064dfd8ffb150867e54291e46d4a7cf11d02c94a5275bae"},
{file = "websockets-11.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4841ed00f1026dfbced6fca7d963c4e7043aa832648671b5138008dc5a8f6d99"},
{file = "websockets-11.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a073fc9ab1c8aff37c99f11f1641e16da517770e31a37265d2755282a5d28aa"},
{file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68b977f21ce443d6d378dbd5ca38621755f2063d6fdb3335bda981d552cfff86"},
{file = "websockets-11.0.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a99a7a71631f0efe727c10edfba09ea6bee4166a6f9c19aafb6c0b5917d09c"},
{file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bee9fcb41db2a23bed96c6b6ead6489702c12334ea20a297aa095ce6d31370d0"},
{file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4b253869ea05a5a073ebfdcb5cb3b0266a57c3764cf6fe114e4cd90f4bfa5f5e"},
{file = "websockets-11.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1553cb82942b2a74dd9b15a018dce645d4e68674de2ca31ff13ebc2d9f283788"},
{file = "websockets-11.0.3-cp38-cp38-win32.whl", hash = "sha256:f61bdb1df43dc9c131791fbc2355535f9024b9a04398d3bd0684fc16ab07df74"},
{file = "websockets-11.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:03aae4edc0b1c68498f41a6772d80ac7c1e33c06c6ffa2ac1c27a07653e79d6f"},
{file = "websockets-11.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:777354ee16f02f643a4c7f2b3eff8027a33c9861edc691a2003531f5da4f6bc8"},
{file = "websockets-11.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8c82f11964f010053e13daafdc7154ce7385ecc538989a354ccc7067fd7028fd"},
{file = "websockets-11.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3580dd9c1ad0701169e4d6fc41e878ffe05e6bdcaf3c412f9d559389d0c9e016"},
{file = "websockets-11.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f1a3f10f836fab6ca6efa97bb952300b20ae56b409414ca85bff2ad241d2a61"},
{file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df41b9bc27c2c25b486bae7cf42fccdc52ff181c8c387bfd026624a491c2671b"},
{file = "websockets-11.0.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:279e5de4671e79a9ac877427f4ac4ce93751b8823f276b681d04b2156713b9dd"},
{file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1fdf26fa8a6a592f8f9235285b8affa72748dc12e964a5518c6c5e8f916716f7"},
{file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69269f3a0b472e91125b503d3c0b3566bda26da0a3261c49f0027eb6075086d1"},
{file = "websockets-11.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:97b52894d948d2f6ea480171a27122d77af14ced35f62e5c892ca2fae9344311"},
{file = "websockets-11.0.3-cp39-cp39-win32.whl", hash = "sha256:c7f3cb904cce8e1be667c7e6fef4516b98d1a6a0635a58a57528d577ac18a128"},
{file = "websockets-11.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c792ea4eabc0159535608fc5658a74d1a81020eb35195dd63214dcf07556f67e"},
{file = "websockets-11.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f2e58f2c36cc52d41f2659e4c0cbf7353e28c8c9e63e30d8c6d3494dc9fdedcf"},
{file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de36fe9c02995c7e6ae6efe2e205816f5f00c22fd1fbf343d4d18c3d5ceac2f5"},
{file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ac56b661e60edd453585f4bd68eb6a29ae25b5184fd5ba51e97652580458998"},
{file = "websockets-11.0.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e052b8467dd07d4943936009f46ae5ce7b908ddcac3fda581656b1b19c083d9b"},
{file = "websockets-11.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:42cc5452a54a8e46a032521d7365da775823e21bfba2895fb7b77633cce031bb"},
{file = "websockets-11.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e6316827e3e79b7b8e7d8e3b08f4e331af91a48e794d5d8b099928b6f0b85f20"},
{file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8531fdcad636d82c517b26a448dcfe62f720e1922b33c81ce695d0edb91eb931"},
{file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c114e8da9b475739dde229fd3bc6b05a6537a88a578358bc8eb29b4030fac9c9"},
{file = "websockets-11.0.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e063b1865974611313a3849d43f2c3f5368093691349cf3c7c8f8f75ad7cb280"},
{file = "websockets-11.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:92b2065d642bf8c0a82d59e59053dd2fdde64d4ed44efe4870fa816c1232647b"},
{file = "websockets-11.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0ee68fe502f9031f19d495dae2c268830df2760c0524cbac5d759921ba8c8e82"},
{file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcacf2c7a6c3a84e720d1bb2b543c675bf6c40e460300b628bab1b1efc7c034c"},
{file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b67c6f5e5a401fc56394f191f00f9b3811fe843ee93f4a70df3c389d1adf857d"},
{file = "websockets-11.0.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d5023a4b6a5b183dc838808087033ec5df77580485fc533e7dab2567851b0a4"},
{file = "websockets-11.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ed058398f55163a79bb9f06a90ef9ccc063b204bb346c4de78efc5d15abfe602"},
{file = "websockets-11.0.3-py3-none-any.whl", hash = "sha256:6681ba9e7f8f3b19440921e99efbb40fc89f26cd71bf539e45d8c8a25c976dc6"},
{file = "websockets-11.0.3.tar.gz", hash = "sha256:88fc51d9a26b10fc331be344f1781224a375b78488fc343620184e95a4b27016"},
]
[metadata]
lock-version = "2.0"
python-versions = "^3.9"
content-hash = "286166c15f65ef87768cf2c7a1d0722de8e60f1dc108cd933ad055611cf223ef"

19
backend/pyproject.toml Normal file
View File

@ -0,0 +1,19 @@
[tool.poetry]
name = "backend"
version = "0.1.0"
description = "Connects everything."
authors = []
[tool.poetry.dependencies]
python = "^3.9"
websockets = "^11.0.3"
protobuf = "^4.24.3"
[tool.poetry.dev-dependencies]
[tool.poetry.scripts]
backend = "backend:main"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

11
backend/shell.nix Normal file
View File

@ -0,0 +1,11 @@
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
packages = with pkgs; [
python3
poetry
python3Packages.python-lsp-server
python3Packages.python-lsp-black
websocat
grpc-tools
];
}

View File

@ -20,8 +20,12 @@
};
in
{
devShells.default = import ./shell.nix { inherit pkgs; };
packages.frontend = pkgs.mmelodies.frontend;
devShells = rec {
frontend = import ./shell.nix { inherit pkgs; };
backend = import ./backend/shell.nix { inherit pkgs; };
default = frontend;
};
packages = pkgs.mmelodies;
}
) // {
nixosModules.default = import ./nixos;
@ -30,6 +34,7 @@
napalm = import inputs.napalm { pkgs = super; };
mmelodies = {
frontend = final.callPackage ./default.nix {};
backend = final.callPackage ./backend {};
};
});
};

View File

@ -1,33 +1,16 @@
syntax = "proto3";
service ParameterService {
rpc SetParameters(ParameterRequest) returns (ParameterResponse) {};
message Parameter {
uint32 id = 1;
uint32 value = 2;
}
message ParameterRequest {
optional uint32 velocity = 1;
optional uint32 tempo = 2;
optional uint32 echo_time = 3;
optional uint32 echo_feedback = 4;
optional uint32 filter_cutoff = 5;
optional uint32 echo_mix = 6;
message UpdateRequest {
optional bool scope_samples = 1;
repeated Parameter param_changes = 2;
}
message ParameterResponse {
uint32 velocity = 1;
uint32 tempo = 2;
uint32 delay_time = 3;
uint32 delay_feedback = 4;
uint32 filter_cutoff = 5;
uint32 echo_mix = 6;
}
service ScopeService {
rpc GetSamples(ScopeSamplesRequest) returns (ScopeSamplesResponse) {};
}
message ScopeSamplesRequest {}
message ScopeSamplesResponse {
bytes samples = 1;
message Update {
optional bytes scope_samples = 1;
repeated Parameter params = 2;
}

View File

@ -2,7 +2,7 @@
"name": "Andisco: Motion music synthesis",
"short_name": "Andisco",
"description": "Connect to an andisco server to generate music with motion controls .",
"start_url": "/",
"start_url": "/controller/",
"theme_color": "#eeffee",
"background_color": "#eeffee",
"display": "standalone",
@ -12,4 +12,4 @@
"sizes": "512x512"
}
]
}
}

View File

@ -1,10 +1,19 @@
import { ParameterRequest } from "/proto/mmelodies.proto";
import { UpdateRequest, Update } from "/proto/mmelodies.proto";
const message = ParameterRequest.create({ velocity: 126 });
const buffer = ParameterRequest.encode(message).finish();
const decoded = ParameterRequest.decode(buffer);
const url = new URL("/api/controller", location.href);
const send = document.querySelector("#send");
console.log(decoded);
url.protocol = "ws";
if (location.protocol.startsWith("https")) {
url.protocol = "wss";
}
const socket = new WebSocket(url);
socket.binaryType = 'arraybuffer'
socket.addEventListener("message", (event) => {
const message = Update.decode(new Uint8Array(event.data));
console.log(message);
});
// Select all range input elements
const sliders = document.querySelectorAll(
@ -12,9 +21,14 @@ const sliders = document.querySelectorAll(
) as NodeListOf<HTMLInputElement>;
// Add an event listener to each slider
sliders.forEach((slider) => {
sliders.forEach((slider, i) => {
slider.addEventListener("input", function () {
console.log(`Slider ${this.id} position: ${this.value}`);
const message = UpdateRequest.create({paramChanges: [{ id: i, value: this.value}]});
const buffer = UpdateRequest.encode(message).finish();
socket.send(buffer);
});
});

View File

@ -0,0 +1,28 @@
import { UpdateRequest, Update } from "/proto/mmelodies.proto";
const url = new URL("/api/display", location.href);
const send = document.querySelector("#send");
url.protocol = "ws";
if (location.protocol.startsWith("https")) {
url.protocol = "wss";
}
const socket = new WebSocket(url);
socket.binaryType = 'arraybuffer';
// Listen for messages
socket.addEventListener("message", (event) => {
send.value = "Pong";
const message = Update.decode(new Uint8Array(event.data));
console.log(message.scope_samples);
});
send.addEventListener("click", function () {
const message = UpdateRequest.create({scopeSamples: true});
console.log(message);
const buffer = UpdateRequest.encode(message).finish();
console.log(buffer);
send.value = "Ping";
socket.send(buffer);
});

View File

@ -8,5 +8,6 @@
</head>
<body>
<h1>Andisco display</h1>
<input type="button" id="send" value="Ping">
</body>
</html>

View File

@ -3,83 +3,90 @@ const HtmlWebpackPlugin = require("html-webpack-plugin");
const WorkboxPlugin = require("workbox-webpack-plugin");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
mode: "development",
entry: {
controller: "./src/controller/controller.ts",
display: "./src/display/display.ts",
index: "./src/index.ts",
},
output: {
filename: "[name]/app.js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: "src/controller/index.html",
filename: "controller/index.html",
chunks: ["controller"],
}),
new HtmlWebpackPlugin({
template: "src/display/index.html",
filename: "display/index.html",
chunks: ["display"],
}),
new HtmlWebpackPlugin({
template: "src/index.html",
filename: "index.html",
chunks: ["index"],
}),
new WorkboxPlugin.GenerateSW({
// these options encourage the ServiceWorkers to get in there fast
// and not allow any straggling "old" SWs to hang around
clientsClaim: true,
skipWaiting: true,
}),
new CopyPlugin({
patterns: ["public"],
}),
],
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-typescript"],
},
},
},
{
test: /\.proto$/,
use: {
loader: "protobufjs-loader",
options: {
paths: ["proto"],
pbjsArgs: ["--no-encode"],
pbts: {},
target: "json-module",
},
},
},
module.exports = (env) => {
return {
mode: "development",
entry: {
controller: "./src/controller/controller.ts",
display: "./src/display/display.ts",
index: "./src/index.ts",
},
output: {
filename: "[name]_[chunkhash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: "src/controller/index.html",
filename: "controller/index.html",
chunks: ["controller"],
}),
new HtmlWebpackPlugin({
template: "src/display/index.html",
filename: "display/index.html",
chunks: ["display"],
}),
new HtmlWebpackPlugin({
template: "src/index.html",
filename: "index.html",
chunks: ["index"],
}),
new WorkboxPlugin.GenerateSW({
// these options encourage the ServiceWorkers to get in there fast
// and not allow any straggling "old" SWs to hang around
clientsClaim: true,
skipWaiting: true,
}),
new CopyPlugin({
patterns: ["public"],
}),
],
},
optimization: {
minimize: false,
},
devServer: {
proxy: {
'/api': {
target: 'ws://localhost:8001',
ws: true // important
},
}
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
{
test: /\.ts$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-typescript"],
},
},
},
{
test: /\.proto$/,
use: {
loader: "protobufjs-loader",
options: {
paths: ["proto"],
pbjsArgs: ["--no-encode"],
pbts: {},
target: "json-module",
},
},
},
],
},
};
};