stagelinq 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -0
- package/.prettierignore +7 -0
- package/.prettierrc.js +10 -0
- package/.vscode/launch.json +40 -0
- package/.vscode/tasks.json +24 -0
- package/Databases/Databases.ts +69 -0
- package/Databases/DbConnection.ts +42 -0
- package/Databases/index.ts +2 -0
- package/LICENSE +674 -0
- package/LogEmitter/index.ts +51 -0
- package/README.md +83 -0
- package/StageLinq/index.ts +58 -0
- package/TODO.md +5 -0
- package/albumArt/index.ts +2 -0
- package/albumArt/maybeDownloadFiles.ts +34 -0
- package/cli/index.ts +142 -0
- package/devices/Player.ts +182 -0
- package/devices/PlayerMessageQueue.ts +62 -0
- package/index.ts +5 -0
- package/network/NetworkDevice.ts +287 -0
- package/network/StageLinqDevices.ts +215 -0
- package/network/StageLinqListener.ts +50 -0
- package/network/announce.ts +133 -0
- package/network/index.ts +4 -0
- package/package.json +31 -0
- package/services/FileTransfer.ts +298 -0
- package/services/Service.ts +144 -0
- package/services/StateMap.ts +170 -0
- package/services/index.ts +3 -0
- package/stagelinq.code-workspace +16 -0
- package/tsconfig.json +13 -0
- package/types/common.ts +240 -0
- package/types/database.ts +50 -0
- package/types/index.ts +53 -0
- package/types/player.ts +41 -0
- package/types/tokens.ts +39 -0
- package/utils/Context.ts +45 -0
- package/utils/ReadContext.ts +114 -0
- package/utils/WriteContext.ts +105 -0
- package/utils/getTempFilePath.ts +23 -0
- package/utils/hex.ts +62 -0
- package/utils/index.ts +6 -0
- package/utils/log.ts +0 -0
- package/utils/sleep.ts +3 -0
- package/utils/tcp.ts +17 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const assert = require('assert');
|
|
3
|
+
import { Context } from './Context';
|
|
4
|
+
|
|
5
|
+
interface WriteContextConstructOptions {
|
|
6
|
+
size?: number;
|
|
7
|
+
autoGrow?: boolean;
|
|
8
|
+
littleEndian?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export class WriteContext extends Context {
|
|
12
|
+
autoGrow: boolean;
|
|
13
|
+
|
|
14
|
+
constructor(p_options?: WriteContextConstructOptions) {
|
|
15
|
+
const buffer = new ArrayBuffer(p_options && p_options.size > 0 ? p_options.size : 128);
|
|
16
|
+
super(buffer, !p_options ? false : !!p_options.littleEndian);
|
|
17
|
+
this.autoGrow = !p_options || (p_options.autoGrow ? !!p_options.autoGrow : true);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getBuffer(): Buffer {
|
|
21
|
+
const newBuf = Buffer.from(this.buffer, 0, this.pos);
|
|
22
|
+
return newBuf;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
sizeLeft(): number {
|
|
26
|
+
return this.buffer.byteLength - this.pos;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
checkSize(p_size: number): void {
|
|
30
|
+
while (true) {
|
|
31
|
+
const diff = this.sizeLeft() - p_size;
|
|
32
|
+
if (diff >= 0) {
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
if (this.autoGrow) {
|
|
36
|
+
this.resize();
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
assert.fail(`Writing ${-diff} bytes OOB of fixed size buffer`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
resize(): void {
|
|
44
|
+
assert(this.autoGrow);
|
|
45
|
+
const size = this.buffer.byteLength;
|
|
46
|
+
const newBuffer = new ArrayBuffer(size * 2);
|
|
47
|
+
new Uint8Array(newBuffer).set(new Uint8Array(this.buffer));
|
|
48
|
+
this.buffer = newBuffer;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
write(p_buffer: Uint8Array, p_bytes: number = -1): number {
|
|
52
|
+
if (p_bytes <= 0) {
|
|
53
|
+
p_bytes = p_buffer.byteLength;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.checkSize(p_bytes);
|
|
57
|
+
|
|
58
|
+
new Uint8Array(this.buffer).set(p_buffer, this.pos);
|
|
59
|
+
this.pos += p_bytes;
|
|
60
|
+
return p_bytes;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
writeFixedSizedString(p_string: string): number {
|
|
64
|
+
for (let i = 0; i < p_string.length; ++i) {
|
|
65
|
+
this.writeUInt8(p_string.charCodeAt(i));
|
|
66
|
+
}
|
|
67
|
+
return p_string.length;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
writeNetworkStringUTF16(p_string: string): number {
|
|
71
|
+
let written = this.writeUInt32(p_string.length * 2);
|
|
72
|
+
for (let i = 0; i < p_string.length; ++i) {
|
|
73
|
+
written += this.writeUInt16(p_string.charCodeAt(i));
|
|
74
|
+
}
|
|
75
|
+
return written;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
writeUInt64(p_value: bigint): number {
|
|
79
|
+
this.checkSize(8);
|
|
80
|
+
new DataView(this.buffer).setBigUint64(this.pos, p_value, this.littleEndian);
|
|
81
|
+
this.pos += 8;
|
|
82
|
+
return 8;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
writeUInt32(p_value: number): number {
|
|
86
|
+
this.checkSize(4);
|
|
87
|
+
new DataView(this.buffer).setUint32(this.pos, p_value, this.littleEndian);
|
|
88
|
+
this.pos += 4;
|
|
89
|
+
return 4;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
writeUInt16(p_value: number): number {
|
|
93
|
+
this.checkSize(2);
|
|
94
|
+
new DataView(this.buffer).setUint16(this.pos, p_value, this.littleEndian);
|
|
95
|
+
this.pos += 2;
|
|
96
|
+
return 2;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
writeUInt8(p_value: number): number {
|
|
100
|
+
this.checkSize(1);
|
|
101
|
+
new DataView(this.buffer).setUint8(this.pos, p_value);
|
|
102
|
+
this.pos += 1;
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as os from 'os';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Recursively create a directory under the OS's temp path.
|
|
7
|
+
*
|
|
8
|
+
* @param p_path Directory to create including filename
|
|
9
|
+
* @returns Absolute path
|
|
10
|
+
*/
|
|
11
|
+
export function getTempFilePath(p_path: string) {
|
|
12
|
+
const tmpPath = `/${os.tmpdir()}/localdb/${p_path}`;
|
|
13
|
+
let paths = tmpPath.split(/[/\\]/).filter((e) => e.length > 0);
|
|
14
|
+
const isFolder = p_path.endsWith('/') || p_path.endsWith('\\');
|
|
15
|
+
let filename = '';
|
|
16
|
+
if (isFolder === false) {
|
|
17
|
+
filename = paths[paths.length - 1];
|
|
18
|
+
paths.pop();
|
|
19
|
+
}
|
|
20
|
+
const newPath = paths.join('/');
|
|
21
|
+
fs.mkdirSync(path.resolve('/', newPath), { recursive: true });
|
|
22
|
+
return path.resolve('/', newPath, filename);
|
|
23
|
+
}
|
package/utils/hex.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// Based on https://www.npmjs.com/package/hex
|
|
2
|
+
const zero = function (n: number, max: number) {
|
|
3
|
+
let str = n.toString(16).toUpperCase();
|
|
4
|
+
while (str.length < max) {
|
|
5
|
+
str = '0' + str;
|
|
6
|
+
}
|
|
7
|
+
return str;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function hex(p_buffer: Uint8Array, p_columns: number = 16) {
|
|
11
|
+
const rows = Math.ceil(p_buffer.length / p_columns);
|
|
12
|
+
const last = p_buffer.length % p_columns || p_columns;
|
|
13
|
+
let offsetLength = p_buffer.length.toString(16).length;
|
|
14
|
+
if (offsetLength < 6) offsetLength = 6;
|
|
15
|
+
|
|
16
|
+
let str = 'Offset';
|
|
17
|
+
while (str.length < offsetLength) {
|
|
18
|
+
str += ' ';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
str = '\u001b[36m' + str + ' ';
|
|
22
|
+
|
|
23
|
+
for (let i = 0; i < p_columns; i++) {
|
|
24
|
+
str += ' ' + zero(i, 2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
str += '\u001b[0m';
|
|
28
|
+
if (p_buffer.length) str += '\n';
|
|
29
|
+
|
|
30
|
+
let b = 0;
|
|
31
|
+
let lastBytes: number;
|
|
32
|
+
let lastSpaces: number;
|
|
33
|
+
let v: number;
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < rows; i++) {
|
|
36
|
+
str += '\u001b[36m' + zero(b, offsetLength) + '\u001b[0m ';
|
|
37
|
+
lastBytes = i === rows - 1 ? last : p_columns;
|
|
38
|
+
lastSpaces = p_columns - lastBytes;
|
|
39
|
+
|
|
40
|
+
for (let j = 0; j < lastBytes; j++) {
|
|
41
|
+
str += ' ' + zero(p_buffer[b], 2);
|
|
42
|
+
b++;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (let j = 0; j < lastSpaces; j++) {
|
|
46
|
+
str += ' ';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
b -= lastBytes;
|
|
50
|
+
str += ' ';
|
|
51
|
+
|
|
52
|
+
for (let j = 0; j < lastBytes; j++) {
|
|
53
|
+
v = p_buffer[b];
|
|
54
|
+
str += (v > 31 && v < 127) || v > 159 ? String.fromCharCode(v) : '.';
|
|
55
|
+
b++;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
str += '\n';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
process.stdout.write(str);
|
|
62
|
+
}
|
package/utils/index.ts
ADDED
package/utils/log.ts
ADDED
|
File without changes
|
package/utils/sleep.ts
ADDED
package/utils/tcp.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Socket as TCPSocket } from 'net';
|
|
2
|
+
import { PromiseSocket } from 'promise-socket';
|
|
3
|
+
import { CONNECT_TIMEOUT } from '../types';
|
|
4
|
+
import { Logger } from '../LogEmitter';
|
|
5
|
+
|
|
6
|
+
export type Connection = PromiseSocket<TCPSocket>;
|
|
7
|
+
|
|
8
|
+
export async function connect(p_ip: string, p_port: number): Promise<Connection> {
|
|
9
|
+
const socket = new TCPSocket();
|
|
10
|
+
socket.setTimeout(CONNECT_TIMEOUT);
|
|
11
|
+
const promiseSocket = new PromiseSocket(socket);
|
|
12
|
+
await promiseSocket.connect(p_port, p_ip).catch((e) => {
|
|
13
|
+
throw new Error(`Failed to connect to '${p_ip}:${p_port}': ${e}`);
|
|
14
|
+
});
|
|
15
|
+
Logger.debug(`TCP connection to '${p_ip}:${p_port}' local port: ${promiseSocket.socket.localPort}`);
|
|
16
|
+
return promiseSocket;
|
|
17
|
+
}
|