Skip to content

Commit

Permalink
add websocket based remote control
Browse files Browse the repository at this point in the history
  • Loading branch information
andir committed Oct 24, 2024
1 parent 24fc657 commit 2106f7b
Show file tree
Hide file tree
Showing 8 changed files with 6,305 additions and 58 deletions.
5 changes: 4 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[*.html]
indent_type = space
tab_width = 4
[*.js]
indent_type = space
tab_width = 4
tab_width = 4
4 changes: 2 additions & 2 deletions code.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const FPS = 60;
const SCHEDULE_URL = "https://talks.nixcon.org/nixcon-2024/schedule/export/schedule.json";
const SCHEDULE_URL = "/schedule.json";
const SPONSORS = {};

function splitLines(context, text, maxWidth, lineHeight) {
Expand Down Expand Up @@ -70,7 +70,7 @@ class Animator {
console.log('Total size', size);
this.chunks = [];
var url = URL.createObjectURL(blob);
this.video.src = url;
if (this.video) this.video.src = url;
};
this.recorder.ondataavailable = (e) => {
console.log('recording data available', e.data.size, this.recorder.state)
Expand Down
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 1 addition & 12 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,7 @@
};
in {
devShells.default = pkgs.mkShell {
nativeBuildInputs = [ pkgs.nodejs ];
};
packages.default = pkgs.npmlock2nix.v2.build {
nodejs = pkgs.nodejs;
name = "nixcon-2023";
src = ./.;

preBuild = "export HOME=$(pwd)";
installPhase = ''
cp -rv dist $out
touch $out/.nojekyll
'';
nativeBuildInputs = [ pkgs.nodejs (pkgs.python3.withPackages (p: with p; [ flask flask-socketio requests ])) ];
};
});
}
100 changes: 63 additions & 37 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<title>NixCon 2023 intro generator</title>
<title>NixCon 2024 intro generator</title>
<link rel="preload" href="https://2023.nixcon.org/fonts/Behrensschrift-SH.otf" as="font" type="font/otf" crossorigin>
<style>
body { background-color: black; }
Expand Down Expand Up @@ -35,54 +35,80 @@
<canvas id="canvas" height="1080" width="1920"></canvas>
<video autoplay controls download id="video"></video>

<script type="application/javascript" src="socket.io.js"></script>
<script type="application/javascript" src="code.js"></script>
<script type="application/javascript">
const socket = io();
socket.on("connect", () => {
console.log("connected");
});
socket.on("disconnect", () => {
console.log("disconnected");
});

const talks = new Object;
loadSchedule().then((ts) => ts.forEach((t) => {
talks[t.id] = t;
}));

socket.on("talk", (talk_id) => {
console.log("Received message:", talk_id);
const talk = talks[talk_id];
const animation = new IntroAnimation("logo.svg", talk.title, "" + talk.persons.map((p) => p.public_name));
var animator = new Animator(document.getElementById('canvas'), null, width, height, animation);

animator.run().then(() => {
button.disabled = false;
console.log('Done recording');
animator = null;
});
});


var fontReadyP = (new FontFace('oxanium', 'url(https://2024.nixcon.org/fonts/oxanium-bold.woff2) format(woff2)').load().then((f) => {
console.log('font loaded');
document.fonts.add(f);
}));
const width = 1920, height = 1080;
//var animation = new Animation("template.svg");
//var outroAnimation = ;

var init = false;

var button = document.getElementById('button');
button.disabled = true;

const what = document.getElementById('what');
const talksList = document.getElementById('talks');
loadSchedule().then((talks) => talks.forEach((t) => {
const ele = document.createElement('option');
ele.talk = t;
ele.value = t.id;
ele.text = t.id + " - " + t.title;
talksList.appendChild(ele);
}));
//var init = false;

document.onreadystatechange = () => {
if (init) return;
init =true;
button.disabled = false;
button.onclick = () => fontReadyP.then(() => {
button.disabled = true;
//var button = document.getElementById('button');
//button.disabled = true;

const w = what.selectedOptions[0].value;
const talk = talksList.selectedOptions[0].talk;
//const what = document.getElementById('what');
//const talksList = document.getElementById('talks');
//loadSchedule().then((talks) => talks.forEach((t) => {
// const ele = document.createElement('option');
// ele.talk = t;
// ele.value = t.id;
// ele.text = t.id + " - " + t.title;
// talksList.appendChild(ele);
//}));

var animation;
if (w == "intro") animation = new IntroAnimation("logo.svg", talk.title, "" + talk.persons.map((p) => p.public_name));
if (w == "outro") animation = new OutroAnimation("template.svg", "by.svg");
if (w == "pause") animation = new PauseAnimation("template.svg"); // FIXME
//document.onreadystatechange = () => {
// if (init) return;
// init =true;
// button.disabled = false;
// button.onclick = () => fontReadyP.then(() => {
// button.disabled = true;

var animator = new Animator(document.getElementById('canvas'), document.getElementById('video'), width, height, animation);
// const w = what.selectedOptions[0].value;
// const talk = talksList.selectedOptions[0].talk;

animator.run().then(() => {
button.disabled = false;
console.log('Done recording');
});
});
}
// var animation;
// if (w == "intro") animation = new IntroAnimation("logo.svg", talk.title, "" + talk.persons.map((p) => p.public_name));
// //if (w == "outro") animation = new OutroAnimation("template.svg", "by.svg");
// //if (w == "pause") animation = new PauseAnimation("template.svg"); // FIXME

// var animator = new Animator(document.getElementById('canvas'), document.getElementById('video'), width, height, animation);

// animator.run().then(() => {
// button.disabled = false;
// console.log('Done recording');
// animator = null;
// });
// });
//}
</script>
</body>
</html>
60 changes: 60 additions & 0 deletions serve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from flask import Flask, request, send_from_directory, send_file, render_template
from flask_socketio import SocketIO, emit
import time
import requests


app = Flask("intros")
socketio = SocketIO(app, debug=True, cors_allowed_origins='*')

@app.route('/', methods=['GET'])
def index():
return send_file('index.html')

@app.route('/fonts/<path:path>', methods=['GET'])
def fonts(path):
return send_from_directory('fonts', path)

@app.route('/code.js', methods=['GET'])
def code():
return send_file('code.js')

@app.route('/socket.io.js', methods=['GET'])
def socketio_js():
return send_file('socket.io.js')

SCHEDULE_URL = "https://talks.nixcon.org/nixcon-2024/schedule/export/schedule.json"

cached_schedule = (None, None)

def load_schedule(force=False):
global cached_schedule
last_fetch = cached_schedule[0]
now = time.time()
if last_fetch is None or last_fetch + 15 < now:
force = True

if force:
d = requests.get(SCHEDULE_URL).json()
cached_schedule = (now, d)

return cached_schedule[1]

@app.route('/schedule.json')
def schedule():
return load_schedule()

@app.route('/logo.svg')
def logo():
return send_file('logo.svg')

@app.route('/admin', methods=['GET'])
def admin_get():
return render_template("admin.html")

@socketio.on("talk")
def on_talk(talk_id):
socketio.emit("talk", talk_id)

if __name__ == "__main__":
socketio.run(app)
Loading

0 comments on commit 2106f7b

Please sign in to comment.