Commit 41c190cb authored by Joseph Larralde's avatar Joseph Larralde
Browse files

added another getting started node project with express, socket.io and osc.js

parent 484b0523
**/.DS_Store
**/Thumbs.db
node_modules/
\ No newline at end of file
# Clients and Views
### presentation
**Clients and Views** is a starter project based on Node.js, Express.js, socket.io
and osc.js.
It provides two static html pages : `index.html` (the client) and `view.html`
(the view).
It implements a basic client-server architecture monitoring all the connected
clients and forwarding their information to all connected pages (clients and views).
Each time a new client connects to the server (automatic on page load), updates
its state, or disconnects from the server (automatic on page close), every other
connected pages (clients and views) get notified so they can display the current
global state.
All the initialization and communication via socket.io is abstracted by the
clientManager class (located in `public/js/client-manager.js`).
More views can be easily created to implement alternative visualizations,
based on the `view.html` file.
Alternative software clients can be developed to provide alternative renderings
of the global state.
See `pd/alternative-view-osc-receiver.pd` for an example of how to receive the
current state via the OSC protocol in pure-data.
### getting started
- From this folder (`clients-and-views`), type `npm install`.
- Start the server with the `node index.js` command.
- You can now visit `http://localhost:8081/view` to see a view, and open new
clients by visiting `http://localhost:8081`.
\ No newline at end of file
var osc = require("osc"),
express = require("express"),
io = require('socket.io');
var cwd = process.cwd();
//======================== setup local osc communication =====================//
var udpPort = new osc.UDPPort({
localAddress: "127.0.0.1",
localPort: 7400,
remoteAddress: "127.0.0.1",
remotePort: 7500,
});
udpPort.on("message", function (oscMessage) {
console.log(oscMessage);
});
udpPort.open();
//========================= create express-based server ======================//
var appResources = cwd + "/public",
app = express(),
server = app.listen(8081);
app.use(express.static('public', {
extensions: ['html']
}));
// local storage of useful data
var sockets = new Set();
var clients = new Map();
// define colors for interpolation here ([R, G, B]) :
var colors = [
[
Math.random() * 255,
Math.random() * 255,
Math.random() * 255
],
[
Math.random() * 255,
Math.random() * 255,
Math.random() * 255
]
];
// color is interpolated according to x position :
var interpColors = function(x) {
return [
colors[0][0] * x + colors[1][0] * (1 - x),
colors[0][1] * x + colors[1][1] * (1 - x),
colors[0][2] * x + colors[1][2] * (1 - x)
];
}
//==================== create socket.io websocket server =====================//
var socket = io.listen(server);
socket.on('connection', function(s) {
s.on('message', function(msg, val) {
switch(msg) {
case 'init':
s.clientType = val.clientType;
if (s.clientType === 'client') {
var c = {
id: s.id,
x: Math.random(),
y: Math.random(),
}
c.color = interpColors(c.x);
clients.set(s.id, c);
s.emit('updateMe', c);
notify('addClient', c);
}
// send all clients info on init for any client type
for (var client of clients.values()) {
s.emit('addClient', client);
}
sockets.add(s);
break;
case 'update':
if (s.clientType === 'client') {
var c = clients.get(s.id);
c.x = val.x;
c.y = val.y;
c.color = interpColors(val.x);
s.emit('updateMe', c);
notify('updateClient', c);
}
break;
}
});
s.on('disconnect', function() {
if (s.clientType === 'client') {
notify('removeClient', clients.get(s.id));
clients.delete(s.id);
}
sockets.delete(s);
});
});
function notify(command, client) {
for (var sock of sockets.values()) {
sock.emit(command, client);
}
// this sends all the info to localhost via osc
// (see ./pd/alternative-view-osc-receiver.pd)
udpPort.send({
address: `/${command}`,
args: [ client.id, client.x, client.y ],
});
}
{
"name": "clients-and-views",
"version": "1.0.0",
"description": "a simple 2 pages (client and view) web app, based on socket.io and osc.js",
"main": "index.js",
"author": "joseph larralde",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "BSD-3-Clause",
"dependencies": {
"express": "^4.15.3",
"osc": "^2.2.0",
"socket.io": "^2.0.3"
}
}
#N canvas 228 289 793 464 10;
#X obj 303 108 oscparse;
#X obj 303 129 list trim;
#X obj 303 77 netreceive -u -b;
#X msg 303 56 listen 7500;
#X obj 303 162 route addClient updateClient removeClient;
#X obj 303 35 loadbang;
#X obj 303 258 unpack s f f;
#X symbolatom 303 282 10 0 0 0 - - -, f 10;
#X floatatom 303 303 5 0 0 0 - - -, f 5;
#X floatatom 338 303 5 0 0 0 - - -, f 5;
#X obj 384 258 unpack s f f;
#X symbolatom 384 282 10 0 0 0 - - -, f 10;
#X floatatom 384 303 5 0 0 0 - - -, f 5;
#X floatatom 419 303 5 0 0 0 - - -, f 5;
#X obj 465 258 unpack s f f;
#X symbolatom 465 282 10 0 0 0 - - -, f 10;
#X floatatom 465 303 5 0 0 0 - - -, f 5;
#X floatatom 500 303 5 0 0 0 - - -, f 5;
#X connect 0 0 1 0;
#X connect 1 0 4 0;
#X connect 2 0 0 0;
#X connect 3 0 2 0;
#X connect 4 0 6 0;
#X connect 4 1 10 0;
#X connect 4 2 14 0;
#X connect 5 0 3 0;
#X connect 6 0 7 0;
#X connect 6 1 8 0;
#X connect 6 2 9 0;
#X connect 10 0 11 0;
#X connect 10 1 12 0;
#X connect 10 2 13 0;
#X connect 14 0 15 0;
#X connect 14 1 16 0;
#X connect 14 2 17 0;
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script src="js/client-manager.js"></script>
<script src="js/osc-browser.min.js"></script>
<script src="js/socket.io.js"></script>
<script src="js/p5.min.js"></script>
</head>
<body>
<script language="javascript" type="text/javascript">
var manager = new clientManager('client');
//============================== p5 methods ================================//
function setup(){
createCanvas(window.innerWidth, window.innerHeight);
rectMode(CENTER);
ellipseMode(CENTER);
}
function draw() {
background(255, 34, 93);
noStroke();
if (mouseIsPressed) {
manager.update({ x: mouseX / window.innerWidth, y: mouseY / window.innerHeight });
}
fill(manager.me.color);
ellipse(manager.me.x * window.innerWidth, manager.me.y * window.innerHeight, 100, 100);
}
</script>
</body>
</html>
\ No newline at end of file
//=========================================//
// DEFINITION OF THE clientManager CLASS : //
//=========================================//
function clientManager(clientType, callback = null) {
// initialize to a hidden place out of the canvas
this.me = {
x: -1000, y: -1000, color: [0, 0, 0]
};
this.clients = [];
this.socket = io();
this.socket.send('init', { clientType: clientType });
// this is sent back by the server when we send 'init' with clientType 'client'
this.socket.on('updateMe', (function(client) {
this.me = client;
}).bind(this));
this.socket.on('addClient', (function(client) {
this.clients.push(client);
}).bind(this));
this.socket.on('updateClient', (function(client) {
for (var i = 0; i < this.clients.length; i++) {
if (this.clients[i].id === client.id) {
this.clients[i] = client;
}
}
}).bind(this));
this.socket.on('removeClient', (function(client) {
for (var i = 0; i < this.clients.length; i++) {
if (this.clients[i].id === client.id) {
this.clients.splice(i, 1);
}
}
}).bind(this));
}
// we update client data here from user input
clientManager.prototype.update = function(data) {
for (var key in data) {
this.me[key] = data[key];
}
this.socket.send('update', this.me);
};
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script src="js/client-manager.js"></script>
<script src="js/osc-browser.min.js"></script>
<script src="js/socket.io.js"></script>
<script src="js/p5.min.js"></script>
</head>
<body>
<script language="javascript" type="text/javascript">
var manager = new clientManager('view');
//============================== p5 methods ================================//
function setup(){
createCanvas(window.innerWidth, window.innerHeight);
rectMode(CENTER);
ellipseMode(CENTER);
}
function draw() {
background(255, 34, 93);
noStroke();
for (var client in manager.clients) {
var c = manager.clients[client];
fill(c.color);
ellipse(c.x * window.innerWidth, c.y * window.innerHeight, 100, 100);
}
}
</script>
</body>
</html>
\ No newline at end of file
...@@ -6,8 +6,8 @@ var cwd = process.cwd(); ...@@ -6,8 +6,8 @@ var cwd = process.cwd();
// Bind to a UDP socket to listen for incoming OSC events. // Bind to a UDP socket to listen for incoming OSC events.
var udpPort = new osc.UDPPort({ var udpPort = new osc.UDPPort({
// localAddress: "0.0.0.0", localAddress: "0.0.0.0",
localAddress: "127.0.0.1", // localAddress: "127.0.0.1",
localPort: 7400, localPort: 7400,
remoteAddress: "127.0.0.1", remoteAddress: "127.0.0.1",
remotePort: 7500, remotePort: 7500,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment