« get me outta code hell

identifier per socket connection - mtui - Music Text User Interface - user-friendly command line music player
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <towerofnix@gmail.com>2021-04-23 11:44:58 -0300
committer(quasar) nebula <towerofnix@gmail.com>2021-04-23 11:44:58 -0300
commit533f2898871cc5c1a548308537fbcd4f8d4bbdf5 (patch)
tree68194e3ce3c8f14c928583709bda0bf3eef9efaf
parent45f804fef3766e3183610b93ac3d1ffb89f08408 (diff)
identifier per socket connection
-rw-r--r--backend.js8
-rw-r--r--socket.js60
-rw-r--r--todo.txt2
-rw-r--r--ui.js8
4 files changed, 53 insertions, 25 deletions
diff --git a/backend.js b/backend.js
index ddfb000..13287ec 100644
--- a/backend.js
+++ b/backend.js
@@ -859,16 +859,16 @@ class Backend extends EventEmitter {
     this.emit('log message', messageInfo)
   }
 
-  loadPartyGrouplike(partyGrouplike) {
-    this.emit('got party grouplike', partyGrouplike)
+  loadPartyGrouplike(socketId, partyGrouplike) {
+    this.emit('got party grouplike', socketId, partyGrouplike)
   }
 
   shareWithParty(item) {
     this.emit('share with party', item)
   }
 
-  partyGrouplikeUpdated(partyGrouplike) {
-    this.emit('party grouplike updated', partyGrouplike)
+  partyGrouplikeUpdated(socketId, partyGrouplike) {
+    this.emit('party grouplike updated', socketId, partyGrouplike)
   }
 }
 
diff --git a/socket.js b/socket.js
index 92a48bf..3db0f98 100644
--- a/socket.js
+++ b/socket.js
@@ -28,6 +28,7 @@ const originalSymbol = Symbol('Original item')
 
 const EventEmitter = require('events')
 const net = require('net')
+const shortid = require('shortid')
 
 const {
   saveBackend,
@@ -110,6 +111,8 @@ function validateCommand(command) {
       switch (command.code) {
         case 'initialize-backend':
           return typeof command.backend === 'object'
+        case 'set-socket-id':
+          return typeof command.socketId === 'string'
       }
       // No break here; servers can send commands which typically come from
       // clients too.
@@ -243,7 +246,7 @@ function makeSocketServer() {
   // that's the responsibility of the caller (use server.listen()).
 
   const server = new net.Server()
-  const sockets = []
+  const socketMap = Object.create(null)
 
   server.canonicalBackend = null
 
@@ -252,13 +255,15 @@ function makeSocketServer() {
   const donePlaying = {}
 
   server.on('connection', socket => {
-    sockets.push(socket)
+    const socketId = shortid.generate()
+
+    socketMap[socketId] = socket
 
     let nickname = DEFAULT_NICKNAME
 
     socket.on('close', () => {
-      if (sockets.includes(socket)) {
-        sockets.splice(sockets.indexOf(socket), 1)
+      if (socketId in socketMap) {
+        delete socketMap[socketId]
       }
     })
 
@@ -273,6 +278,7 @@ function makeSocketServer() {
       }
 
       command.sender = 'client'
+      command.senderSocketId = socketId
       command.senderNickname = nickname
 
       if (!validateCommand(command)) {
@@ -286,25 +292,26 @@ function makeSocketServer() {
         switch (command.status) {
           case 'done-playing': {
             const doneSockets = donePlaying[command.queuePlayer]
-            if (doneSockets && !doneSockets.includes(socket)) {
-              doneSockets.push(socket)
-              if (doneSockets.length === sockets.length) {
+            if (doneSockets && !doneSockets.includes(socketId)) {
+              doneSockets.push(socketId)
+              if (doneSockets.length === Object.keys(socketMap).length) {
                 // determine next track
-                for (const socket of sockets) {
+                for (const socket of Object.values(socketMap)) {
                   // play next track
                 }
                 delete donePlaying[command.queuePlayer]
               }
             }
+            break
           }
           case 'ready-to-resume': {
             const readySockets = readyToResume[command.queuePlayer]
-            if (readySockets && !readySockets.includes(socket)) {
-              readySockets.push(socket)
-              if (readySockets.length === sockets.length) {
+            if (readySockets && !readySockets.includes(socketId)) {
+              readySockets.push(socketId)
+              if (readySockets.length === Object.keys(socketMap).length) {
                 const QP = server.canonicalBackend.queuePlayers.find(QP => QP.id === command.queuePlayer)
                 silenceEvents(QP, ['set-pause'], () => QP.setPause(false))
-                for (const socket of sockets) {
+                for (const socket of Object.values(socketMap)) {
                   socket.write(serializeCommandToData({
                     sender: 'server',
                     code: 'set-pause',
@@ -359,7 +366,7 @@ function makeSocketServer() {
 
       // Relay the command to client sockets besides the sender.
 
-      const otherSockets = sockets.filter(s => s !== socket)
+      const otherSockets = Object.values(socketMap).filter(s => s !== socket)
 
       for (const socket of otherSockets) {
         socket.write(serializeCommandToData(command) + '\n')
@@ -376,6 +383,12 @@ function makeSocketServer() {
 
     socket.write(serializeCommandToData({
       sender: 'server',
+      code: 'set-socket-id',
+      socketId
+    }) + '\n')
+
+    socket.write(serializeCommandToData({
+      sender: 'server',
       code: 'initialize-backend',
       backend: savedBackend
     }) + '\n')
@@ -392,6 +405,7 @@ function makeSocketClient() {
   const client = new EventEmitter()
   client.socket = new net.Socket()
   client.nickname = DEFAULT_NICKNAME
+  client.socketId = null // Will be received from server.
 
   client.sendCommand = function(command) {
     const data = serializeCommandToData(command)
@@ -432,11 +446,16 @@ function attachBackendToSocketClient(backend, client, {
   // All actual logic for instances of the mtui backend interacting with each
   // other through commands lives here.
 
-  const partyGrouplike = {name: 'My Party Sources', isPartySources: true, items: []}
+  const partyGrouplike = {
+    name: `Party Sources - ${client.nickname}`,
+    isPartySources: true,
+    items: []
+  }
+
+  const partyGrouplikeMap = Object.create(null)
 
   backend.setAlwaysStartPaused(true)
   backend.setWaitWhenDonePlaying(true)
-  backend.loadPartyGrouplike(partyGrouplike)
 
   function logCommand(command) {
     const nickToMessage = nickname => `\x1b[32;1m${nickname}\x1b[0m`
@@ -497,6 +516,8 @@ function attachBackendToSocketClient(backend, client, {
         actionmsg = `updated their nickname (from ${nickToMessage(command.oldNickname)})`
         senderNickname = command.nickname
         break
+      case 'set-socket-id':
+        return
       case 'set-pause':
         if (command.paused) {
           actionmsg = 'paused the player'
@@ -548,6 +569,11 @@ function attachBackendToSocketClient(backend, client, {
     switch (command.sender) {
       case 'server':
         switch (command.code) {
+          case 'set-socket-id':
+            client.socketId = command.socketId
+            partyGrouplikeMap[command.socketId] = partyGrouplike
+            backend.loadPartyGrouplike(client.socketId, partyGrouplike)
+            return
           case 'initialize-backend':
             await restoreBackend(backend, command.backend)
             // TODO: does this need to be called here?
@@ -559,7 +585,7 @@ function attachBackendToSocketClient(backend, client, {
             })
             return
         }
-        // Again, no pause. Client commands can come from the server.
+        // Again, no break. Client commands can come from the server.
       case 'client': {
         let QP = (
           command.queuePlayer &&
@@ -775,7 +801,7 @@ function attachBackendToSocketClient(backend, client, {
 
     if (partyGrouplike.items.every(x => x[originalSymbol] !== origItem)) {
       partyGrouplike.items.push(newItem)
-      backend.partyGrouplikeUpdated(partyGrouplike)
+      backend.partyGrouplikeUpdated(client.socketId, partyGrouplike)
     }
   })
 }
diff --git a/todo.txt b/todo.txt
index fd024d7..b2068c9 100644
--- a/todo.txt
+++ b/todo.txt
@@ -581,3 +581,5 @@ TODO: Pressing next track (shift+N) on the last track should start the first
       track, if the queue is being looped.
 
 TODO: Tabber tab list should be accessible via tab (key).
+
+TODO: Show current index and number of tabs beside tabber tab list.
diff --git a/ui.js b/ui.js
index fb0916e..aaf776c 100644
--- a/ui.js
+++ b/ui.js
@@ -561,11 +561,11 @@ class AppElement extends FocusElement {
     this.log.newLogMessage(messageInfo)
   }
 
-  handleGotPartyGrouplike(partyGrouplike) {
-    this.newPartyTab(partyGrouplike)
+  handleGotPartyGrouplike(socketId, partyGrouplike) {
+    this.newPartyTab(socketId, partyGrouplike)
   }
 
-  handlePartyGrouplikeUpdated(partyGrouplike) {
+  handlePartyGrouplikeUpdated(socketId, partyGrouplike) {
     for (const grouplikeListing of this.tabber.tabberElements) {
       if (grouplikeListing.grouplike === partyGrouplike) {
         grouplikeListing.loadGrouplike(partyGrouplike, false)
@@ -1579,7 +1579,7 @@ class AppElement extends FocusElement {
     })
   }
 
-  newPartyTab(partyGrouplike) {
+  newPartyTab(socketId, partyGrouplike) {
     const listing = this.newGrouplikeListing()
     listing.loadGrouplike(partyGrouplike)
   }