@groovenet/player 0.1.3 → 0.1.5

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 (73) hide show
  1. package/MPRIS.md +97 -0
  2. package/OWNTONE.md +145 -0
  3. package/README.md +17 -0
  4. package/SERVER_PLAYERS.md +348 -0
  5. package/build/daemon.d.ts.map +1 -1
  6. package/build/daemon.js +3 -0
  7. package/build/daemon.js.map +1 -1
  8. package/build/index.d.ts +1 -0
  9. package/build/index.d.ts.map +1 -1
  10. package/build/index.js +1 -0
  11. package/build/index.js.map +1 -1
  12. package/build/mpris.d.ts +11 -0
  13. package/build/mpris.d.ts.map +1 -0
  14. package/build/mpris.js +145 -0
  15. package/build/mpris.js.map +1 -0
  16. package/build/mprisBin.d.ts +3 -0
  17. package/build/mprisBin.d.ts.map +1 -0
  18. package/build/mprisBin.js +26 -0
  19. package/build/mprisBin.js.map +1 -0
  20. package/build/mprisMapping.d.ts +12 -0
  21. package/build/mprisMapping.d.ts.map +1 -0
  22. package/build/mprisMapping.js +35 -0
  23. package/build/mprisMapping.js.map +1 -0
  24. package/build/mpvBackend.d.ts.map +1 -1
  25. package/build/mpvBackend.js +2 -1
  26. package/build/mpvBackend.js.map +1 -1
  27. package/build/ownToneBackend.d.ts +62 -0
  28. package/build/ownToneBackend.d.ts.map +1 -0
  29. package/build/ownToneBackend.js +349 -0
  30. package/build/ownToneBackend.js.map +1 -0
  31. package/build/player.d.ts +1 -0
  32. package/build/player.d.ts.map +1 -1
  33. package/build/player.js +11 -0
  34. package/build/player.js.map +1 -1
  35. package/build/protocol.d.ts.map +1 -1
  36. package/build/protocol.js +1 -0
  37. package/build/protocol.js.map +1 -1
  38. package/build/resolver.d.ts +3 -1
  39. package/build/resolver.d.ts.map +1 -1
  40. package/build/resolver.js +30 -1
  41. package/build/resolver.js.map +1 -1
  42. package/build/server/bin.d.ts +3 -0
  43. package/build/server/bin.d.ts.map +1 -0
  44. package/build/server/bin.js +7 -0
  45. package/build/server/bin.js.map +1 -0
  46. package/build/server/http.d.ts +5 -0
  47. package/build/server/http.d.ts.map +1 -0
  48. package/build/server/http.js +129 -0
  49. package/build/server/http.js.map +1 -0
  50. package/build/server/manager.d.ts +61 -0
  51. package/build/server/manager.d.ts.map +1 -0
  52. package/build/server/manager.js +555 -0
  53. package/build/server/manager.js.map +1 -0
  54. package/build/server/observer.d.ts +10 -0
  55. package/build/server/observer.d.ts.map +1 -0
  56. package/build/server/observer.js +47 -0
  57. package/build/server/observer.js.map +1 -0
  58. package/build/server/runtime.d.ts +18 -0
  59. package/build/server/runtime.d.ts.map +1 -0
  60. package/build/server/runtime.js +101 -0
  61. package/build/server/runtime.js.map +1 -0
  62. package/build/server/store.d.ts +47 -0
  63. package/build/server/store.d.ts.map +1 -0
  64. package/build/server/store.js +120 -0
  65. package/build/server/store.js.map +1 -0
  66. package/build/types.d.ts +3 -1
  67. package/build/types.d.ts.map +1 -1
  68. package/build/types.js.map +1 -1
  69. package/owntone/Dockerfile +27 -0
  70. package/owntone/smoke.mjs +135 -0
  71. package/owntone/terminal-v1.patch +96 -0
  72. package/package.json +24 -4
  73. package/scripts/mpris-smoke.mjs +54 -0
