added P5 and pb

This commit is contained in:
ojack
2022-02-11 17:30:00 +01:00
parent cfe1f9ed76
commit eda9ea84dd
5 changed files with 30942 additions and 21348 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,138 +0,0 @@
/* globals sessionStorage */
// Extends rtc-patch-bay to include support for nicknames and persistent session storage
var PatchBay = require('./rtc-patch-bay.js')
//var PatchBay = require('./../../../../rtc-patch-bay')
var inherits = require('inherits')
var PBLive = function () {
this.session = {}
// lookup tables for converting id to nickname
this.nickFromId = {}
this.idFromNick = {}
this.loadFromStorage()
}
// inherits from PatchBay module
inherits(PBLive, PatchBay)
PBLive.prototype.init = function (stream, opts) {
this.settings = {
server: opts.server || 'https://patch-bay.glitch.me/',
room: opts.room || 'patch-bay',
stream: stream
}
this.makeGlobal = opts.makeGlobal || true
this.setPageTitle = opts.setTitle || true
if (this.session.id) this.settings.id = this.session.id
PatchBay.call(this, this.settings)
if (this.makeGlobal) window.pb = this
this.on('ready', () => {
if (!this.nick) {
if (this.session.nick) {
this.setName(this.session.nick)
} else {
this.session.id = this.id
this.setName(this.session.id)
}
}
console.log('connected to server ' + this.settings.server + ' with name ' + this.settings.id)
})
// received a broadcast
this.on('broadcast', this._processBroadcast.bind(this))
this.on('new peer', this.handleNewPeer.bind(this))
window.onbeforeunload = () => {
this.session.id = window.pb.id
this.session.nick = this.nick
sessionStorage.setItem('pb', JSON.stringify(this.session))
}
var self = this
this.on('stream', function (id, stream) {
console.log('got stream!', id, stream)
const video = document.createElement('video')
if ('srcObject' in video) {
video.srcObject = stream
} else {
// Avoid using this in new browsers, as it is going away.
video.src = window.URL.createObjectURL(stream)
}
// video.src = window.URL.createObjectURL(stream)
video.addEventListener('loadedmetadata', () => {
// console.log("loaded meta22")
video.play()
self.video = video
self.emit('got video', self.nickFromId[id], video)
})
})
}
PBLive.prototype.loadFromStorage = function () {
if (sessionStorage.getItem('pb') !== null) {
this.session = JSON.parse(sessionStorage.getItem('pb'))
}
}
PBLive.prototype.initSource = function (nick, callback) {
this.initConnectionFromId(this.idFromNick[nick], callback)
// this.peers[this.idFromNick[nick]].streamCallback = callback
}
// default nickname is just peer id.
// to do: save nickname information between sessions
PBLive.prototype.handleNewPeer = function (peer) {
// console.log("new peer", peer)
this.nickFromId[peer] = peer
this.idFromNick[peer] = peer
// console.log("THIS IS THE PEER", peer)
// to do: only send to new peer, not to all
if (this.nick) {
this.broadcast({
type: 'update-nick',
id: this.id,
nick: this.nick
})
}
}
PBLive.prototype.list = function () {
var l = Object.keys(this.idFromNick)
//console.log(l)
return Object.keys(this.idFromNick)
}
// choose an identifying name
PBLive.prototype.setName = function (nick) {
this.broadcast({
type: 'update-nick',
id: this.id,
nick: nick,
previous: this.nick
})
this.nick = nick
if (this.setPageTitle) document.title = nick
}
PBLive.prototype._processBroadcast = function (data) {
if (data.type === 'update-nick') {
if (data.previous !== data.nick) {
delete this.idFromNick[this.nickFromId[data.id]]
this.nickFromId[data.id] = data.nick
this.idFromNick[data.nick] = data.id
if (data.previous) {
//console.log(data.previous + ' changed to ' + data.nick)
} else {
//console.log('connected to ' + data.nick)
}
}
}
}
// PBExtended.prototype.
module.exports = PBLive

View File

