From 13e1facf63a71be7944587f0b0149691939adec2 Mon Sep 17 00:00:00 2001 From: badaix Date: Sat, 9 Mar 2024 20:13:14 +0000 Subject: [PATCH] Fix ESLint errors --- .eslintrc.cjs | 6 +- .github/dependabot.yml | 3 - src/components/Client.tsx | 18 ++--- src/components/Group.tsx | 72 +++++++++--------- src/components/SnapWeb.tsx | 30 ++++---- src/snapcontrol.ts | 65 ++++++++-------- src/snapstream.ts | 148 ++++++++++++++++++------------------- 7 files changed, 171 insertions(+), 171 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d6c9537..2136d95 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -6,10 +6,14 @@ module.exports = { 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', ], - ignorePatterns: ['dist', '.eslintrc.cjs'], + ignorePatterns: ['dist', 'debian', '.eslintrc.cjs'], parser: '@typescript-eslint/parser', plugins: ['react-refresh'], rules: { + "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-explicit-any": "off", 'react-refresh/only-export-components': [ 'warn', { allowConstantExport: true }, diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3be968a..cacadbe 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -13,9 +13,6 @@ updates: dependencies: patterns: - "*" - ignore: - - dependency-name: "typescript" - update-types: ["version-update:semver-major"] - package-ecosystem: github-actions directory: "/" schedule: diff --git a/src/components/Client.tsx b/src/components/Client.tsx index 57d6273..7320876 100644 --- a/src/components/Client.tsx +++ b/src/components/Client.tsx @@ -29,7 +29,7 @@ export default function Client(props: ClientProps) { props.snapcontrol.setVolume(props.client.id, value, false); // setState({}); props.onVolumeChange(); - }; + } function handleOptionsClicked(event: React.MouseEvent) { console.debug("handleOptionsClicked"); @@ -38,12 +38,12 @@ export default function Client(props: ClientProps) { setName(props.client.config.name); setTmpLatency(props.client.config.latency); setLatency(props.client.config.latency); - }; + } function handleMenuClose() { setAnchorEl(null) setOpen(false); - }; + } function handleDetailsClose(apply: boolean) { setDetailsOpen(false); @@ -59,33 +59,33 @@ export default function Client(props: ClientProps) { setName(props.client.config.name) setTmpLatency(latency); } - }; + } function handleDetailsClicked() { console.debug("handleDetailsClicked"); setDetailsOpen(true); setAnchorEl(null); setOpen(false); - }; + } function handleNameChange(name: string) { console.debug('handleNameChange: ' + name); setName(name); - }; + } function handleLatencyChange(latency: number) { console.debug('handleLatencyChange: ' + latency); setTmpLatency(latency); props.snapcontrol.setClientLatency(props.client.id, latency); - }; + } function handleMuteClicked() { console.debug("handleMuteClicked"); props.snapcontrol.setVolume(props.client.id, props.client.config.volume.percent, !props.client.config.volume.muted); setUpdate(update + 1); - }; + } - let menuitems = []; + const menuitems = []; menuitems.push( { handleDetailsClicked() }}>Details); if (!props.client.connected) menuitems.push( { props.onDelete(); setAnchorEl(null); setOpen(false); }}>Delete); diff --git a/src/components/Group.tsx b/src/components/Group.tsx index 313b698..6a0ad5a 100644 --- a/src/components/Group.tsx +++ b/src/components/Group.tsx @@ -37,9 +37,9 @@ export default function Group(props: GroupProps) { const groupVolumeChange = useRef({ volumeEntered: true, client_volumes: new Map(), group_volume: 0 }); function updateVolume() { - let clients = getClients(); + const clients = getClients(); let volume = 0; - for (let client of clients) + for (const client of clients) volume += client.config.volume.percent; volume /= clients.length; setVolume(volume); @@ -53,10 +53,10 @@ export default function Group(props: GroupProps) { function handleSettingsClicked(_event: React.MouseEvent) { console.debug("handleSettingsClicked"); - let clients: GroupClient[] = []; - for (let group of props.server.groups) { - for (let client of group.clients) { - let inGroup: boolean = props.group.clients.includes(client); + const clients: GroupClient[] = []; + for (const group of props.server.groups) { + for (const client of group.clients) { + const inGroup: boolean = props.group.clients.includes(client); clients.push({ client: client, inGroup: inGroup, wasInGroup: inGroup }); } } @@ -66,13 +66,13 @@ export default function Group(props: GroupProps) { setSettingsOpen(true); setClients(clients); setStreamId(props.group.stream_id) - }; + } function handleSettingsClose(apply: boolean) { console.debug("handleSettingsClose: " + apply); if (apply) { let changed: boolean = false; - for (let element of clients) { + for (const element of clients) { if (element.inGroup !== element.wasInGroup) { changed = true; break; @@ -80,8 +80,8 @@ export default function Group(props: GroupProps) { } if (changed) { - let groupClients: string[] = []; - for (let element of clients) + const groupClients: string[] = []; + for (const element of clients) if (element.inGroup) groupClients.push(element.client.id); props.snapcontrol.setClients(props.group.id, groupClients); @@ -91,21 +91,21 @@ export default function Group(props: GroupProps) { props.snapcontrol.setStream(props.group.id, streamId); } setSettingsOpen(false); - }; + } function handleGroupClientChange(client: Snapcast.Client, inGroup: boolean) { console.debug("handleGroupClientChange: " + client.id + ", in group: " + inGroup); - let newclients = clients; - let idx = newclients.findIndex(element => element.client === client); + const newclients = clients; + const idx = newclients.findIndex(element => element.client === client); newclients[idx].inGroup = inGroup; setClients(newclients); // dummy update, since the array was just mutated setUpdate(update + 1); - }; + } function handleClientDelete(client: Snapcast.Client) { console.debug("handleClientDelete: " + client.getName()); - let newDeletedClients = deletedClients; + const newDeletedClients = deletedClients; if (!newDeletedClients.includes(client)) newDeletedClients.push(client); setDeletedClients(newDeletedClients); @@ -123,27 +123,27 @@ export default function Group(props: GroupProps) { if (!undo) props.snapcontrol.deleteClient(client.id); - let newDeletedClients = deletedClients; + const newDeletedClients = deletedClients; if (newDeletedClients.includes(client)) newDeletedClients.splice(newDeletedClients.indexOf(client), 1); setDeletedClients(newDeletedClients); setUpdate(update + 1); - }; + } function handleMuteClicked() { console.debug("handleMuteClicked"); props.group.muted = !props.group.muted; props.snapcontrol.muteGroup(props.group.id, props.group.muted); setUpdate(update + 1); - }; + } function handleVolumeChange(value: number) { console.debug("handleVolumeChange: " + value); if (groupVolumeChange.current.volumeEntered) { groupVolumeChange.current.client_volumes.clear(); groupVolumeChange.current.group_volume = 0; - for (let client of getClients()) { + for (const client of getClients()) { groupVolumeChange.current.client_volumes.set(client.id, client.config.volume.percent); groupVolumeChange.current.group_volume += client.config.volume.percent; } @@ -151,14 +151,14 @@ export default function Group(props: GroupProps) { groupVolumeChange.current.volumeEntered = false; } - let delta = value - groupVolumeChange.current.group_volume; + const delta = value - groupVolumeChange.current.group_volume; let ratio: number; if (delta < 0) ratio = (groupVolumeChange.current.group_volume - value) / groupVolumeChange.current.group_volume; else ratio = (value - groupVolumeChange.current.group_volume) / (100 - groupVolumeChange.current.group_volume); - for (let client of getClients()) { + for (const client of getClients()) { let new_volume = groupVolumeChange.current.client_volumes.get(client.id)!; if (delta < 0) new_volume -= ratio * new_volume; @@ -170,12 +170,12 @@ export default function Group(props: GroupProps) { } setVolume(value); - }; + } function handleVolumeChangeCommitted(value: number) { console.debug("handleVolumeChangeCommitted: " + value); groupVolumeChange.current.volumeEntered = true; - }; + } function handlePlayPauseClicked() { if (props.server.getStream(props.group.stream_id)?.properties.playbackStatus === "playing") @@ -203,12 +203,12 @@ export default function Group(props: GroupProps) { ) ) - }; + } function getClients(): Snapcast.Client[] { - let clients = []; - for (let client of props.group.clients) { + const clients = []; + for (const client of props.group.clients) { if ((client.connected || props.showOffline) && !deletedClients.includes(client)) { clients.push(client); } @@ -217,24 +217,24 @@ export default function Group(props: GroupProps) { } console.debug("Render Group " + props.group.id); - let groupClients = []; + const groupClients = []; - for (let client of getClients()) { + for (const client of getClients()) { groupClients.push( { handleClientDelete(client) }} onVolumeChange={() => { handleClientVolumeChange(client) }} />); } if (groupClients.length === 0) return (
{snackbar()}
); - let stream = props.server.getStream(props.group.stream_id); - let artUrl = stream?.properties.metadata?.artUrl || logo; - let title = stream?.properties.metadata?.title || "Unknown Title"; - let artist: string = (stream?.properties.metadata?.artist) ? stream!.properties.metadata.artist.join(', ') : "Unknown Artist"; + const stream = props.server.getStream(props.group.stream_id); + const artUrl = stream?.properties.metadata?.artUrl || logo; + const title = stream?.properties.metadata?.title || "Unknown Title"; + const artist: string = (stream?.properties.metadata?.artist) ? stream!.properties.metadata.artist.join(', ') : "Unknown Artist"; console.debug("Art URL: " + artUrl); - let allClients = []; - for (let group of props.server.groups) - for (let client of group.clients) + const allClients = []; + for (const group of props.server.groups) + for (const client of group.clients) allClients.push(client); return ( @@ -263,7 +263,7 @@ export default function Group(props: GroupProps) { value={props.group.stream_id} label="Stream" onChange={(event) => { - let stream: string = event.target.value; + const stream: string = event.target.value; setStreamId(stream); props.snapcontrol.setStream(props.group.id, stream); }} diff --git a/src/components/SnapWeb.tsx b/src/components/SnapWeb.tsx index 37afe02..e98af51 100644 --- a/src/components/SnapWeb.tsx +++ b/src/components/SnapWeb.tsx @@ -105,24 +105,24 @@ export default function SnapWeb(props: SnapWebProps) { function getMyStreamId(): string { try { - let group = props.snapcontrol.getGroupFromClient(SnapStream.getClientId()); + const group = props.snapcontrol.getGroupFromClient(SnapStream.getClientId()); return props.snapcontrol.getStream(group.stream_id).id; } catch (e) { return ""; } - }; + } function updateMediaSession() { console.debug('updateMediaSession'); if (!snapstreamRef.current) return; try { - let streamId = getMyStreamId(); - let properties = props.snapcontrol.getStream(streamId).properties; - let metadata = properties.metadata; - let title: string = metadata?.title || "Unknown Title"; - let artist: string = (metadata?.artist !== undefined) ? metadata?.artist.join(', ') : "Unknown Artist"; - let album: string = metadata?.album || ""; + const streamId = getMyStreamId(); + const properties = props.snapcontrol.getStream(streamId).properties; + const metadata = properties.metadata; + const title: string = metadata?.title || "Unknown Title"; + const artist: string = (metadata?.artist !== undefined) ? metadata?.artist.join(', ') : "Unknown Artist"; + const album: string = metadata?.album || ""; let artwork: Array = [{ src: snapcast512, sizes: '512x512', type: 'image/png' }]; if (metadata?.artUrl !== undefined) { artwork = [ @@ -142,7 +142,7 @@ export default function SnapWeb(props: SnapWebProps) { artwork: artwork }); - let mediaSession = navigator.mediaSession!; + const mediaSession = navigator.mediaSession!; let play_state: MediaSessionPlaybackState = "none"; if (properties.playbackStatus !== undefined) { if (properties.playbackStatus === "playing") { @@ -172,17 +172,17 @@ export default function SnapWeb(props: SnapWebProps) { } catch (error) { console.debug('Warning! The "stop" media session action is not supported.'); } - let defaultSkipTime: number = 10; // Time to skip in seconds by default + const defaultSkipTime: number = 10; // Time to skip in seconds by default mediaSession.setActionHandler('seekbackward', properties.canSeek ? (event: MediaSessionActionDetails) => { - let offset: number = (event.seekOffset || defaultSkipTime) * -1; + const offset: number = (event.seekOffset || defaultSkipTime) * -1; if (properties.position !== undefined) Math.max(properties.position! + offset, 0); props.snapcontrol.control(streamId, 'seek', { 'offset': offset }) } : null); mediaSession.setActionHandler('seekforward', properties.canSeek ? (event: MediaSessionActionDetails) => { - let offset: number = event.seekOffset || defaultSkipTime; + const offset: number = event.seekOffset || defaultSkipTime; if ((metadata?.duration !== undefined) && (properties.position !== undefined)) Math.min(properties.position! + offset, metadata.duration!); props.snapcontrol.control(streamId, 'seek', { 'offset': offset }) @@ -190,7 +190,7 @@ export default function SnapWeb(props: SnapWebProps) { try { mediaSession.setActionHandler('seekto', properties.canSeek ? (event: MediaSessionActionDetails) => { - let position: number = event.seekTime || 0; + const position: number = event.seekTime || 0; if (metadata?.duration !== undefined) Math.min(position, metadata.duration!); props.snapcontrol.control(streamId, 'setPosition', { 'position': position }) @@ -281,7 +281,7 @@ export default function SnapWeb(props: SnapWebProps) { { - let showoffline = !showOffline; + const showoffline = !showOffline; if (window.localStorage) window.localStorage.setItem("showoffline", showoffline ? "true" : "false"); setShowOffline(showoffline); @@ -301,7 +301,7 @@ export default function SnapWeb(props: SnapWebProps) { { - let darkmode = !darkMode; + const darkmode = !darkMode; if (window.localStorage) window.localStorage.setItem("darkmode", darkmode ? "true" : "false"); setDarkMode(darkmode); diff --git a/src/snapcontrol.ts b/src/snapcontrol.ts index 8f3641c..5d6abb9 100644 --- a/src/snapcontrol.ts +++ b/src/snapcontrol.ts @@ -31,9 +31,9 @@ namespace Snapcast { fromJson(json: any) { this.id = json.id; this.host = new Host(json.host); - let jsnapclient = json.snapclient; + const jsnapclient = json.snapclient; this.snapclient = { name: jsnapclient.name, protocolVersion: jsnapclient.protocolVersion, version: jsnapclient.version } - let jconfig = json.config; + const jconfig = json.config; this.config = { instance: jconfig.instance, latency: jconfig.latency, name: jconfig.name, volume: { muted: jconfig.volume.muted, percent: jconfig.volume.percent } } this.lastSeen = { sec: json.lastSeen.sec, usec: json.lastSeen.usec } this.connected = Boolean(json.connected); @@ -77,7 +77,7 @@ namespace Snapcast { this.id = json.id; this.stream_id = json.stream_id; this.muted = Boolean(json.muted); - for (let client of json.clients) + for (const client of json.clients) this.clients.push(new Client(client)); } @@ -88,7 +88,7 @@ namespace Snapcast { clients: Client[] = []; getClient(id: string): Client | null { - for (let client of this.clients) { + for (const client of this.clients) { if (client.id === id) return client; } @@ -175,7 +175,7 @@ namespace Snapcast { } else { this.properties = new Properties({}); } - let juri = json.uri; + const juri = json.uri; this.uri = { raw: juri.raw, scheme: juri.scheme, host: juri.host, path: juri.path, fragment: juri.fragment, query: juri.query } } @@ -202,12 +202,12 @@ namespace Snapcast { fromJson(json: any) { this.groups = [] - for (let jgroup of json.groups) + for (const jgroup of json.groups) this.groups.push(new Group(jgroup)); - let jsnapserver: any = json.server.snapserver; + const jsnapserver: any = json.server.snapserver; this.server = { host: new Host(json.server.host), snapserver: { controlProtocolVersion: jsnapserver.controlProtocolVersion, name: jsnapserver.name, protocolVersion: jsnapserver.protocolVersion, version: jsnapserver.version } }; this.streams = [] - for (let jstream of json.streams) { + for (const jstream of json.streams) { this.streams.push(new Stream(jstream)); } } @@ -225,8 +225,8 @@ namespace Snapcast { streams: Stream[] = []; getClient(id: string): Client | null { - for (let group of this.groups) { - let client = group.getClient(id); + for (const group of this.groups) { + const client = group.getClient(id); if (client) return client; } @@ -234,7 +234,7 @@ namespace Snapcast { } getGroup(id: string): Group | null { - for (let group of this.groups) { + for (const group of this.groups) { if (group.id === id) return group; } @@ -242,7 +242,7 @@ namespace Snapcast { } getStream(id: string): Stream | null { - for (let stream of this.streams) { + for (const stream of this.streams) { if (stream.id === id) return stream; } @@ -251,7 +251,7 @@ namespace Snapcast { } } -interface OnChange { (server: Snapcast.Server): void }; +interface OnChange { (_server: Snapcast.Server): void } // interface OnStreamChange { (id: string): void }; class SnapControl { @@ -279,8 +279,7 @@ class SnapControl { let stream!: Snapcast.Stream; switch (notification.method) { case 'Client.OnVolumeChanged': - let client = this.getClient(notification.params.id); - client.config.volume = notification.params.volume; + this.getClient(notification.params.id).config.volume = notification.params.volume; // updateGroupVolume(this.getGroupFromClient(client.id)); return true; case 'Client.OnLatencyChanged': @@ -473,7 +472,7 @@ class SnapControl { // } public getClient(client_id: string): Snapcast.Client { - let client = this.server.getClient(client_id); + const client = this.server.getClient(client_id); if (client == null) { throw new Error(`client ${client_id} was null`); } @@ -481,7 +480,7 @@ class SnapControl { } public getGroup(group_id: string): Snapcast.Group { - let group = this.server.getGroup(group_id); + const group = this.server.getGroup(group_id); if (group == null) { throw new Error(`group ${group_id} was null`); } @@ -493,7 +492,7 @@ class SnapControl { return 0; let group_vol: number = 0; let client_count: number = 0; - for (let client of group.clients) { + for (const client of group.clients) { if (online && !client.connected) continue; group_vol += client.config.volume.percent; @@ -505,15 +504,15 @@ class SnapControl { } public getGroupFromClient(client_id: string): Snapcast.Group { - for (let group of this.server.groups) - for (let client of group.clients) + for (const group of this.server.groups) + for (const client of group.clients) if (client.id === client_id) return group; throw new Error(`group for client ${client_id} was null`); } public getStreamFromClient(client_id: string): Snapcast.Stream { - let group: Snapcast.Group = this.getGroupFromClient(client_id); + const group: Snapcast.Group = this.getGroupFromClient(client_id); return this.getStream(group.stream_id); } @@ -528,7 +527,7 @@ class SnapControl { // } public getStream(stream_id: string): Snapcast.Stream { - let stream = this.server.getStream(stream_id); + const stream = this.server.getStream(stream_id); if (stream == null) { throw new Error(`stream ${stream_id} was null`); } @@ -537,7 +536,7 @@ class SnapControl { public setVolume(client_id: string, percent: number, mute?: boolean) { percent = Math.max(0, Math.min(100, percent)); - let client = this.getClient(client_id); + const client = this.getClient(client_id); client.config.volume.percent = percent; if (mute !== undefined) client.config.volume.muted = mute; @@ -545,8 +544,8 @@ class SnapControl { } public setClientName(client_id: string, name: string) { - let client = this.getClient(client_id); - let current_name: string = (client.config.name !== "") ? client.config.name : client.host.name; + const client = this.getClient(client_id); + const current_name: string = (client.config.name !== "") ? client.config.name : client.host.name; if (name !== current_name) { this.sendRequest('Client.SetName', { id: client_id, name: name }); client.config.name = name; @@ -554,8 +553,8 @@ class SnapControl { } public setClientLatency(client_id: string, latency: number) { - let client = this.getClient(client_id); - let current_latency: number = client.config.latency; + const client = this.getClient(client_id); + const current_latency: number = client.config.latency; if (latency !== current_latency) { this.sendRequest('Client.SetLatency', { id: client_id, latency: latency }); client.config.latency = latency; @@ -596,7 +595,7 @@ class SnapControl { } public control(stream_id: string, command: string, params?: any) { - let json: any = { id: stream_id, command: command }; + const json: any = { id: stream_id, command: command }; if (params) { json.params = params; } @@ -604,7 +603,7 @@ class SnapControl { } private sendRequest(method: string, params?: any): number { - let msg: any = { + const msg: any = { id: ++this.msg_id, jsonrpc: '2.0', method: method @@ -612,7 +611,7 @@ class SnapControl { if (params) msg.params = params; - let msgJson = JSON.stringify(msg); + const msgJson = JSON.stringify(msg); console.debug("Sending: " + msgJson); this.connection.send(msgJson); return this.msg_id; @@ -620,8 +619,8 @@ class SnapControl { private onMessage(msg: string) { let refresh: boolean = false; - let json_msg = JSON.parse(msg); - let is_response: boolean = (json_msg.id !== undefined); + const json_msg = JSON.parse(msg); + const is_response: boolean = (json_msg.id !== undefined); // console.debug("Received " + (is_response ? "response" : "notification") + ", json: " + JSON.stringify(json_msg)) if (is_response) { if (json_msg.id === this.status_req_id) { @@ -633,7 +632,7 @@ class SnapControl { } else { if (Array.isArray(json_msg)) { - for (let notification of json_msg) { + for (const notification of json_msg) { refresh = this.onNotification(notification) || refresh; } } else { diff --git a/src/snapstream.ts b/src/snapstream.ts index aceb77e..013ec22 100644 --- a/src/snapstream.ts +++ b/src/snapstream.ts @@ -16,7 +16,7 @@ interface IAudioContextPatched extends IAudioContext { } function setCookie(key: string, value: string, exdays: number = -1) { - let d = new Date(); + const d = new Date(); if (exdays < 0) exdays = 10 * 365; d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); @@ -35,9 +35,9 @@ function getPersistentValue(key: string, defaultValue: string = ""): string { return defaultValue; } // Fallback to cookies if localStorage is not available. - let name = key + "="; - let decodedCookie = decodeURIComponent(document.cookie); - let ca = decodedCookie.split(';'); + const name = key + "="; + const decodedCookie = decodeURIComponent(document.cookie); + const ca = decodedCookie.split(';'); for (let c of ca) { c = c.trimLeft(); if (c.indexOf(name) === 0) { @@ -55,7 +55,7 @@ function getChromeVersion(): number | null { function uuidv4(): string { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = Math.random() * 16 | 0, v = c === 'x' ? r : ((r & 0x3) | 0x8); + const r = Math.random() * 16 | 0, v = c === 'x' ? r : ((r & 0x3) | 0x8); return v.toString(16); }); } @@ -83,7 +83,7 @@ class Tv { class BaseMessage { deserialize(buffer: ArrayBuffer) { - let view = new DataView(buffer); + const view = new DataView(buffer); this.type = view.getUint16(0, true); this.id = view.getUint16(2, true); this.refersTo = view.getUint16(4, true); @@ -94,8 +94,8 @@ class BaseMessage { serialize(): ArrayBuffer { this.size = 26 + this.getSize(); - let buffer = new ArrayBuffer(this.size); - let view = new DataView(buffer); + const buffer = new ArrayBuffer(this.size); + const view = new DataView(buffer); view.setUint16(0, this.type, true); view.setUint16(2, this.id, true); view.setUint16(4, this.refersTo, true); @@ -132,11 +132,11 @@ class CodecMessage extends BaseMessage { deserialize(buffer: ArrayBuffer) { super.deserialize(buffer); - let view = new DataView(buffer); - let codecSize = view.getInt32(26, true); - let decoder = new TextDecoder("utf-8"); + const view = new DataView(buffer); + const codecSize = view.getInt32(26, true); + const decoder = new TextDecoder("utf-8"); this.codec = decoder.decode(buffer.slice(30, 30 + codecSize)); - let payloadSize = view.getInt32(30 + codecSize, true); + const payloadSize = view.getInt32(30 + codecSize, true); console.debug("payload size: " + payloadSize); this.payload = buffer.slice(34 + codecSize, 34 + codecSize + payloadSize); console.debug("payload: " + this.payload); @@ -158,13 +158,13 @@ class TimeMessage extends BaseMessage { deserialize(buffer: ArrayBuffer) { super.deserialize(buffer); - let view = new DataView(buffer); + const view = new DataView(buffer); this.latency = new Tv(view.getInt32(26, true), view.getInt32(30, true)); } serialize(): ArrayBuffer { - let buffer = super.serialize(); - let view = new DataView(buffer); + const buffer = super.serialize(); + const view = new DataView(buffer); view.setInt32(26, this.latency.sec, true); view.setInt32(30, this.latency.usec, true); return buffer; @@ -188,27 +188,27 @@ class JsonMessage extends BaseMessage { deserialize(buffer: ArrayBuffer) { super.deserialize(buffer); - let view = new DataView(buffer); - let size = view.getUint32(26, true); - let decoder = new TextDecoder(); + const view = new DataView(buffer); + const size = view.getUint32(26, true); + const decoder = new TextDecoder(); this.json = JSON.parse(decoder.decode(buffer.slice(30, 30 + size))); } serialize(): ArrayBuffer { - let buffer = super.serialize(); - let view = new DataView(buffer); - let jsonStr = JSON.stringify(this.json); + const buffer = super.serialize(); + const view = new DataView(buffer); + const jsonStr = JSON.stringify(this.json); view.setUint32(26, jsonStr.length, true); - let encoder = new TextEncoder(); - let encoded = encoder.encode(jsonStr); + const encoder = new TextEncoder(); + const encoded = encoder.encode(jsonStr); for (let i = 0; i < encoded.length; ++i) view.setUint8(30 + i, encoded[i]); return buffer; } getSize() { - let encoder = new TextEncoder(); - let encoded = encoder.encode(JSON.stringify(this.json)); + const encoder = new TextEncoder(); + const encoded = encoder.encode(JSON.stringify(this.json)); return encoded.length + 4; // return JSON.stringify(this.json).length; } @@ -295,7 +295,7 @@ class PcmChunkMessage extends BaseMessage { deserialize(buffer: ArrayBuffer) { super.deserialize(buffer); - let view = new DataView(buffer); + const view = new DataView(buffer); this.timestamp = new Tv(view.getInt32(26, true), view.getInt32(30, true)); // this.payloadSize = view.getUint32(34, true); this.payload = buffer.slice(38);//, this.payloadSize + 38));// , this.payloadSize); @@ -304,12 +304,12 @@ class PcmChunkMessage extends BaseMessage { readFrames(frames: number): ArrayBuffer { let frameCnt = frames; - let frameSize = this.sampleFormat.frameSize(); + const frameSize = this.sampleFormat.frameSize(); if (this.idx + frames > this.payloadSize() / frameSize) frameCnt = (this.payloadSize() / frameSize) - this.idx; - let begin = this.idx * frameSize; + const begin = this.idx * frameSize; this.idx += frameCnt; - let end = begin + frameCnt * frameSize; + const end = begin + frameCnt * frameSize; // console.log("readFrames: " + frames + ", result: " + frameCnt + ", begin: " + begin + ", end: " + end + ", payload: " + this.payload.byteLength); return this.payload.slice(begin, end); } @@ -339,10 +339,10 @@ class PcmChunkMessage extends BaseMessage { } addPayload(buffer: ArrayBuffer) { - let payload = new ArrayBuffer(this.payload.byteLength + buffer.byteLength); - let view = new DataView(payload); - let viewOld = new DataView(this.payload); - let viewNew = new DataView(buffer); + const payload = new ArrayBuffer(this.payload.byteLength + buffer.byteLength); + const view = new DataView(payload); + const viewOld = new DataView(this.payload); + const viewNew = new DataView(buffer); for (let i = 0; i < viewOld.byteLength; ++i) { view.setInt8(i, viewOld.getInt8(i)); } @@ -361,7 +361,7 @@ class PcmChunkMessage extends BaseMessage { class AudioStream { - constructor(public timeProvider: TimeProvider, public sampleFormat: SampleFormat, public bufferMs: number) { + constructor(public _timeProvider: TimeProvider, public _sampleFormat: SampleFormat, public _bufferMs: number) { } chunks: Array = new Array(); @@ -380,9 +380,9 @@ class AudioStream { // console.debug("chunks: " + this.chunks.length + ", oldest: " + oldest.toFixed(2) + ", newest: " + newest.toFixed(2)); while (this.chunks.length > 0) { - let age = this.timeProvider.serverNow() - this.chunks[0].timestamp.getMilliseconds(); + const age = this._timeProvider.serverNow() - this.chunks[0].timestamp.getMilliseconds(); // todo: consider buffer ms - if (age > 5000 + this.bufferMs) { + if (age > 5000 + this._bufferMs) { this.chunks.shift(); console.log("Dropping old chunk: " + age.toFixed(2) + ", left: " + this.chunks.length); } @@ -396,18 +396,18 @@ class AudioStream { this.chunk = this.chunks.shift() } // let age = this.timeProvider.serverTime(this.playTime * 1000) - startMs; - let frames = buffer.length; + const frames = buffer.length; // console.debug("getNextBuffer: " + frames + ", play time: " + playTimeMs.toFixed(2)); - let left = new Float32Array(frames); - let right = new Float32Array(frames); + const left = new Float32Array(frames); + const right = new Float32Array(frames); let read = 0; let pos = 0; // let volume = this.muted ? 0 : this.volume; - let serverPlayTimeMs = this.timeProvider.serverTime(playTimeMs); + const serverPlayTimeMs = this._timeProvider.serverTime(playTimeMs); if (this.chunk) { let age = serverPlayTimeMs - this.chunk.startMs();// - 500; - let reqChunkDuration = frames / this.sampleFormat.msRate(); - let secs = Math.floor(Date.now() / 1000); + const reqChunkDuration = frames / this._sampleFormat.msRate(); + const secs = Math.floor(Date.now() / 1000); if (this.lastLog !== secs) { this.lastLog = secs; console.log("age: " + age.toFixed(2) + ", req: " + reqChunkDuration); @@ -433,7 +433,7 @@ class AudioStream { } else if (age < 0) { console.log("Playing silence " + -age.toFixed(2) + "ms"); - let silentFrames = Math.floor(-age * this.chunk.sampleFormat.msRate()); + const silentFrames = Math.floor(-age * this.chunk.sampleFormat.msRate()); left.fill(0, 0, silentFrames); right.fill(0, 0, silentFrames); read = silentFrames; @@ -471,16 +471,16 @@ class AudioStream { addFrames = Math.floor(age); // / 5); } // addFrames = -2; - let readFrames = frames + addFrames - read; + const readFrames = frames + addFrames - read; if (addFrames !== 0) everyN = Math.ceil((frames + addFrames - read) / (Math.abs(addFrames) + 1)); // addFrames = 0; // console.debug("frames: " + frames + ", readFrames: " + readFrames + ", addFrames: " + addFrames + ", everyN: " + everyN); while ((read < readFrames) && this.chunk) { - let pcmChunk = this.chunk as PcmChunkMessage; - let pcmBuffer = pcmChunk.readFrames(readFrames - read); - let payload = new Int16Array(pcmBuffer); + const pcmChunk = this.chunk as PcmChunkMessage; + const pcmBuffer = pcmChunk.readFrames(readFrames - read); + const payload = new Int16Array(pcmBuffer); // console.debug("readFrames: " + (frames - read) + ", read: " + pcmBuffer.byteLength + ", payload: " + payload.length); // read += (pcmBuffer.byteLength / this.sampleFormat.frameSize()); for (let i = 0; i < payload.length; i += 2) { @@ -564,7 +564,7 @@ class TimeProvider { } else { if (this.diffBuffer.push((c2s - s2c) / 2) > 100) this.diffBuffer.shift(); - let sorted = [...this.diffBuffer]; + const sorted = [...this.diffBuffer]; sorted.sort() this.diff = sorted[Math.floor(sorted.length / 2)]; } @@ -578,7 +578,7 @@ class TimeProvider { } else { const ctx = this.ctx as IAudioContextPatched; // Use the more accurate getOutputTimestamp if available, fallback to ctx.currentTime otherwise. - const contextTime = !!ctx.getOutputTimestamp ? ctx.getOutputTimestamp().contextTime : undefined; + const contextTime = ctx.getOutputTimestamp ? ctx.getOutputTimestamp().contextTime : undefined; return (contextTime !== undefined ? contextTime : ctx.currentTime) * 1000; } } @@ -644,8 +644,8 @@ class Decoder { class OpusDecoder extends Decoder { setHeader(buffer: ArrayBuffer): SampleFormat | null { - let view = new DataView(buffer); - let ID_OPUS = 0x4F505553; + const view = new DataView(buffer); + const ID_OPUS = 0x4F505553; if (buffer.byteLength < 12) { console.error("Opus header too small: " + buffer.byteLength); return null; @@ -654,7 +654,7 @@ class OpusDecoder extends Decoder { return null; } - let format = new SampleFormat(); + const format = new SampleFormat(); format.rate = view.getUint32(4, true); format.bits = view.getUint16(8, true); format.channels = view.getUint16(10, true); @@ -673,7 +673,7 @@ class FlacDecoder extends Decoder { super(); this.decoder = Flac.create_libflac_decoder(true); if (this.decoder) { - let init_status = Flac.init_decoder_stream(this.decoder, this.read_callback_fn.bind(this), this.write_callback_fn.bind(this), this.error_callback_fn.bind(this), this.metadata_callback_fn.bind(this), false); + const init_status = Flac.init_decoder_stream(this.decoder, this.read_callback_fn.bind(this), this.write_callback_fn.bind(this), this.error_callback_fn.bind(this), this.metadata_callback_fn.bind(this), false); console.log("Flac init: " + init_status); Flac.setOptions(this.decoder, { analyseSubframes: true, analyseResiduals: true }); } @@ -700,7 +700,7 @@ class FlacDecoder extends Decoder { } // console.log("Pcm payload: " + this.pcmChunk!.payloadSize()); if (this.cacheInfo.cachedBlocks > 0) { - let diffMs = this.cacheInfo.cachedBlocks / this.sampleFormat.msRate(); + const diffMs = this.cacheInfo.cachedBlocks / this.sampleFormat.msRate(); // console.log("Cached: " + this.cacheInfo.cachedBlocks + ", " + diffMs + "ms"); this.pcmChunk!.timestamp.setMilliseconds(this.pcmChunk!.timestamp.getMilliseconds() - diffMs); } @@ -711,14 +711,14 @@ class FlacDecoder extends Decoder { // console.log(' decode read callback, buffer bytes max=', bufferSize); if (this.header) { console.log(" header: " + this.header.byteLength); - let data = new Uint8Array(this.header); + const data = new Uint8Array(this.header); this.header = null; return { buffer: data, readDataLength: data.byteLength, error: false }; } else if (this.flacChunk) { // console.log(" flacChunk: " + this.flacChunk.byteLength); // a fresh read => next call to write will not be from cached data this.cacheInfo.isCachedChunk = false; - let data = new Uint8Array(this.flacChunk.slice(0, Math.min(bufferSize, this.flacChunk.byteLength))); + const data = new Uint8Array(this.flacChunk.slice(0, Math.min(bufferSize, this.flacChunk.byteLength))); this.flacChunk = this.flacChunk.slice(data.byteLength); return { buffer: data, readDataLength: data.byteLength, error: false }; } @@ -731,10 +731,10 @@ class FlacDecoder extends Decoder { // there was no call to read, so it's some cached data this.cacheInfo.cachedBlocks += frameInfo.blocksize; } - let payload = new ArrayBuffer((frameInfo.bitsPerSample / 8) * frameInfo.channels * frameInfo.blocksize); - let view = new DataView(payload); + const payload = new ArrayBuffer((frameInfo.bitsPerSample / 8) * frameInfo.channels * frameInfo.blocksize); + const view = new DataView(payload); for (let channel: number = 0; channel < frameInfo.channels; ++channel) { - let channelData = new DataView(data[channel].buffer, 0, data[channel].buffer.byteLength); + const channelData = new DataView(data[channel].buffer, 0, data[channel].buffer.byteLength); // console.log("channelData: " + channelData.byteLength + ", blocksize: " + frameInfo.blocksize); for (let i: number = 0; i < frameInfo.blocksize; ++i) { view.setInt16(2 * (frameInfo.channels * i + channel), channelData.getInt16(2 * i, true), true); @@ -784,7 +784,7 @@ class PlayBuffer { this.onended = (_playBuffer: PlayBuffer) => { }; } - public onended: (playBuffer: PlayBuffer) => void + public onended: (_playBuffer: PlayBuffer) => void start() { this.source.onended = () => { @@ -802,8 +802,8 @@ class PlayBuffer { class PcmDecoder extends Decoder { setHeader(buffer: ArrayBuffer): SampleFormat | null { - let sampleFormat = new SampleFormat(); - let view = new DataView(buffer); + const sampleFormat = new SampleFormat(); + const view = new DataView(buffer); sampleFormat.channels = view.getUint16(22, true); sampleFormat.rate = view.getUint32(24, true); sampleFormat.bits = view.getUint16(34, true); @@ -885,10 +885,10 @@ class SnapStream { } private onMessage(msg: MessageEvent) { - let view = new DataView(msg.data); - let type = view.getUint16(0, true); + const view = new DataView(msg.data); + const type = view.getUint16(0, true); if (type === 1) { - let codec = new CodecMessage(msg.data); + const codec = new CodecMessage(msg.data); console.log("Codec: " + codec.codec); if (codec.codec === "flac") { this.decoder = new FlacDecoder(); @@ -932,9 +932,9 @@ class SnapStream { } } } else if (type === 2) { - let pcmChunk = new PcmChunkMessage(msg.data, this.sampleFormat as SampleFormat); + const pcmChunk = new PcmChunkMessage(msg.data, this.sampleFormat as SampleFormat); if (this.decoder) { - let decoded = this.decoder.decode(pcmChunk); + const decoded = this.decoder.decode(pcmChunk); if (decoded) { this.stream!.addChunk(decoded); } @@ -946,7 +946,7 @@ class SnapStream { console.log("ServerSettings bufferMs: " + this.serverSettings.bufferMs + ", latency: " + this.serverSettings.latency + ", volume: " + this.serverSettings.volumePercent + ", muted: " + this.serverSettings.muted); } else if (type === 4) { if (this.timeProvider) { - let time = new TimeMessage(msg.data); + const time = new TimeMessage(msg.data); this.timeProvider.setDiff(time.latency.getMilliseconds(), this.timeProvider.now() - time.sent.getMilliseconds()); } // console.log("Time sec: " + time.latency.sec + ", usec: " + time.latency.usec + ", diff: " + this.timeProvider.diff); @@ -965,7 +965,7 @@ class SnapStream { } private syncTime() { - let t = new TimeMessage(); + const t = new TimeMessage(); t.latency.setMilliseconds(this.timeProvider.now()); this.sendMessage(t); // console.log("prepareSource median: " + Math.round(this.median * 10) / 10); @@ -977,7 +977,7 @@ class SnapStream { // } this.ctx.suspend(); while (this.audioBuffers.length > 0) { - let buffer = this.audioBuffers.pop(); + const buffer = this.audioBuffers.pop(); buffer!.onended = () => { }; buffer!.source.stop(); } @@ -1003,12 +1003,12 @@ class SnapStream { } public playNext() { - let buffer = this.freeBuffers.pop() || this.ctx!.createBuffer(this.sampleFormat!.channels, this.bufferFrameCount, this.sampleFormat!.rate); - let playTimeMs = (this.playTime + this.latency) * 1000 - this.bufferMs; + const buffer = this.freeBuffers.pop() || this.ctx!.createBuffer(this.sampleFormat!.channels, this.bufferFrameCount, this.sampleFormat!.rate); + const playTimeMs = (this.playTime + this.latency) * 1000 - this.bufferMs; this.stream!.getNextBuffer(buffer, playTimeMs); - let source = this.ctx!.createBufferSource(); - let playBuffer = new PlayBuffer(buffer, this.playTime, source, this.gainNode!); + const source = this.ctx!.createBufferSource(); + const playBuffer = new PlayBuffer(buffer, this.playTime, source, this.gainNode!); this.audioBuffers.push(playBuffer); playBuffer.num = ++this.bufferNum; playBuffer.onended = (buffer: PlayBuffer) => {