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.
Files changed (45) hide show
  1. package/.gitattributes +2 -0
  2. package/.prettierignore +7 -0
  3. package/.prettierrc.js +10 -0
  4. package/.vscode/launch.json +40 -0
  5. package/.vscode/tasks.json +24 -0
  6. package/Databases/Databases.ts +69 -0
  7. package/Databases/DbConnection.ts +42 -0
  8. package/Databases/index.ts +2 -0
  9. package/LICENSE +674 -0
  10. package/LogEmitter/index.ts +51 -0
  11. package/README.md +83 -0
  12. package/StageLinq/index.ts +58 -0
  13. package/TODO.md +5 -0
  14. package/albumArt/index.ts +2 -0
  15. package/albumArt/maybeDownloadFiles.ts +34 -0
  16. package/cli/index.ts +142 -0
  17. package/devices/Player.ts +182 -0
  18. package/devices/PlayerMessageQueue.ts +62 -0
  19. package/index.ts +5 -0
  20. package/network/NetworkDevice.ts +287 -0
  21. package/network/StageLinqDevices.ts +215 -0
  22. package/network/StageLinqListener.ts +50 -0
  23. package/network/announce.ts +133 -0
  24. package/network/index.ts +4 -0
  25. package/package.json +31 -0
  26. package/services/FileTransfer.ts +298 -0
  27. package/services/Service.ts +144 -0
  28. package/services/StateMap.ts +170 -0
  29. package/services/index.ts +3 -0
  30. package/stagelinq.code-workspace +16 -0
  31. package/tsconfig.json +13 -0
  32. package/types/common.ts +240 -0
  33. package/types/database.ts +50 -0
  34. package/types/index.ts +53 -0
  35. package/types/player.ts +41 -0
  36. package/types/tokens.ts +39 -0
  37. package/utils/Context.ts +45 -0
  38. package/utils/ReadContext.ts +114 -0
  39. package/utils/WriteContext.ts +105 -0
  40. package/utils/getTempFilePath.ts +23 -0
  41. package/utils/hex.ts +62 -0
  42. package/utils/index.ts +6 -0
  43. package/utils/log.ts +0 -0
  44. package/utils/sleep.ts +3 -0
  45. package/utils/tcp.ts +17 -0