@@ -1,251 +0,0 @@
// Module for handling connections to multiple peers.
var io = require('socket.io-client')
var SimplePeer = require('simple-peer')
var extend = Object.assign
var events = require('events').EventEmitter
var inherits = require('inherits')
const shortid = require('shortid')
var PatchBay = function (options) {
// connect to websocket signalling server. To DO: error validation
this.signaller = io(options.server)
//assign unique id to this peer, or use id passed in
this.id = options.id || shortid.generate()
this.stream = options.stream || null
//options to be sent to simple peer
this._peerOptions = options.peerOptions || {}
this._room = options.room
this.settings['shareMediaWhenRequested'] = true
this.settings['shareMediaWhenInitiating'] = false
this.settings['requestMediaWhenInitiating'] = true
this.settings['autoconnect'] = false
//object containing ALL peers in room
this.peers = {}
//object containing peers connected via webrtc
this.rtcPeers = {}
// Handle events from signalling server
this.signaller.on('ready', this._readyForSignalling.bind(this))
// this.signaller.on('peers', )
// this.signaller.on('signal', this._handleSignal.bind(this))
this.signaller.on('message', this._handleMessage.bind(this))
// Received message via websockets to all peers in room
this.signaller.on('broadcast', this._receivedBroadcast.bind(this))
// emit 'join' event to signalling server
this.signaller.emit('join', this._room, {uuid: this.id})
this.signaller.on('new peer', this._newPeer.bind(this))
}
// inherits from events module in order to trigger events
inherits(PatchBay, events)
// send data to all connected peers via data channels
PatchBay.prototype.sendToAll = function (data) {
Object.keys(this.rtcPeers).forEach(function (id) {
this.rtcPeers[id].send(data)
}, this)
}
// sends to peer specified b
PatchBay.prototype.sendToPeer = function (peerId, data) {
if (peerId in this.rtcPeers) {
this.rtcPeers[peerId].send(data)
}
}
PatchBay.prototype.reinitAll = function(){
Object.keys(this.rtcPeers).forEach(function (id) {
this.reinitPeer(id)
}.bind(this))
// this._connectToPeers.bind(this)
}
PatchBay.prototype.initRtcPeer = function(id, opts) {
this.emit('new peer', {id: id})
var newOptions = opts
// console.log()
if(this.iceServers) {
opts['config'] = {
iceServers: this.iceServers
}
}
if(opts.initiator === true) {
if (this.stream != null) {
if(this.settings.shareMediaWhenInitiating === true){
newOptions.stream = this.stream
}
}
if(this.settings.requestMediaWhenInitiating === true){
newOptions.offerConstraints = {
offerToReceiveVideo: true,
offerToReceiveAudio: true
}
}
} else {
if(this.settings.shareMediaWhenRequested === true){
if (this.stream != null) {
newOptions.stream = this.stream
}
}
}
var options = extend(this._peerOptions, newOptions)
//console.log("OPTIONS", options)
this.rtcPeers[id] = new SimplePeer(options)
this._attachPeerEvents(this.rtcPeers[id], id)
}
PatchBay.prototype.reinitRtcConnection = function(id, opts){
// Because renegotiation is not implemeneted in SimplePeer, reinitiate connection when configuration has changed
this.rtcPeers[id]._destroy(null, function(e){
this.initRtcPeer(id, {
stream: this.stream,
initiator: true
})
}.bind(this))
}
// //new peer connected to signalling server
PatchBay.prototype._newPeer = function (peer){
// this.connectedIds.push(peer)
// Configuration for specified peer.
// Individual configuration controls whether will receive media from
// and/or send media to a specific peer.
this.peers[peer] = {
rtcPeer: null
}
this.emit('new peer', peer)
// this.emit('updated peer list', this.connectedIds)
}
// // Once the new peer receives a list of connected peers from the server,
// // creates new simple peer object for each connected peer.
PatchBay.prototype._readyForSignalling = function ({ peers, servers }) {
// console.log("received peer list", _t, this.peers)
peers.forEach((peer) => {
this._newPeer(peer)
})
// if received ice and turn server information from signalling server, use in establishing
if(servers) {
this.iceServers = servers
}
// this.peers = peers
this.emit('ready')
}
// Init connection to RECEIVE video
PatchBay.prototype.initConnectionFromId = function(id, callback){
// console.log("initianing connection")
if(id in this.rtcPeers){
console.log("Already connected to..", id, this.rtcPeers)
//if this peer was originally only sending a stream (not receiving), recreate connecting but this time two-way
if(this.rtcPeers[id].initiator===false){
this.reinitRtcConnection(id)
} else {
//already connected, do nothing
}
} else {
this.initRtcPeer(id, {
initiator: true
})
}
}
// receive signal from signalling server, forward to simple-peer
PatchBay.prototype._handleMessage = function (data) {
// if there is currently no peer object for a peer id, that peer is initiating a new connection.
if (data.type === 'signal'){
this._handleSignal(data)
} else {
this.emit('message', data)
}
}
// receive signal from signalling server, forward to simple-peer
PatchBay.prototype._handleSignal = function (data) {
// if there is currently no peer object for a peer id, that peer is initiating a new connection.
if (!this.rtcPeers[data.id]) {
// this.emit('new peer', data)
// var options = extend({stream: this.stream}, this._peerOptions)
// this.rtcPeers[data.id] = new SimplePeer(options)
// this._attachPeerEvents(this.rtcPeers[data.id], data.id)
this.initRtcPeer(data.id, {initiator: false})
}
this.rtcPeers[data.id].signal(data.message)
}
// sendToAll send through rtc connections, whereas broadcast
// send through the signalling server. Useful in cases where
// not all peers are connected via webrtc with other peers
PatchBay.prototype._receivedBroadcast = function(data) {
//console.log("RECEIVED BROADCAST", data)
this.emit('broadcast', data)
}
//sends via signalling server
PatchBay.prototype.broadcast = function (data) {
this.signaller.emit('broadcast', data)
}
// handle events for each connected peer
PatchBay.prototype._attachPeerEvents = function (p, _id) {
p.on('signal', function (id, signal) {
// console.log('signal', id, signal)
// console.log("peer signal sending over sockets", id, signal)
// this.signaller.emit('signal', {id: id, signal: signal})
this.signaller.emit('message', {id: id, message: signal, type: 'signal'})
}.bind(this, _id))
p.on('stream', function (id, stream) {
this.rtcPeers[id].stream = stream
// console.log('E: stream', id, stream)
// console.log("received a stream", stream)
this.emit('stream', id, stream)
}.bind(this, _id))
p.on('connect', function (id) {
// console.log("connected to ", id)
this.emit('connect', id)
}.bind(this, _id))
p.on('data', function (id, data) {
// console.log('data', id)
this.emit('data', {id: id, data: JSON.parse(data)})
}.bind(this, _id))
p.on('close', function (id) {
//console.log('CLOSED')
delete (this.rtcPeers[id])
this.emit('close', id)
}.bind(this, _id))
p.on('error', function(e){
console.warn("simple peer error", e)
})
}
PatchBay.prototype._destroy = function () {
Object.values(this.rtcPeers).forEach( function (peer) {
peer.destroy()
})
this.signaller.close()
}
module.exports = PatchBay

