lox-slimproto 0.1.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.
@@ -0,0 +1,22 @@
1
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
+ // README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
3
+ {
4
+ "name": "Node.js & TypeScript",
5
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6
+ "image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm"
7
+
8
+ // Features to add to the dev container. More info: https://containers.dev/features.
9
+ // "features": {},
10
+
11
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
12
+ // "forwardPorts": [],
13
+
14
+ // Use 'postCreateCommand' to run commands after the container is created.
15
+ // "postCreateCommand": "yarn install",
16
+
17
+ // Configure tool-specific properties.
18
+ // "customizations": {},
19
+
20
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
21
+ // "remoteUser": "root"
22
+ }
@@ -0,0 +1,33 @@
1
+ name: publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*.*.*'
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ publish:
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: read
14
+ steps:
15
+ - name: Checkout
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Node
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: 20
22
+ registry-url: https://registry.npmjs.org
23
+
24
+ - name: Install deps
25
+ run: npm ci
26
+
27
+ - name: Build
28
+ run: npm run build
29
+
30
+ - name: Publish
31
+ run: npm publish
32
+ env:
33
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # lox-slimproto
2
+
3
+ SlimProto server/client utilities for controlling Squeezebox-compatible players from Node.js. This is a TypeScript port of aioslimproto with the full server + player-control implementation used by lox-audioserver.
4
+
5
+ ## Quick start (server)
6
+
7
+ ```ts
8
+ import { SlimServer, EventType } from "lox-slimproto";
9
+
10
+ const server = new SlimServer();
11
+ await server.start();
12
+
13
+ server.subscribe((event) => {
14
+ console.log(`[${event.type}]`, event.playerId, event.data);
15
+ });
16
+
17
+ process.on("SIGINT", async () => {
18
+ await server.stop();
19
+ process.exit(0);
20
+ });
21
+ ```
22
+
23
+ ## Quick start (playback control)
24
+
25
+ ```ts
26
+ import { SlimServer } from "lox-slimproto";
27
+
28
+ const server = new SlimServer();
29
+ await server.start();
30
+
31
+ const player = server.getPlayer("aa:bb:cc:dd:ee:ff");
32
+ if (player) {
33
+ await player.playUrl("http://host:7090/streams/1/current.mp3", "audio/mpeg", {
34
+ title: "Now Playing",
35
+ artist: "Artist",
36
+ });
37
+ }
38
+ ```
39
+
40
+ ## What is implemented
41
+
42
+ - SlimProto TCP server with player tracking and event subscriptions.
43
+ - UDP discovery responses (legacy + TLV).
44
+ - SlimClient playback control: play/pause/stop, volume, metadata, and power.
45
+ - HTTP stream control and codec negotiation.
46
+ - Sync helpers (`pauseFor`, `skipOver`, `unpauseAt`) and heartbeat/jiffies tracking.
47
+ - Typed enums and helpers mirroring the reference implementation.
48
+
49
+ ## Notes
50
+
51
+ - This package focuses on server-side SlimProto and player control; it does not implement LMS CLI or display rendering.
@@ -0,0 +1,78 @@
1
+ import net from 'net';
2
+ import { EventType, MediaDetails, MediaMetadata, PlayerState, TransitionType } from './models.js';
3
+ type SlimClientCallback = (client: SlimClient, eventType: EventType, data?: unknown) => void | Promise<void>;
4
+ export declare class SlimClient {
5
+ private readonly socket;
6
+ private readonly callback;
7
+ private readonly remoteAddress?;
8
+ private readonly remotePort?;
9
+ private readonly volumeControl;
10
+ private buffer;
11
+ private _connected;
12
+ private _playerId;
13
+ private _deviceType;
14
+ private capabilities;
15
+ private _deviceName;
16
+ private _powered;
17
+ private _muted;
18
+ private _state;
19
+ private _jiffies;
20
+ private _lastTimestamp;
21
+ private _elapsedMs;
22
+ private _currentMedia;
23
+ private _bufferingMedia;
24
+ private _nextMedia;
25
+ private _autoPlay;
26
+ private _heartbeatTimer;
27
+ private _heartbeatId;
28
+ constructor(socket: net.Socket, callback: SlimClientCallback);
29
+ disconnect(): void;
30
+ get connected(): boolean;
31
+ get playerId(): string;
32
+ get deviceType(): string;
33
+ get name(): string;
34
+ get deviceAddress(): string | undefined;
35
+ get devicePort(): number | undefined;
36
+ get state(): PlayerState;
37
+ get currentMedia(): MediaDetails | null;
38
+ get supportedCodecs(): string[];
39
+ get maxSampleRate(): number;
40
+ get firmware(): string;
41
+ get volumeLevel(): number;
42
+ get elapsedMilliseconds(): number;
43
+ get jiffies(): number;
44
+ get lastHeartbeatAt(): number | null;
45
+ stop(): Promise<void>;
46
+ play(): Promise<void>;
47
+ pause(): Promise<void>;
48
+ pauseFor(millis: number): Promise<void>;
49
+ skipOver(millis: number): Promise<void>;
50
+ unpauseAt(timestamp: number): Promise<void>;
51
+ power(powered?: boolean): Promise<void>;
52
+ volumeSet(volumeLevel: number): Promise<void>;
53
+ volumeUp(): Promise<void>;
54
+ volumeDown(): Promise<void>;
55
+ mute(muted?: boolean): Promise<void>;
56
+ playUrl(url: string, mimeType?: string | null, metadata?: MediaMetadata, transition?: TransitionType, transitionDuration?: number, enqueue?: boolean, autostart?: boolean, sendFlush?: boolean): Promise<void>;
57
+ private sendAudg;
58
+ private sendFrame;
59
+ private sendStrm;
60
+ private handleDisconnect;
61
+ private onData;
62
+ private processHelo;
63
+ private processButn;
64
+ private processKnob;
65
+ private processIr;
66
+ private processDsco;
67
+ private processStat;
68
+ private processStatHeartbeat;
69
+ private processResp;
70
+ private processSetd;
71
+ private parseCodc;
72
+ private signalUpdate;
73
+ private signalEvent;
74
+ private startHeartbeat;
75
+ private togglePower;
76
+ private togglePause;
77
+ }
78
+ export {};