improvements on osc input
This commit is contained in:
33
ToposServer/OSCtoTopos.js
Normal file
33
ToposServer/OSCtoTopos.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const WebSocket = require("ws");
|
||||||
|
const osc = require("osc");
|
||||||
|
|
||||||
|
const cleanIncomingOSC = (oscMsg) => {
|
||||||
|
let data = oscMsg.args;
|
||||||
|
// Remove information about type of data
|
||||||
|
data = data.map((item) => {
|
||||||
|
return item.value;
|
||||||
|
})
|
||||||
|
return {data: data, address: oscMsg.address};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==============================================
|
||||||
|
// Receiving and forwarding OSC UDP messages
|
||||||
|
// Create an osc.js UDP Port listening on port 57121.
|
||||||
|
console.log("> OSC Input: 127.0.0.1:30000");
|
||||||
|
const wss = new WebSocket.Server({ port: 3001 });
|
||||||
|
var udpPort = new osc.UDPPort({
|
||||||
|
localAddress: "0.0.0.0",
|
||||||
|
localPort: 30000,
|
||||||
|
metadata: true
|
||||||
|
});
|
||||||
|
udpPort.on("message", function (oscMsg, timeTag, info) {
|
||||||
|
console.log(`> Incoming OSC to ${oscMsg.address}:`, oscMsg.args.map(
|
||||||
|
(item) => {return item.value})
|
||||||
|
);
|
||||||
|
wss.clients.forEach(client => {
|
||||||
|
if (client.readyState === WebSocket.OPEN) {
|
||||||
|
client.send(JSON.stringify(cleanIncomingOSC(oscMsg)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
udpPort.open();
|
||||||
81
ToposServer/ToposToOSC.js
Normal file
81
ToposServer/ToposToOSC.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
const WebSocket = require("ws");
|
||||||
|
const osc = require("osc");
|
||||||
|
|
||||||
|
// Listening to WebSocket messages
|
||||||
|
const wss = new WebSocket.Server({ port: 3000 });
|
||||||
|
|
||||||
|
// Setting up for message broadcasting
|
||||||
|
wss.on("connection", function (ws) {
|
||||||
|
console.log("> Client connected");
|
||||||
|
ws.on("message", function (data) {
|
||||||
|
try {
|
||||||
|
const message = JSON.parse(data);
|
||||||
|
sendOscMessage(
|
||||||
|
formatAndTypeMessage(message),
|
||||||
|
message.address,
|
||||||
|
message.port
|
||||||
|
);
|
||||||
|
console.log(`> Message sent to ${message.address}:${message.port}: ${JSON.stringify(message.args)}`)
|
||||||
|
} catch (error) {
|
||||||
|
console.error("> Error processing message:", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
wss.on("error", function (error) {
|
||||||
|
console.error("> Server error:", error);
|
||||||
|
})
|
||||||
|
|
||||||
|
wss.on("close", function () {
|
||||||
|
// Close the websocket server
|
||||||
|
wss.close();
|
||||||
|
console.log("> Closing websocket server")
|
||||||
|
});
|
||||||
|
|
||||||
|
let udpPort = new osc.UDPPort({
|
||||||
|
localAddress: "0.0.0.0",
|
||||||
|
localPort: 3000,
|
||||||
|
metadata: true,
|
||||||
|
remoteAddress: "0.0.0.0",
|
||||||
|
remotePort: 57120,
|
||||||
|
});
|
||||||
|
udpPort.on("error", function (error) {
|
||||||
|
console.error("> UDP Port error:", error);
|
||||||
|
});
|
||||||
|
udpPort.on("ready", function () {
|
||||||
|
//console.log(`> UDP Receive: ${udpPort.options.localPort}`);
|
||||||
|
console.log("> WebSocket server: 127.0.0.1:3000");
|
||||||
|
});
|
||||||
|
|
||||||
|
udpPort.open();
|
||||||
|
|
||||||
|
function sendOscMessage(message, address, port) {
|
||||||
|
try {
|
||||||
|
udpPort.options.remotePort = port
|
||||||
|
message.address = address;
|
||||||
|
udpPort.send(message);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("> Error sending OSC message:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatAndTypeMessage = (message) => {
|
||||||
|
let newMessage = {};
|
||||||
|
delete message.args['address'];
|
||||||
|
delete message.args['port'];
|
||||||
|
newMessage.address = message.address;
|
||||||
|
newMessage.timestamp = osc.timeTag(message.timetag);
|
||||||
|
|
||||||
|
args = [...Object.entries(message.args)].flat().map((arg) => {
|
||||||
|
if (typeof arg === 'string')
|
||||||
|
return {type: 's', value: arg};
|
||||||
|
if (typeof arg === 'number')
|
||||||
|
return {type: 'f', value: arg};
|
||||||
|
if (typeof arg === 'boolean')
|
||||||
|
return value ? {type: 's', value: 1} : {type: 's', value: 0};
|
||||||
|
})
|
||||||
|
|
||||||
|
newMessage.args = args
|
||||||
|
|
||||||
|
return newMessage;
|
||||||
|
}
|
||||||
14
ToposServer/banner.js
Normal file
14
ToposServer/banner.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
var pjson = require('./package.json');
|
||||||
|
let banner = `
|
||||||
|
┏┳┓ ┏┓┏┓┏┓
|
||||||
|
┃ ┏┓┏┓┏┓┏ ┃┃┗┓┃
|
||||||
|
┻ ┗┛┣┛┗┛┛ ┗┛┗┛┗┛
|
||||||
|
┛
|
||||||
|
${pjson.version}\n`
|
||||||
|
function greet() {
|
||||||
|
console.log(banner)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
greet: greet
|
||||||
|
}
|
||||||
@ -1,114 +1,9 @@
|
|||||||
const WebSocket = require("ws");
|
const WebSocket = require("ws");
|
||||||
const osc = require("osc");
|
const osc = require("osc");
|
||||||
var pjson = require('./package.json');
|
|
||||||
|
|
||||||
let banner = `
|
require('./banner').greet();
|
||||||
┏┳┓ ┏┓┏┓┏┓
|
// Topos to OSC
|
||||||
┃ ┏┓┏┓┏┓┏ ┃┃┗┓┃
|
require('./ToposToOSC')
|
||||||
┻ ┗┛┣┛┗┛┛ ┗┛┗┛┗┛
|
// OSC to Topos
|
||||||
┛
|
require("./OSCtoTopos")
|
||||||
${pjson.version}\n`
|
|
||||||
|
|
||||||
console.log(banner)
|
|
||||||
console.log("Listening to: ws://localhost:3000. Open Topos.\n");
|
|
||||||
|
|
||||||
// Listening to WebSocket messages
|
|
||||||
const wss = new WebSocket.Server({ port: 3000 });
|
|
||||||
|
|
||||||
// Sending WebSocket messages
|
|
||||||
const inputWss = new WebSocket.Server({ port: 3001 });
|
|
||||||
|
|
||||||
inputWss.on("connection", function (ws) {
|
|
||||||
inputWss.clients.forEach(function each(client) {
|
|
||||||
// Send message to all clients except sender
|
|
||||||
if (client !== ws && client.readyState === WebSocket.OPEN) {
|
|
||||||
client.send("New client connected");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
// Setting up for message broadcasting
|
|
||||||
wss.on("connection", function (ws) {
|
|
||||||
console.log("> Client connected");
|
|
||||||
ws.on("message", function (data) {
|
|
||||||
try {
|
|
||||||
const message = JSON.parse(data);
|
|
||||||
sendOscMessage(
|
|
||||||
formatAndTypeMessage(message),
|
|
||||||
message.address,
|
|
||||||
message.port
|
|
||||||
);
|
|
||||||
console.log(`> Message sent to ${message.address}:${message.port}: ${JSON.stringify(message.args)}`)
|
|
||||||
} catch (error) {
|
|
||||||
console.error("> Error processing message:", error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
wss.on("error", function (error) {
|
|
||||||
console.error("> Server error:", error);
|
|
||||||
})
|
|
||||||
|
|
||||||
wss.on("close", function () {
|
|
||||||
// Close the websocket server
|
|
||||||
wss.close();
|
|
||||||
console.log("> Closing websocket server")
|
|
||||||
});
|
|
||||||
|
|
||||||
// Setting up for OSC messages
|
|
||||||
|
|
||||||
let udpPort = new osc.UDPPort({
|
|
||||||
localAddress: "0.0.0.0",
|
|
||||||
localPort: 3000,
|
|
||||||
metadata: true,
|
|
||||||
remoteAddress: "0.0.0.0",
|
|
||||||
remotePort: 57120,
|
|
||||||
});
|
|
||||||
|
|
||||||
udpPort.on("error", function (error) {
|
|
||||||
console.error("> UDP Port error:", error);
|
|
||||||
});
|
|
||||||
|
|
||||||
udpPort.on("ready", function () {
|
|
||||||
console.log(`> UDP Port opened on port ${udpPort.options.localPort}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
udpPort.open();
|
|
||||||
|
|
||||||
function sendOscMessage(message, address, port) {
|
|
||||||
try {
|
|
||||||
udpPort.options.remotePort = port
|
|
||||||
message.address = address;
|
|
||||||
udpPort.send(message);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("> Error sending OSC message:", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const formatAndTypeMessage = (message) => {
|
|
||||||
let newMessage = {};
|
|
||||||
delete message.args['address'];
|
|
||||||
delete message.args['port'];
|
|
||||||
newMessage.address = message.address;
|
|
||||||
newMessage.timestamp = osc.timeTag(message.timetag);
|
|
||||||
|
|
||||||
args = [...Object.entries(message.args)].flat().map((arg) => {
|
|
||||||
if (typeof arg === 'string')
|
|
||||||
return {type: 's', value: arg};
|
|
||||||
if (typeof arg === 'number')
|
|
||||||
return {type: 'f', value: arg};
|
|
||||||
if (typeof arg === 'boolean')
|
|
||||||
return value ? {type: 's', value: 1} : {type: 's', value: 0};
|
|
||||||
})
|
|
||||||
|
|
||||||
newMessage.args = args
|
|
||||||
|
|
||||||
return newMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log(formatAndTypeMessage({
|
|
||||||
// address: '/baba',
|
|
||||||
// port: 2000,
|
|
||||||
// args: { s: 'fhardkick', dur: 0.5, port: 2000, address: 'baba' },
|
|
||||||
// timetag: 1701696184583
|
|
||||||
// }))
|
|
||||||
|
|||||||
14
src/API.ts
14
src/API.ts
@ -1,5 +1,5 @@
|
|||||||
import { EditorView } from "@codemirror/view";
|
import { EditorView } from "@codemirror/view";
|
||||||
import { sendToServer, type OSCMessage } from "./IO/OSC";
|
import { sendToServer, type OSCMessage, oscMessages } from "./IO/OSC";
|
||||||
import { getAllScaleNotes, nearScales, seededRandom } from "zifferjs";
|
import { getAllScaleNotes, nearScales, seededRandom } from "zifferjs";
|
||||||
import {
|
import {
|
||||||
MidiCCEvent,
|
MidiCCEvent,
|
||||||
@ -2109,6 +2109,18 @@ export class UserAPI {
|
|||||||
} as OSCMessage);
|
} as OSCMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getOSC = (address?: string): any[] => {
|
||||||
|
/**
|
||||||
|
* Give access to incoming OSC messages. If no address is specified, returns the raw oscMessages array. If an address is specified, returns only the messages who contain the address and filter the address itself.
|
||||||
|
*/
|
||||||
|
if (address) {
|
||||||
|
let messages = oscMessages.filter((msg) => msg.address === address);
|
||||||
|
messages = messages.map((msg) => msg.data);
|
||||||
|
return messages
|
||||||
|
} else {
|
||||||
|
return oscMessages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// Transport functions
|
// Transport functions
|
||||||
|
|||||||
@ -9,9 +9,18 @@ export interface OSCMessage {
|
|||||||
export let outputSocket = new WebSocket("ws://localhost:3000");
|
export let outputSocket = new WebSocket("ws://localhost:3000");
|
||||||
export let inputSocket = new WebSocket("ws://localhost:3001");
|
export let inputSocket = new WebSocket("ws://localhost:3001");
|
||||||
|
|
||||||
inputSocket.onmessage= function (event) {
|
// Queue of 1000 last messages
|
||||||
console.log("Received: ", event.data);
|
export let oscMessages : any[] = [];
|
||||||
}
|
|
||||||
|
inputSocket.addEventListener('message', (event) => {
|
||||||
|
let data = JSON.parse(event.data);
|
||||||
|
if (oscMessages.length > 1000) {
|
||||||
|
oscMessages.shift();
|
||||||
|
}
|
||||||
|
oscMessages.push(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
outputSocket.onopen = function (event) {
|
outputSocket.onopen = function (event) {
|
||||||
@ -20,7 +29,7 @@ outputSocket.onopen = function (event) {
|
|||||||
outputSocket.send(
|
outputSocket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
address: "/successful_connexion",
|
address: "/successful_connexion",
|
||||||
args: true,
|
port: 3000, args: {}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -16,9 +16,12 @@ To use **OSC** with Topos, you will need to download the <ic>ToposServer</ic> by
|
|||||||
- 3) Start the server using <ic>npm start</ic>.
|
- 3) Start the server using <ic>npm start</ic>.
|
||||||
- 4) Open the <ic>Topos</ic> application in your web browser.
|
- 4) Open the <ic>Topos</ic> application in your web browser.
|
||||||
|
|
||||||
|
This server can be used both for **OSC** _input_ and _output_.
|
||||||
|
|
||||||
## Input
|
## Input
|
||||||
|
|
||||||
|
Send an **OSC** message to the server at the address <ic>localhost:30000</ic>. You will receive your message in Topos as an Array containing the address and data of your message.
|
||||||
|
|
||||||
## Output
|
## Output
|
||||||
|
|
||||||
Once the server is loaded, you are ready to send an **OSC** message:
|
Once the server is loaded, you are ready to send an **OSC** message:
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { scriptBlinkers } from "./Visuals/Blinkers";
|
|||||||
import { javascript } from "@codemirror/lang-javascript";
|
import { javascript } from "@codemirror/lang-javascript";
|
||||||
import { markdown } from "@codemirror/lang-markdown";
|
import { markdown } from "@codemirror/lang-markdown";
|
||||||
import { Extension } from "@codemirror/state";
|
import { Extension } from "@codemirror/state";
|
||||||
import { outputSocket } from "./IO/OSC";
|
import { outputSocket, oscMessages } from "./IO/OSC";
|
||||||
import {
|
import {
|
||||||
initializeSelectedUniverse,
|
initializeSelectedUniverse,
|
||||||
AppSettings,
|
AppSettings,
|
||||||
@ -206,6 +206,7 @@ export class Editor {
|
|||||||
// Loading universe from URL (if needed)
|
// Loading universe from URL (if needed)
|
||||||
loadUniverserFromUrl(this);
|
loadUniverserFromUrl(this);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getBuffer(type: string): any {
|
private getBuffer(type: string): any {
|
||||||
|
|||||||
Reference in New Issue
Block a user