View File

@@ -1,6 +1,10 @@
const html = require('choo/html')
const Component = require('choo/component')
const HydraSynth = require('hydra-synth')
const P5 = require('./../lib/p5-wrapper.js')
const PatchBay = require('./../lib/patch-bay/pb-live.js')
module.exports = class Hydra extends Component {
constructor (id, state, emit) {
@@ -10,10 +14,27 @@ module.exports = class Hydra extends Component {
}
load (element) {
const hydra = new HydraSynth({ detectAudio: true, canvas: element.querySelector("canvas")})
let isIOS =
(/iPad|iPhone|iPod/.test(navigator.platform) ||
(navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) &&
!window.MSStream;
let precisionValue = isIOS ? 'highp' : 'mediump'
const pb = new PatchBay()
const hydra = new HydraSynth({ pb: pb, detectAudio: true, canvas: element.querySelector("canvas"), precision: precisionValue})
console.log(hydra)
this.hydra = hydra
osc().out()
pb.init(hydra.captureStream, {
server: window.location.origin,
room: 'iclc'
})
window.P5 = P5
window.pb = pb
}
update (center) {

View File

@@ -2,22 +2,17 @@ const html = require('choo/html')
const info = require('./info.js')
const Hydra = require('./Hydra.js')
const Editor = require('./EditorComponent.js')
module.exports = function mainView(state, emit) {
return html`
<body>
<div id="hydra-ui">
${state.cache(Hydra, 'hydra-canvas').render(state, emit)}
<!---<canvas id="audio-canvas">
</canvas>--->
</div>
${info(state, emit)}
${state.cache(Editor, 'editor').render(state, emit)}
</body>
`
function onclick () {
emit('increment', 1)
}
}