let data = { clients: {}, // Key: Controller // Value: Controlee // Music is played on Value's device. control: {} } function getSocketByDevice (devid) { for (let id in data.clients) { let sock = data.clients[i] if (sock.device && sock.device === devid) { return sock } } return null } function getControlling (sockid) { for (let id in data.control) { let cl = data.control[id] if (cl === sockid) return id } return null } function start (io) { io.on('connection', function (socket) { let sockid = socket.id socket.on('auth', function (device) { if (getSocketByDevice(device) != null) { return socket.emit('cerr', {error: 'devexists', code: 0}) } socket.device = device data.clients[sockid] = socket }) socket.on('req:devs', function () { let devices = [] for (let i in data.clients) { let cl = data.clients[i] if (cl.device === socket.device) continue devices.push(devices) } socket.emit('res:devs', devices) }) // Controller wants to take control of Controlee socket.on('ctrl:connect', function (ctrlee) { let dev = getSocketByDevice(ctrlee) if (!dev) return socket.emit('cerr', {error: 'devnull', code: 1}) // Device is already controlling/being controlled if (data.control[sockid] || getControlling(dev.id)) return socket.emit('cerr', {error: 'devctrl', code: 2}) dev.emit('ctrl:connect', { device: socket.device }) socket.emit('targ:success', { device: ctrlee }) }) // Disconnect socket.on('ctrl:disconnect', function (ctrlee) { let id, ctrl if (getControlling(sockid)) { // If this is a controlee, disconnect from controller id = getControlling(sockid) ctrl = data.clients[id] delete data.control[id] } else if (data.control[sockid]) { // If this is a controller, disconnect from controlee id = data.control[sockid] ctrl = data.clients[id] delete data.control[sockid] } if (!ctrl) return ctrl.emit('targ:disconnect', {}) }) let directpass = ['track', 'pause', 'seek', 'volume', 'mute', 'queue', 'req:queue', 'res:queue'] for (let i in directpass) { let syn = 'sync:' + directpass[i] // Set pause/play state // Sent from controlee to controller socket.on(syn, function (data) { let ctrl if (getControlling(sockid)) { // If this is a controlee, send to controller ctrl = data.clients[getControlling(sockid)] } else if (data.control[sockid]) { // If this is a controller, send to controlee ctrl = data.clients[data.control[sockid]] } ctrl && ctrl.emit('set:' + directpass[i], data) }) } // Synchronize timestamp socket.on('sync:time', function (data) { if (!getControlling(sockid)) return let ctrl = data.clients[getControlling(sockid)] ctrl && ctrl.emit('sync:time', data) }) socket.on('disconnect', function () { if (data.clients[sockid]) { let dev = data.clients[sockid] // Controller loses connection // Emit to controlee if (data.control[sockid]) { let clt = data.clients[sockid] clt && clt.emit('ctrl:disconnect', {}) // Controlee loses connection // Emit to controller } else if (getControlling(sockid)) { let clt = data.clients[getControlling(sockid)] clt && clt.emit('targ:disconnect', {}) } delete data.clients[sockid] } }) }) } module.exports = { start }