package/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ # Set the default behavior, in case people don't have core.autocrlf set.
2
+ * text=auto eol=lf
@@ -0,0 +1,7 @@
1
+ www/
2
+ node_modules/
3
+ .DS_Store
4
+ .yarn
5
+ .github
6
+ *.md
7
+ *.yml
package/.prettierrc.js ADDED
@@ -0,0 +1,10 @@
1
+ module.exports = {
2
+ trailingComma: 'es5',
3
+ tabWidth: 2,
4
+ semi: true,
5
+ singleQuote: true,
6
+ useTabs: false,
7
+ bracketSpacing: true,
8
+ endOfLine: 'lf',
9
+ printWidth: 120,
10
+ };
@@ -0,0 +1,40 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "type": "node",
9
+ "request": "launch",
10
+ "name": "Launch JS",
11
+ "program": "${workspaceFolder}/dist/cli.js",
12
+ "internalConsoleOptions": "openOnSessionStart",
13
+ "sourceMaps": true,
14
+ "smartStep": true,
15
+ "outputCapture": "std",
16
+ "skipFiles": [
17
+ "${workspaceFolder}/node_modules/**/*.js",
18
+ "${workspaceFolder}/lib/**/*.js",
19
+ "<node_internals>/**/*.js"
20
+ ]
21
+ },
22
+ {
23
+ "type": "node",
24
+ "request": "launch",
25
+ "name": "Launch TS",
26
+ "program": "${workspaceFolder}/cli/index.ts",
27
+ "preLaunchTask": "tsc: build - tsconfig.json",
28
+ "internalConsoleOptions": "openOnSessionStart",
29
+ "outFiles": ["${workspaceFolder}/dist/**/*.js"],
30
+ "sourceMaps": true,
31
+ "smartStep": true,
32
+ "outputCapture": "std",
33
+ "skipFiles": [
34
+ "${workspaceFolder}/node_modules/**/*.js",
35
+ "${workspaceFolder}/lib/**/*.js",
36
+ "<node_internals>/**/*.js"
37
+ ]
38
+ }
39
+ ]
40
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "tasks": [
4
+ {
5
+ "type": "typescript",
6
+ "tsconfig": "tsconfig.json",
7
+ "option": "watch",
8
+ "presentation": {
9
+ "echo": true,
10
+ "reveal": "silent",
11
+ "focus": false,
12
+ "panel": "shared"
13
+ },
14
+ "isBackground": true,
15
+ "runOptions": { "runOn": "folderOpen" },
16
+ "problemMatcher": ["$tsc-watch"],
17
+ "group": {
18
+ "kind": "build",
19
+ "isDefault": true
20
+ },
21
+ "label": "tsc: watch - tsconfig.json"
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,69 @@
1
+ import { EventEmitter } from 'stream';
2
+ import { FileTransfer } from '../services';
3
+ import { getTempFilePath } from '../albumArt';
4
+ import { NetworkDevice } from '../network';
5
+ import * as fs from 'fs';
6
+ import { Logger } from '../LogEmitter';
7
+ import { ConnectionInfo, Source } from '../types';
8
+
9
+ export declare interface Databases {
10
+ on(event: 'dbDownloaded', listener: (sourceName: string, dbPath: string) => void): this;
11
+ on(event: 'dbDownloading', listener: (sourceName: string, dbPath: string) => void): this;
12
+ on(event: 'dbProgress', listener: (sourceName: string, total: number, bytesDownloaded: number, percentComplete: number) => void): this;
13
+ }
14
+
15
+ export class Databases extends EventEmitter {
16
+
17
+ sources: Map<string, string> = new Map();
18
+
19
+ constructor() {
20
+ super();
21
+ }
22
+
23
+ async downloadSourcesFromDevice(connectionInfo: ConnectionInfo, networkDevice: NetworkDevice) {
24
+ const service = await networkDevice.connectToService(FileTransfer);
25
+ const sources = await service.getSources();
26
+ const output: string[] = [];
27
+ for (const source of sources) {
28
+ const dbConnectionName = `${connectionInfo.address}_${connectionInfo.port}_${source.name}`;
29
+ if (this.sources.has(dbConnectionName)) {
30
+ Logger.debug(`Already seen ${source} on ${connectionInfo.address}:${connectionInfo.port}`);
31
+ } else {
32
+ await this.downloadDb(dbConnectionName, service, source);
33
+ output.push(dbConnectionName);
34
+ }
35
+ }
36
+ return output;
37
+ }
38
+
39
+ /**
40
+ * Download databases from this network source.
41
+ */
42
+ async downloadDb(sourceId: string, service: FileTransfer, source: Source) {
43
+ const dbPath = getTempFilePath(`${sourceId}/m.db`);
44
+
45
+ // Read database from source
46
+ Logger.debug(`Reading database ${sourceId}`);
47
+ this.emit('dbDownloading', sourceId, dbPath);
48
+
49
+ service.on('fileTransferProgress', (progress) => {
50
+ this.emit('dbProgress', sourceId, progress.total, progress.bytesDownloaded, progress.percentComplete);
51
+ });
52
+
53
+ // Save database to a file
54
+ const file = await service.getFile(source.database.location);
55
+ Logger.debug(`Saving ${sourceId} to ${dbPath}`);
56
+ fs.writeFileSync(dbPath, Buffer.from(file));
57
+ this.sources.set(sourceId, dbPath);
58
+
59
+ Logger.debug(`Downloaded ${sourceId} to ${dbPath}`);
60
+ this.emit('dbDownloaded', sourceId, dbPath);
61
+ }
62
+
63
+ getDbPath(dbSourceName: string) {
64
+ if (!this.sources.has(dbSourceName))
65
+ throw new Error(`Database name ${dbSourceName} does not exist`);
66
+ return this.sources.get(dbSourceName);
67
+ }
68
+
69
+ }
@@ -0,0 +1,42 @@
1
+ import Database = require('better-sqlite3');
2
+
3
+
4
+ export class DbConnection {
5
+
6
+ private db: Database.Database;
7
+ private dbPath: string;
8
+
9
+ constructor(dbPath: string) {
10
+ this.dbPath = dbPath;
11
+ console.debug(`Opening ${this.dbPath}`);
12
+ this.db = new Database(this.dbPath);
13
+ }
14
+
15
+ /**
16
+ * Execute a SQL query.
17
+ *
18
+ * @param query SQL query to execute
19
+ * @param params Parameters for BetterSqlite3 result.all.
20
+ * @returns
21
+ */
22
+ querySource<T>(query: string, ...params: any[]): T[] {
23
+ console.debug(`Querying ${this.dbPath}: `);
24
+ const result = this.db.prepare(query);
25
+ return result.all(params);
26
+ }
27
+
28
+ /**
29
+ * Return track's DB entry.
30
+ *
31
+ * @param trackPath Path of track on the source's filesystem.
32
+ * @returns
33
+ */
34
+ getTrackInfo(trackPath: string) {
35
+ return this.querySource(`SELECT * FROM Track WHERE path = '${trackPath}'`);
36
+ }
37
+
38
+ close() {
39
+ console.debug(`Closing ${this.dbPath}`);
40
+ this.db.close();
41
+ }
42
+ }
@@ -0,0 +1,2 @@
1
+ export * from './Databases';
2
+ export * from './DbConnection';