From 5126b5d5af582526e224d5335e62b1f6df784b37 Mon Sep 17 00:00:00 2001 From: Francesco Luzzana Date: Sun, 17 Apr 2022 00:35:59 +0200 Subject: [PATCH] setup flask app and test with socketIO --- .gitignore | 3 ++ .vscode/settings.json | 3 ++ config.py | 6 ++++ clients.jpg => img/clients.jpg | Bin cover.jpg => img/cover.jpg | Bin spaghetti.jpg => img/spaghetti.jpg | Bin structure.jpg => img/structure.jpg | Bin readme.md | 8 ++--- requirements.txt | 22 ++++++++++++++ index.html => sequencer/index.html | 0 index.js => sequencer/index.js | 0 style.css => sequencer/style.css | 0 skimmer/__init__.py | 47 +++++++++++++++++++++++++++++ skimmer/bowl.py | 11 +++++++ skimmer/events.py | 10 ++++++ skimmer/prefix.py | 14 +++++++++ skimmer/static/favicon.ico | Bin 0 -> 15406 bytes skimmer/templates/bowl.html | 24 +++++++++++++++ skimmer/templates/pot.html | 24 +++++++++++++++ 19 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 config.py rename clients.jpg => img/clients.jpg (100%) rename cover.jpg => img/cover.jpg (100%) rename spaghetti.jpg => img/spaghetti.jpg (100%) rename structure.jpg => img/structure.jpg (100%) create mode 100644 requirements.txt rename index.html => sequencer/index.html (100%) rename index.js => sequencer/index.js (100%) rename style.css => sequencer/style.css (100%) create mode 100644 skimmer/__init__.py create mode 100644 skimmer/bowl.py create mode 100644 skimmer/events.py create mode 100644 skimmer/prefix.py create mode 100644 skimmer/static/favicon.ico create mode 100644 skimmer/templates/bowl.html create mode 100644 skimmer/templates/pot.html diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a95067 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +venv/ +__pycache__ +.env \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0ceb6db --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} diff --git a/config.py b/config.py new file mode 100644 index 0000000..7689f54 --- /dev/null +++ b/config.py @@ -0,0 +1,6 @@ +import os + +class Config(object): + DEBUG = False + FLASK_APP = os.environ.get('FLASK_APP') + FLASK_ENV = os.environ.get('FLASK_ENV') \ No newline at end of file diff --git a/clients.jpg b/img/clients.jpg similarity index 100% rename from clients.jpg rename to img/clients.jpg diff --git a/cover.jpg b/img/cover.jpg similarity index 100% rename from cover.jpg rename to img/cover.jpg diff --git a/spaghetti.jpg b/img/spaghetti.jpg similarity index 100% rename from spaghetti.jpg rename to img/spaghetti.jpg diff --git a/structure.jpg b/img/structure.jpg similarity index 100% rename from structure.jpg rename to img/structure.jpg diff --git a/readme.md b/readme.md index eb17137..96f0ebd 100644 --- a/readme.md +++ b/readme.md @@ -1,17 +1,17 @@ # Skimmer: multi-channel & displaced muzik -![cover with the skimmer](cover.jpg) +![cover with the skimmer](img/cover.jpg) The Skimmer is a container for experiments on multi-channel and displaced sound works, developed in the context of SI18. The main concept is a system that streams to various connected clients, using them as speakers. Unlike classical broadcast transmissions where everyone receive the same signal, here each client is an individual channel. In doing so, the Skimmer can have as many channels as many clients are connected. This opens interesting spatial and expressive possibilities that I would like to explore. To rely on connected clients and the public as a founding part of the instrument raises questions about instability and contingency in both composition and design. What does it mean for the public to host the instrument, and what does it mean for the performer to be hosted by the public? Which kind of politics and relations are generated? The Skimmer works with a lightweight setup: a server application links together a source and the connected clients. Instead of streaming the audio directly from the source to the server, what is shared is a model to generate the sounds. With this approach the stream consists in just messages for modulating the instrument on each client, and the traffic it is super light. This require a sound design oriented to the specs of the clients. -![skimming the notes](clients.jpg) +![skimming the notes](img/clients.jpg) ## Structure -![structure with a pot](structure.jpg) +![structure with a pot](img/structure.jpg) This setup is made by three main parts: @@ -30,7 +30,7 @@ The source is the instrument that the server and clients share. The recipe of th - The handle will be maybe something similar to the [modular spaghetti interface](https://git.xpub.nl/kamo/spaghetti)? (not sure yet, but i like the idea of drawing connections between the source and the clients) - The sift will be a little server in the Soupboat, not sure yet if with node.js and express (pro: all JS pipeline) or flask (pro: mixed pipeline and familiar pattern) -![spaghetti setup](spaghetti.jpg) +![spaghetti setup](img/spaghetti.jpg) Prototype of the spaghetti cables interface ### Process diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f12a61d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,22 @@ +bidict==0.22.0 +black==22.3.0 +click==8.1.2 +colorama==0.4.4 +dnspython==2.2.1 +eventlet==0.33.0 +Flask==2.1.1 +Flask-SocketIO==5.1.1 +greenlet==1.1.2 +itsdangerous==2.1.2 +Jinja2==3.1.1 +Mako==1.2.0 +MarkupSafe==2.1.1 +mypy-extensions==0.4.3 +pathspec==0.9.0 +platformdirs==2.5.1 +python-dotenv==0.20.0 +python-engineio==4.3.1 +python-socketio==5.5.2 +six==1.16.0 +tomli==2.0.1 +Werkzeug==2.1.1 diff --git a/index.html b/sequencer/index.html similarity index 100% rename from index.html rename to sequencer/index.html diff --git a/index.js b/sequencer/index.js similarity index 100% rename from index.js rename to sequencer/index.js diff --git a/style.css b/sequencer/style.css similarity index 100% rename from style.css rename to sequencer/style.css diff --git a/skimmer/__init__.py b/skimmer/__init__.py new file mode 100644 index 0000000..ce1a0fe --- /dev/null +++ b/skimmer/__init__.py @@ -0,0 +1,47 @@ +import os +from flask import Flask, send_from_directory +from flask_socketio import SocketIO +from . import prefix + +socketio = SocketIO() + + +def create_app(test_config=None): + # Create and configure the Flask App + app = Flask(__name__, instance_relative_config=True) + app.config.from_mapping( + SECRET_KEY="dev", + ) + + if test_config is None: + # load the instance config, if it exists, when not testing + app.config.from_pyfile("config.py", silent=True) + else: + # load the test config if passed in + app.config.from_mapping(test_config) + + # ensure the instance folder exists + try: + os.makedirs(app.instance_path) + except OSError: + pass + + @app.route("/favicon.ico") + def favicon(): + return send_from_directory( + os.path.join(app.root_path, "static"), + "favicon.ico", + mimetype="image/vnd.microsoft.icon", + ) + + from . import bowl + + app.register_blueprint(bowl.bp) + + app.wsgi_app = prefix.PrefixMiddleware( + app.wsgi_app, prefix=os.environ.get("URL_PREFIX", "") + ) + + socketio.init_app(app) + + return app diff --git a/skimmer/bowl.py b/skimmer/bowl.py new file mode 100644 index 0000000..e1974e0 --- /dev/null +++ b/skimmer/bowl.py @@ -0,0 +1,11 @@ +from flask import Blueprint +from mako.template import Template + +from . import events + +bp = Blueprint("bowl", __name__) + + +@bp.route("/") +def bowl(): + return Template(filename="skimmer/templates/bowl.html").render() diff --git a/skimmer/events.py b/skimmer/events.py new file mode 100644 index 0000000..ac0b9dd --- /dev/null +++ b/skimmer/events.py @@ -0,0 +1,10 @@ +from flask import session +from flask_socketio import emit + +from . import socketio + + +@socketio.on("my event") +def test(message): + print(message) + emit("message", {"msg": "eheh"}) diff --git a/skimmer/prefix.py b/skimmer/prefix.py new file mode 100644 index 0000000..3d6a9cc --- /dev/null +++ b/skimmer/prefix.py @@ -0,0 +1,14 @@ +class PrefixMiddleware(object): + def __init__(self, app, prefix=""): + self.app = app + self.prefix = prefix + + def __call__(self, environ, start_response): + + if environ["PATH_INFO"].startswith(self.prefix): + environ["PATH_INFO"] = environ["PATH_INFO"][len(self.prefix) :] + environ["SCRIPT_NAME"] = self.prefix + return self.app(environ, start_response) + else: + start_response("404", [("Content-Type", "text/plain")]) + return ["This url does not belong to the app.".encode()] \ No newline at end of file diff --git a/skimmer/static/favicon.ico b/skimmer/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1663939934174d4c0bd2ef728ab81a8e8dc77a4c GIT binary patch literal 15406 zcmeHOONbmr7%q*P1YaBQfl+Y92Qhe9B?y9Oj^bqzgGdf4Ud&Aq5f94vfLwxy;9ytH zY<7HQr>lC`-JO2K-OHfhUJT~2Q6t1d9txV1=4oQK{iG z|NgJ5s;mC0A>=BujtmVE{0@^{*AVh3A!K;C^SosfA>+s!8R?ckK*++agls__h(Mx~ zkDpZOD^b1A;`9&4VB@I-yOkZG?XU%NaUCz^(=(7Ke={> zecg92-@j{f`i~`QXrcX+5S8m}&dx29_u3KN(_fm915@;lu&jrnnM9uR4>wA@K^>OP zs!8N!9mszhly^jJM^bsq&_@08co#1qpB^(Owfp-5 zUu6Z`pxa>k)H2(hwTx>CdIr~1t27ZS-kxp@VZQfkl%Yvu zjPD@M^CaRAzeTOz5zm{!xu9E$7|&xk>x8(&E5N;o>v9bKONgU5rlD;wQY_2cLojN) zf$dBrZr{F&j00gW@u<09lSevpPnAmLYGB?8Tz~e%?k_hvJt|{ec{||k-*NhlA6wFU z_)t%K#x84r<(W@#e<>+ue?7!^PudypN2c`;`vaCAQ<{7D{Wt2r>bh$7HiEv*&3$$~ z#++2`KIk8Os4sB7F{oR`vtx`s9K@6M8Dr7B{3fWt8?+(!veV)X*QW>Nxsjl570-5) z?F{4bon7*c`*HQqeiogn+FdH}25rdm$#J+6=Nt5p$+bI!x>Y=*-D0kjj_*)?d^_^` zj!E8tCwi`v)Gy8qA=u3-_zv2Ta|cVO$3mPY#qQOs?P<5$_%};F$uektVEmk(#hHkg z^FiLR>P*(34(^pE^#^0m2~!_?C{O&d4* + + + + + + Document + + + + + + Hello Bonjur + + diff --git a/skimmer/templates/pot.html b/skimmer/templates/pot.html new file mode 100644 index 0000000..dd58b3f --- /dev/null +++ b/skimmer/templates/pot.html @@ -0,0 +1,24 @@ + + + + + + + 🍲 Skimmer - Pot + + + + + + + + + +
+ +