@@ -0,0 +1,555 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { randomUUID } from "node:crypto";
3
+ import { createServerPlayerSchema, serverPlayerCommandSchema } from "@groovenet/contracts";
4
+ import { audioSource } from "../resolver.js";
5
+ import { PlayerError } from "../types.js";
6
+ import { advanceProgress, initialProgress, isPlay } from "../playThreshold.js";
7
+ import { ServerPlayerError } from "./store.js";
8
+ export const unknownSpeaker = () => ({ availability: "unknown", observed_at: null, source: "unconfigured", sender_identity: "unknown" });
9
+ const errorValue = (error) => error instanceof PlayerError || error instanceof ServerPlayerError ? { code: error.code, message: error.message } : { code: "PLAYER_OPERATION_FAILED", message: "Player operation failed" };
10
+ const clone = (value) => structuredClone(value);
11
+ /** Owns all player lifecycles; no HTTP connection owns a backend. */
12
+ export class ServerPlayerManager extends EventEmitter {
13
+ store;
14
+ engines;
15
+ observe;
16
+ playLogging;
17
+ players = new Map();
18
+ runtimes = new Map();
19
+ generation = 0;
20
+ tail = Promise.resolve();
21
+ stopping = false;
22
+ checkpointAt = new Map();
23
+ progress = new Map();
24
+ queuedPlays = new Set();
25
+ retrying = false;
26
+ constructor(store, engines, observe = async () => unknownSpeaker(), playLogging) {
27
+ super();
28
+ this.store = store;
29
+ this.engines = engines;
30
+ this.observe = observe;
31
+ this.playLogging = playLogging;
32
+ }
33
+ /** Retry durable deliveries independently of queue changes and playback. */
34
+ async retryPlays() {
35
+ if (!this.playLogging || this.retrying || this.stopping)
36
+ return;
37
+ this.retrying = true;
38
+ try {
39
+ for (const play of await this.store.pendingPlays()) {
40
+ try {
41
+ await this.playLogging.logPlay(play);
42
+ await this.store.markPlayLogged(play.entryId);
43
+ }
44
+ catch (error) {
45
+ this.emit("play-log-error", error);
46
+ }
47
+ }
48
+ }
49
+ catch (error) {
50
+ this.emit("play-log-error", error);
51
+ }
52
+ finally {
53
+ this.retrying = false;
54
+ }
55
+ }
56
+ serial(action) {
57
+ const result = this.tail.then(action);
58
+ this.tail = result.catch(() => { });
59
+ return result;
60
+ }
61
+ async initialize() {
62
+ // No engine object or network connection is created during restoration.
63
+ for (const saved of await this.store.list()) {
64
+ const player = clone(saved);
65
+ player.assigned_output = null;
66
+ player.state.status = "stopped";
67
+ player.state.checkpoint = true;
68
+ this.players.set(player.id, await this.store.save(player, saved.revision));
69
+ }
70
+ }
71
+ engineIds() { return Object.keys(this.engines).sort(); }
72
+ list() { return [...this.players.values()].map(clone); }
73
+ get(id) {
74
+ const player = this.players.get(id);
75
+ if (!player)
76
+ throw new ServerPlayerError("PLAYER_NOT_FOUND", "Player does not exist", 404);
77
+ return clone(player);
78
+ }
79
+ create(input) {
80
+ return this.serial(async () => {
81
+ this.available();
82
+ const parsed = createServerPlayerSchema.parse(input);
83
+ if (!this.engines[parsed.engine_id])
84
+ throw new ServerPlayerError("ENGINE_NOT_CONFIGURED", "Engine is not configured on this server", 400);
85
+ const player = await this.store.create(parsed, { queue: [], current_entry_id: null, status: "stopped", position: 0, duration: null, volume: 50, desired_output: null, checkpoint: false, error: null });
86
+ this.players.set(player.id, player);
87
+ this.publish(player);
88
+ return clone(player);
89
+ });
90
+ }
91
+ async devices(id) {
92
+ const player = this.get(id);
93
+ const runtime = this.runtimes.get(id);
94
+ const backend = runtime?.backend ?? this.engine(player).create();
95
+ try {
96
+ const outputs = await backend.listDevices();
97
+ const nameCounts = new Map();
98
+ for (const output of outputs)
99
+ nameCounts.set(output.name, (nameCounts.get(output.name) ?? 0) + 1);
100
+ return await Promise.all(outputs.map(async (output) => ({ ...output,
101
+ assigned_player_id: this.list().find((p) => p.assigned_output === output.id)?.id ?? null,
102
+ desired_by: this.list().filter((p) => p.state.desired_output === output.id).map((p) => p.id),
103
+ observed: await this.observe(output.id, { outputName: nameCounts.get(output.name) === 1 ? output.name : undefined }),
104
+ })));
105
+ }
106
+ finally {
107
+ if (!runtime)
108
+ await backend.close();
109
+ }
110
+ }
111
+ command(id, input) {
112
+ return this.serial(async () => {
113
+ this.available();
114
+ const command = serverPlayerCommandSchema.parse(input);
115
+ let player = this.get(id);
116
+ if (command.expected_revision !== undefined)
117
+ this.revision(player, command.expected_revision);
118
+ if (command.type === "output.transfer")
119
+ return this.transfer(player, command);
120
+ try {
121
+ switch (command.type) {
122
+ case "rename":
123
+ player.name = command.name;
124
+ break;
125
+ case "availability.set":
126
+ player.availability_policy = command.availability_policy;
127
+ break;
128
+ case "queue.add": {
129
+ const at = command.at ?? player.state.queue.length;
130
+ if (at > player.state.queue.length || player.state.queue.length + command.tracks.length > 10000)
131
+ throw new ServerPlayerError("INVALID_QUEUE", "Queue insertion is out of range", 400);
132
+ const added = [];
133
+ for (const ref of command.tracks) {
134
+ const track = await this.store.resolve(ref);
135
+ if (!track)
136
+ throw new ServerPlayerError("TRACK_NOT_FOUND", "Queued track does not exist or is ambiguous", 404);
137
+ added.push({ ...ref, id: randomUUID(), title: track.title, artist: track.artist });
138
+ }
139
+ player.state.queue.splice(at, 0, ...added);
140
+ break;
141
+ }
142
+ case "queue.remove": {
143
+ const index = player.state.queue.findIndex((entry) => entry.id === command.entry_id);
144
+ if (index < 0)
145
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Queue entry does not exist", 404);
146
+ if (command.entry_id === player.state.current_entry_id)
147
+ await this.stop(player);
148
+ player.state.queue.splice(index, 1);
149
+ break;
150
+ }
151
+ case "queue.move": {
152
+ const index = player.state.queue.findIndex((entry) => entry.id === command.entry_id);
153
+ if (index < 0)
154
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Queue entry does not exist", 404);
155
+ if (command.to >= player.state.queue.length)
156
+ throw new ServerPlayerError("INVALID_QUEUE", "Queue move is out of range", 400);
157
+ player.state.queue.splice(command.to, 0, player.state.queue.splice(index, 1)[0]);
158
+ break;
159
+ }
160
+ case "queue.replace": return { player: await this.replaceQueue(player, command) };
161
+ case "queue.clear":
162
+ await this.stop(player);
163
+ player.state.queue = [];
164
+ break;
165
+ case "output.select":
166
+ if (this.runtimes.has(id))
167
+ await this.stop(player, true);
168
+ player.state.desired_output = command.output_id;
169
+ // Remembering a desired output does not reserve or connect it.
170
+ break;
171
+ case "play": {
172
+ const entryId = command.entry_id ?? player.state.current_entry_id ?? player.state.queue[0]?.id;
173
+ await this.play(player, entryId, command);
174
+ return { player: this.get(id) };
175
+ }
176
+ case "resume":
177
+ if (this.runtimes.has(id)) {
178
+ const backend = this.runtimes.get(id).backend;
179
+ if (await backend.outputConnection?.() !== "connected")
180
+ await this.requireAvailable(player, player.state.desired_output, command);
181
+ await backend.pause(false);
182
+ player.state.status = "playing";
183
+ player.state.checkpoint = false;
184
+ }
185
+ else {
186
+ await this.play(player, player.state.current_entry_id ?? undefined, command);
187
+ return { player: this.get(id) };
188
+ }
189
+ break;
190
+ case "pause":
191
+ await this.active(id).backend.pause(true);
192
+ player.state.status = "paused";
193
+ break;
194
+ case "stop":
195
+ await this.stop(player);
196
+ break;
197
+ case "next":
198
+ case "previous": {
199
+ const index = player.state.queue.findIndex((entry) => entry.id === player.state.current_entry_id);
200
+ const next = command.type === "next" ? index + 1 : Math.max(0, index - 1);
201
+ if (next >= player.state.queue.length) {
202
+ await this.stop(player);
203
+ player.state.status = "ended";
204
+ }
205
+ else {
206
+ await this.play(player, player.state.queue[next]?.id, command, false);
207
+ return { player: this.get(id) };
208
+ }
209
+ break;
210
+ }
211
+ case "seek":
212
+ if (!player.state.current_entry_id)
213
+ throw new ServerPlayerError("NO_CURRENT_TRACK", "No current track", 400);
214
+ if (this.runtimes.has(id))
215
+ await this.active(id).backend.seek(command.seconds);
216
+ player.state.position = command.seconds;
217
+ player.state.checkpoint = !this.runtimes.has(id);
218
+ break;
219
+ case "volume":
220
+ if (this.runtimes.has(id))
221
+ await this.active(id).backend.setVolume(command.volume);
222
+ player.state.volume = command.volume;
223
+ break;
224
+ }
225
+ // Queue/settings edits do not recover failed playback. Keep its cause
226
+ // visible until a transport command successfully leaves the error state.
227
+ if (player.state.status !== "error")
228
+ player.state.error = null;
229
+ player = await this.save(player);
230
+ return { player: clone(player) };
231
+ }
232
+ catch (error) {
233
+ // Validation failures do not mutate authoritative state. Engine operations
234
+ // persist an actionable error; they never advance or silently retry.
235
+ if (!(error instanceof ServerPlayerError)) {
236
+ player = this.get(id);
237
+ player.state.status = "error";
238
+ player.state.error = errorValue(error);
239
+ await this.save(player);
240
+ }
241
+ throw error;
242
+ }
243
+ });
244
+ }
245
+ async replaceQueue(player, command) {
246
+ // Resolve and validate the entire replacement before touching playback or
247
+ // saving anything. A bad final entry cannot leave a half-cleared queue.
248
+ const previousEntries = new Map(player.state.queue.map(entry => [entry.id, entry]));
249
+ const queue = [];
250
+ for (const ref of command.entries) {
251
+ const previous = ref.id ? previousEntries.get(ref.id) : undefined;
252
+ if (previous && (previous.track_id !== ref.track_id || previous.friend_id !== ref.friend_id))
253
+ throw new ServerPlayerError("INVALID_QUEUE", "An existing entry ID cannot identify a different track", 400);
254
+ const track = await this.store.resolve(ref).catch(() => {
255
+ throw new ServerPlayerError("TRACK_RESOLUTION_FAILED", "Unable to resolve replacement tracks", 503);
256
+ });
257
+ if (!track)
258
+ throw new ServerPlayerError("TRACK_NOT_FOUND", "Queued track does not exist or is ambiguous", 404);
259
+ queue.push({ ...ref, id: ref.id ?? randomUUID(), title: track.title, artist: track.artist });
260
+ }
261
+ const retained = queue.some(entry => entry.id === player.state.current_entry_id);
262
+ const current = command.current_entry_id === undefined
263
+ ? (retained ? player.state.current_entry_id : command.play ? queue[0]?.id ?? null : null)
264
+ : command.current_entry_id;
265
+ if (current !== null && !queue.some(entry => entry.id === current))
266
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Current entry must belong to the replacement queue", 404);
267
+ if (command.play && current === null)
268
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Select a replacement entry before playing", 400);
269
+ const unchanged = current !== null && current === player.state.current_entry_id;
270
+ const position = command.position ?? (unchanged ? player.state.position : 0);
271
+ if (unchanged && this.runtimes.has(player.id)) {
272
+ const backend = this.active(player.id).backend;
273
+ if (command.play && player.state.status !== "playing") {
274
+ if (await backend.outputConnection?.() !== "connected")
275
+ await this.requireAvailable(player, player.state.desired_output, command);
276
+ await backend.pause(false);
277
+ player.state.status = "playing";
278
+ player.state.checkpoint = false;
279
+ player.state.error = null;
280
+ }
281
+ if (position !== player.state.position)
282
+ await backend.seek(position);
283
+ player.state.queue = queue;
284
+ player.state.position = position;
285
+ return this.save(player);
286
+ }
287
+ if (command.play) {
288
+ // play validates output policy and audio before detaching the old backend.
289
+ player.state.queue = queue;
290
+ player.state.current_entry_id = current;
291
+ player.state.position = position;
292
+ await this.play(player, current, command);
293
+ return this.get(player.id);
294
+ }
295
+ if (!unchanged)
296
+ await this.stop(player);
297
+ player.state.queue = queue;
298
+ player.state.current_entry_id = current;
299
+ player.state.position = current === null ? 0 : position;
300
+ player.state.checkpoint = current !== null && !this.runtimes.has(player.id);
301
+ if (player.state.status !== "error")
302
+ player.state.error = null;
303
+ return this.save(player);
304
+ }
305
+ async play(player, entryId, policy, resumeCheckpoint = true) {
306
+ const entry = player.state.queue.find((entry) => entry.id === entryId);
307
+ if (!entry)
308
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Queue is empty or the entry does not exist", 404);
309
+ const output = player.state.desired_output;
310
+ if (!output)
311
+ throw new ServerPlayerError("OUTPUT_REQUIRED", "Select a desired output before playing", 400);
312
+ const owner = this.list().find((p) => p.assigned_output === output && p.id !== player.id);
313
+ if (owner)
314
+ throw new ServerPlayerError("OUTPUT_ASSIGNED", "Speaker belongs to another player; use explicit transfer");
315
+ const needsReconnect = (player.state.status === "paused" || player.state.status === "error") && await this.runtimes.get(player.id)?.backend.outputConnection?.() !== "connected";
316
+ if (player.assigned_output !== output || needsReconnect)
317
+ await this.requireAvailable(player, output, policy);
318
+ const track = await this.store.resolve(entry);
319
+ const engine = this.engine(player);
320
+ const source = track ? audioSource(track, { apiBase: "http://unused/api", audioLibraryRoot: engine.libraryRoot }) : null;
321
+ if (!source)
322
+ throw new ServerPlayerError("NO_AUDIO", "Current track has no indexed audio source", 422);
323
+ const position = resumeCheckpoint && player.state.current_entry_id === entry.id ? player.state.position : 0;
324
+ await this.detach(player);
325
+ player.assigned_output = output;
326
+ player.state.current_entry_id = entry.id;
327
+ player.state.position = position;
328
+ player.state.duration = null;
329
+ player.state.status = "loading";
330
+ player.state.checkpoint = false;
331
+ player.state.error = null;
332
+ // Persist the selected entry before engine effects. A crash never replays a
333
+ // completed entry or automatically starts this pending load on restoration.
334
+ player = await this.save(player);
335
+ this.available();
336
+ const backend = engine.create(output);
337
+ const runtime = { backend, generation: ++this.generation };
338
+ this.runtimes.set(player.id, runtime);
339
+ backend.on("position", (position, duration) => this.enqueueEvent(player.id, runtime, async (current) => {
340
+ if (!Number.isFinite(position) || position < 0)
341
+ return;
342
+ current.state.position = position;
343
+ current.state.duration = duration !== null && Number.isFinite(duration) && duration >= 0 ? duration : null;
344
+ current.state.checkpoint = false;
345
+ const entryId = current.state.current_entry_id;
346
+ if (this.playLogging && entryId && track?.friend_id === this.playLogging.ownerFriendId && track.release_id && !this.queuedPlays.has(entryId)) {
347
+ const listening = this.progress.get(entryId) ?? { listened: initialProgress, startedAt: this.playLogging.now?.() ?? new Date() };
348
+ listening.listened = advanceProgress(listening.listened, position, current.state.status === "playing");
349
+ this.progress.set(entryId, listening);
350
+ if (isPlay(listening.listened.listened, current.state.duration)) {
351
+ const play = { entryId, playerId: current.id, trackId: entry.track_id, friendId: entry.friend_id, releaseId: track.release_id, startedAt: listening.startedAt };
352
+ try {
353
+ await this.store.queuePlay(play);
354
+ this.queuedPlays.add(entryId);
355
+ void this.retryPlays();
356
+ }
357
+ catch (error) {
358
+ this.emit("play-log-error", error);
359
+ }
360
+ }
361
+ }
362
+ this.players.set(current.id, current);
363
+ this.emit("position", { player_id: current.id, revision: current.revision, current_entry_id: current.state.current_entry_id, position: current.state.position, duration: current.state.duration, observed_at: new Date().toISOString() });
364
+ if (Date.now() - (this.checkpointAt.get(current.id) ?? 0) >= 5000) {
365
+ await this.store.checkpoint(current);
366
+ this.checkpointAt.set(current.id, Date.now());
367
+ }
368
+ }));
369
+ backend.on("ended", () => this.enqueueEvent(player.id, runtime, async (current) => {
370
+ const index = current.state.queue.findIndex((entry) => entry.id === current.state.current_entry_id);
371
+ const next = current.state.queue[index + 1];
372
+ if (next) {
373
+ current.state.current_entry_id = next.id;
374
+ current.state.position = 0;
375
+ current.state.duration = null;
376
+ current.state.status = "loading";
377
+ const advanced = await this.save(current);
378
+ await this.play(advanced, next.id, { allow_unknown: true, takeover: false }, false);
379
+ }
380
+ else {
381
+ await this.stop(current);
382
+ current.state.status = "ended";
383
+ await this.save(current);
384
+ }
385
+ }));
386
+ backend.on("error", (error) => this.enqueueEvent(player.id, runtime, async (current) => {
387
+ current.state.status = "error";
388
+ current.state.error = errorValue(error);
389
+ try {
390
+ await this.detach(current);
391
+ }
392
+ catch { /* retain the uncertain claim */ }
393
+ await this.save(current);
394
+ }));
395
+ try {
396
+ await backend.load(source);
397
+ if (position > 0)
398
+ await backend.seek(position);
399
+ await backend.setVolume(player.state.volume);
400
+ player.state.status = "playing";
401
+ await this.save(player);
402
+ }
403
+ catch (error) {
404
+ player = this.get(player.id);
405
+ player.state.status = "error";
406
+ player.state.error = errorValue(error);
407
+ try {
408
+ await this.detach(player);
409
+ }
410
+ catch { /* don't transfer an uncertain claim */ }
411
+ await this.save(player);
412
+ throw error;
413
+ }
414
+ }
415
+ enqueueEvent(id, runtime, action) {
416
+ void this.serial(async () => {
417
+ if (this.stopping || this.runtimes.get(id)?.generation !== runtime.generation)
418
+ return;
419
+ try {
420
+ await action(this.get(id));
421
+ }
422
+ catch (error) {
423
+ const current = this.get(id);
424
+ current.state.status = "error";
425
+ current.state.error = errorValue(error);
426
+ try {
427
+ await this.detach(current);
428
+ }
429
+ catch { /* preserve uncertain claim */ }
430
+ await this.save(current);
431
+ }
432
+ }).catch((error) => { this.emit("fault", error); });
433
+ }
434
+ async detach(player) {
435
+ const runtime = this.runtimes.get(player.id);
436
+ if (runtime) {
437
+ // Invalidate callbacks before awaiting close, including duplicate EOFs.
438
+ this.runtimes.delete(player.id);
439
+ await runtime.backend.close();
440
+ }
441
+ else if (player.assigned_output !== null) {
442
+ throw new ServerPlayerError("RELEASE_UNCERTAIN", "Previous engine release is uncertain; stop that engine and restart the worker before reassigning", 503);
443
+ }
444
+ player.assigned_output = null;
445
+ }
446
+ async stop(player, preserveCurrent = false) {
447
+ await this.detach(player);
448
+ player.state.status = preserveCurrent && player.state.current_entry_id ? "paused" : "stopped";
449
+ player.state.checkpoint = preserveCurrent && player.state.current_entry_id !== null;
450
+ if (!preserveCurrent) {
451
+ player.state.current_entry_id = null;
452
+ player.state.position = 0;
453
+ player.state.duration = null;
454
+ }
455
+ }
456
+ async transfer(target, command) {
457
+ if (target.id === command.from_player_id)
458
+ throw new ServerPlayerError("INVALID_TRANSFER", "Transfer requires two different players", 400);
459
+ let source = this.get(command.from_player_id);
460
+ this.revision(source, command.from_revision);
461
+ if (source.assigned_output !== command.output_id)
462
+ throw new ServerPlayerError("OUTPUT_NOT_ASSIGNED", "Source player does not own this speaker");
463
+ let detached = false;
464
+ try {
465
+ await this.stop(source, true);
466
+ source = await this.save(source);
467
+ detached = true;
468
+ if (this.runtimes.has(target.id)) {
469
+ await this.stop(target, true);
470
+ target = await this.save(target);
471
+ }
472
+ target.state.desired_output = command.output_id;
473
+ target = await this.save(target);
474
+ if (command.play)
475
+ await this.play(target, target.state.current_entry_id ?? target.state.queue[0]?.id, command);
476
+ return { player: this.get(target.id), transfer: { from_player: this.get(source.id), detached, attached: command.play, error: null } };
477
+ }
478
+ catch (error) {
479
+ if (!detached) {
480
+ source.state.status = "error";
481
+ source.state.error = errorValue(error);
482
+ try {
483
+ await this.save(source);
484
+ }
485
+ catch { /* keep the transfer result truthful */ }
486
+ }
487
+ // The source may already be detached. Report each phase; do not reconnect
488
+ // it to pretend the operation was atomic or compete with an external app.
489
+ return { player: this.get(target.id), transfer: { from_player: this.get(source.id), detached, attached: false, error: errorValue(error) } };
490
+ }
491
+ }
492
+ async shutdown() {
493
+ this.stopping = true;
494
+ await this.serial(async () => {
495
+ for (const player of this.list()) {
496
+ try {
497
+ await this.stop(player, true);
498
+ await this.save(player);
499
+ }
500
+ catch (error) {
501
+ this.emit("fault", error);
502
+ }
503
+ }
504
+ });
505
+ }
506
+ async requireAvailable(player, output, policy) {
507
+ // Assignment is a Groovenet claim, independent of HA's observation.
508
+ if (this.list().some(other => other.id !== player.id && other.assigned_output === output))
509
+ throw new ServerPlayerError("OUTPUT_ASSIGNED", "Speaker belongs to another player; use explicit transfer");
510
+ const observed = await this.observe(output, { fresh: true, resolveOutputName: async () => {
511
+ const runtime = this.runtimes.get(player.id);
512
+ const backend = runtime?.backend ?? this.engine(player).create();
513
+ try {
514
+ const devices = await backend.listDevices();
515
+ const name = devices.find(device => device.id === output)?.name;
516
+ return name && devices.filter(device => device.name === name).length === 1 ? name : undefined;
517
+ }
518
+ finally {
519
+ if (!runtime)
520
+ await backend.close();
521
+ }
522
+ } });
523
+ const ownSender = observed.sender_identity === "groovenet" && observed.sender_engine_id === player.engine_id;
524
+ if (observed.availability === "occupied" && !ownSender && !policy.takeover && player.availability_policy !== "always")
525
+ throw new ServerPlayerError("SPEAKER_OCCUPIED", "Observed speaker activity requires explicit takeover");
526
+ if (observed.availability === "unknown" && !policy.allow_unknown && player.availability_policy === "ask")
527
+ throw new ServerPlayerError("AVAILABILITY_UNKNOWN", "Speaker availability is unknown; explicitly acknowledge it before connecting");
528
+ }
529
+ engine(player) {
530
+ const engine = this.engines[player.engine_id];
531
+ if (!engine)
532
+ throw new ServerPlayerError("ENGINE_NOT_CONFIGURED", "Player engine is not configured", 503);
533
+ return engine;
534
+ }
535
+ active(id) {
536
+ const runtime = this.runtimes.get(id);
537
+ if (!runtime)
538
+ throw new ServerPlayerError("PLAYER_INACTIVE", "Player has no active engine session; explicitly play to start one");
539
+ return runtime;
540
+ }
541
+ revision(player, expected) {
542
+ if (player.revision !== expected)
543
+ throw new ServerPlayerError("REVISION_CONFLICT", "Player changed; refresh its state before retrying");
544
+ }
545
+ available() { if (this.stopping)
546
+ throw new ServerPlayerError("WORKER_STOPPING", "Player worker is stopping", 503); }
547
+ async save(player) {
548
+ const saved = await this.store.save(player, player.revision);
549
+ this.players.set(player.id, saved);
550
+ this.publish(saved);
551
+ return clone(saved);
552
+ }
553
+ publish(player) { this.emit("snapshot", clone(player)); }
554
+ }
555
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/server/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { type SpeakerObserver } from "./manager.js";
2
+ /** Exact attribute matches must identify one dedicated engine, never a shared host. */
3
+ export declare function homeAssistantObserver(options: {
4
+ url?: string;
5
+ token?: string;
6
+ entities?: Record<string, string>;
7
+ senders?: Record<string, Record<string, string>>;
8
+ fetch?: typeof fetch;
9
+ }): SpeakerObserver;
10
+ //# sourceMappingURL=observer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../src/server/observer.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpE,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CAAE,GAAG,eAAe,CAqC3M"}