homebridge-sonos-scenes 0.1.4 → 0.1.6
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/README.md +7 -1
- package/dist/src/accessories/sceneSpeaker.d.ts +18 -0
- package/dist/src/accessories/sceneSpeaker.js +83 -0
- package/dist/src/accessories/sceneSpeaker.js.map +1 -0
- package/dist/src/platform.d.ts +11 -1
- package/dist/src/platform.js +94 -22
- package/dist/src/platform.js.map +1 -1
- package/dist/src/transports/localTransport.d.ts +9 -0
- package/dist/src/transports/localTransport.js +97 -0
- package/dist/src/transports/localTransport.js.map +1 -1
- package/dist/src/types.d.ts +6 -0
- package/docs/assets/homebridge-sonos-scenes-icon-256x256.png +0 -0
- package/docs/assets/homebridge-sonos-scenes-icon-512x512.png +0 -0
- package/homebridge-ui/public/index.html +302 -80
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/homebridge-sonos-scenes-icon-512x512.png" alt="homebridge-sonos-scenes icon" width="164">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">homebridge-sonos-scenes</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">Homebridge plugin for Sonos workflow scenes and orchestration.</p>
|
|
2
8
|
|
|
3
9
|
`homebridge-sonos-scenes` is a Homebridge plugin scaffold for Sonos workflow scenes.
|
|
4
10
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { PlatformAccessory } from "homebridge";
|
|
2
|
+
import type { SceneDefinition } from "../types";
|
|
3
|
+
import type { SonosScenesPlatform } from "../platform";
|
|
4
|
+
export declare class SceneSpeakerAccessory {
|
|
5
|
+
private readonly platform;
|
|
6
|
+
private readonly accessory;
|
|
7
|
+
private service;
|
|
8
|
+
private scene;
|
|
9
|
+
private lastKnownVolume;
|
|
10
|
+
private lastKnownMuted;
|
|
11
|
+
constructor(platform: SonosScenesPlatform, accessory: PlatformAccessory, scene: SceneDefinition);
|
|
12
|
+
updateScene(scene: SceneDefinition): void;
|
|
13
|
+
private displayNameFor;
|
|
14
|
+
private handleVolumeGet;
|
|
15
|
+
private handleVolumeSet;
|
|
16
|
+
private handleMuteGet;
|
|
17
|
+
private handleMuteSet;
|
|
18
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SceneSpeakerAccessory = void 0;
|
|
4
|
+
class SceneSpeakerAccessory {
|
|
5
|
+
platform;
|
|
6
|
+
accessory;
|
|
7
|
+
service;
|
|
8
|
+
scene;
|
|
9
|
+
lastKnownVolume;
|
|
10
|
+
lastKnownMuted = false;
|
|
11
|
+
constructor(platform, accessory, scene) {
|
|
12
|
+
this.platform = platform;
|
|
13
|
+
this.accessory = accessory;
|
|
14
|
+
this.scene = scene;
|
|
15
|
+
this.lastKnownVolume = scene.coordinatorVolume ?? 0;
|
|
16
|
+
this.accessory.context.sceneId = scene.id;
|
|
17
|
+
this.accessory.context.kind = "speaker";
|
|
18
|
+
this.accessory.displayName = this.displayNameFor(scene);
|
|
19
|
+
this.accessory.category = 26 /* this.platform.api.hap.Categories.SPEAKER */;
|
|
20
|
+
this.service =
|
|
21
|
+
this.accessory.getService(this.platform.Service.Speaker)
|
|
22
|
+
?? this.accessory.addService(this.platform.Service.Speaker);
|
|
23
|
+
if (!this.service.testCharacteristic(this.platform.Characteristic.Volume)) {
|
|
24
|
+
this.service.addCharacteristic(this.platform.Characteristic.Volume);
|
|
25
|
+
}
|
|
26
|
+
this.service.setCharacteristic(this.platform.Characteristic.Name, this.displayNameFor(scene));
|
|
27
|
+
this.service.getCharacteristic(this.platform.Characteristic.Mute)
|
|
28
|
+
.onGet(this.handleMuteGet.bind(this))
|
|
29
|
+
.onSet(this.handleMuteSet.bind(this));
|
|
30
|
+
this.service.getCharacteristic(this.platform.Characteristic.Volume)
|
|
31
|
+
.onGet(this.handleVolumeGet.bind(this))
|
|
32
|
+
.onSet(this.handleVolumeSet.bind(this));
|
|
33
|
+
const accessoryInformation = this.accessory.getService(this.platform.Service.AccessoryInformation)
|
|
34
|
+
?? this.accessory.addService(this.platform.Service.AccessoryInformation);
|
|
35
|
+
accessoryInformation
|
|
36
|
+
.setCharacteristic(this.platform.Characteristic.Manufacturer, "homebridge-sonos-scenes")
|
|
37
|
+
.setCharacteristic(this.platform.Characteristic.Model, "Sonos Scene Speaker")
|
|
38
|
+
.setCharacteristic(this.platform.Characteristic.SerialNumber, `${scene.id}:speaker`);
|
|
39
|
+
}
|
|
40
|
+
updateScene(scene) {
|
|
41
|
+
this.scene = scene;
|
|
42
|
+
this.lastKnownVolume = scene.coordinatorVolume ?? this.lastKnownVolume;
|
|
43
|
+
this.accessory.context.sceneId = scene.id;
|
|
44
|
+
this.accessory.context.kind = "speaker";
|
|
45
|
+
this.accessory.displayName = this.displayNameFor(scene);
|
|
46
|
+
this.service.setCharacteristic(this.platform.Characteristic.Name, this.displayNameFor(scene));
|
|
47
|
+
}
|
|
48
|
+
displayNameFor(scene) {
|
|
49
|
+
return `${scene.name} Volume`;
|
|
50
|
+
}
|
|
51
|
+
async handleVolumeGet() {
|
|
52
|
+
try {
|
|
53
|
+
this.lastKnownVolume = await this.platform.getSceneVolume(this.scene.id);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
void 0;
|
|
57
|
+
}
|
|
58
|
+
return this.lastKnownVolume;
|
|
59
|
+
}
|
|
60
|
+
async handleVolumeSet(value) {
|
|
61
|
+
const nextVolume = Math.max(0, Math.min(100, Math.round(Number(value))));
|
|
62
|
+
await this.platform.setSceneVolume(this.scene.id, nextVolume);
|
|
63
|
+
this.lastKnownVolume = nextVolume;
|
|
64
|
+
this.service.updateCharacteristic(this.platform.Characteristic.Volume, nextVolume);
|
|
65
|
+
}
|
|
66
|
+
async handleMuteGet() {
|
|
67
|
+
try {
|
|
68
|
+
this.lastKnownMuted = await this.platform.getSceneMuted(this.scene.id);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
void 0;
|
|
72
|
+
}
|
|
73
|
+
return this.lastKnownMuted;
|
|
74
|
+
}
|
|
75
|
+
async handleMuteSet(value) {
|
|
76
|
+
const nextMuted = value === true;
|
|
77
|
+
await this.platform.setSceneMuted(this.scene.id, nextMuted);
|
|
78
|
+
this.lastKnownMuted = nextMuted;
|
|
79
|
+
this.service.updateCharacteristic(this.platform.Characteristic.Mute, nextMuted);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.SceneSpeakerAccessory = SceneSpeakerAccessory;
|
|
83
|
+
//# sourceMappingURL=sceneSpeaker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneSpeaker.js","sourceRoot":"","sources":["../../../src/accessories/sceneSpeaker.ts"],"names":[],"mappings":"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"}
|
package/dist/src/platform.d.ts
CHANGED
|
@@ -14,10 +14,20 @@ export declare class SonosScenesPlatform implements DynamicPlatformPlugin {
|
|
|
14
14
|
private readonly sceneRunner;
|
|
15
15
|
private readonly transport;
|
|
16
16
|
private readonly cachedAccessories;
|
|
17
|
-
private readonly
|
|
17
|
+
private readonly switchAccessories;
|
|
18
|
+
private readonly speakerAccessories;
|
|
18
19
|
constructor(log: Logger, rawConfig: PlatformConfig, api: API);
|
|
19
20
|
configureAccessory(accessory: PlatformAccessory): void;
|
|
20
21
|
runScene(sceneId: string, trigger: SceneTrigger): Promise<SceneRunResult>;
|
|
21
22
|
getScene(sceneId: string): SceneDefinition | undefined;
|
|
23
|
+
getSceneVolume(sceneId: string): Promise<number>;
|
|
24
|
+
setSceneVolume(sceneId: string, volume: number): Promise<void>;
|
|
25
|
+
getSceneMuted(sceneId: string): Promise<boolean>;
|
|
26
|
+
setSceneMuted(sceneId: string, muted: boolean): Promise<void>;
|
|
22
27
|
private syncAccessories;
|
|
28
|
+
private syncSwitchAccessory;
|
|
29
|
+
private syncSpeakerAccessory;
|
|
30
|
+
private pruneWrapperMaps;
|
|
31
|
+
private getRequiredScene;
|
|
32
|
+
private usesGroupAudio;
|
|
23
33
|
}
|
package/dist/src/platform.js
CHANGED
|
@@ -5,6 +5,7 @@ const config_1 = require("./config");
|
|
|
5
5
|
const discoveryService_1 = require("./discoveryService");
|
|
6
6
|
const logger_1 = require("./logger");
|
|
7
7
|
const sceneRunner_1 = require("./sceneRunner");
|
|
8
|
+
const sceneSpeaker_1 = require("./accessories/sceneSpeaker");
|
|
8
9
|
const sceneSwitch_1 = require("./accessories/sceneSwitch");
|
|
9
10
|
const transports_1 = require("./transports");
|
|
10
11
|
const types_1 = require("./types");
|
|
@@ -22,7 +23,8 @@ class SonosScenesPlatform {
|
|
|
22
23
|
sceneRunner;
|
|
23
24
|
transport;
|
|
24
25
|
cachedAccessories = new Map();
|
|
25
|
-
|
|
26
|
+
switchAccessories = new Map();
|
|
27
|
+
speakerAccessories = new Map();
|
|
26
28
|
constructor(log, rawConfig, api) {
|
|
27
29
|
this.log = log;
|
|
28
30
|
this.rawConfig = rawConfig;
|
|
@@ -63,25 +65,47 @@ class SonosScenesPlatform {
|
|
|
63
65
|
getScene(sceneId) {
|
|
64
66
|
return this.config.scenes.find((scene) => scene.id === sceneId);
|
|
65
67
|
}
|
|
68
|
+
async getSceneVolume(sceneId) {
|
|
69
|
+
const scene = this.getRequiredScene(sceneId);
|
|
70
|
+
if (this.usesGroupAudio(scene)) {
|
|
71
|
+
return this.transport.getGroupVolume(scene.householdId, scene.coordinatorPlayerId);
|
|
72
|
+
}
|
|
73
|
+
return this.transport.getPlayerVolume(scene.householdId, scene.coordinatorPlayerId);
|
|
74
|
+
}
|
|
75
|
+
async setSceneVolume(sceneId, volume) {
|
|
76
|
+
const scene = this.getRequiredScene(sceneId);
|
|
77
|
+
if (this.usesGroupAudio(scene)) {
|
|
78
|
+
await this.transport.setGroupVolume(scene.householdId, scene.coordinatorPlayerId, volume);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
await this.transport.setPlayerVolume(scene.householdId, scene.coordinatorPlayerId, volume);
|
|
82
|
+
}
|
|
83
|
+
async getSceneMuted(sceneId) {
|
|
84
|
+
const scene = this.getRequiredScene(sceneId);
|
|
85
|
+
if (this.usesGroupAudio(scene)) {
|
|
86
|
+
return this.transport.getGroupMuted(scene.householdId, scene.coordinatorPlayerId);
|
|
87
|
+
}
|
|
88
|
+
return this.transport.getPlayerMuted(scene.householdId, scene.coordinatorPlayerId);
|
|
89
|
+
}
|
|
90
|
+
async setSceneMuted(sceneId, muted) {
|
|
91
|
+
const scene = this.getRequiredScene(sceneId);
|
|
92
|
+
if (this.usesGroupAudio(scene)) {
|
|
93
|
+
await this.transport.setGroupMuted(scene.householdId, scene.coordinatorPlayerId, muted);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
await this.transport.setPlayerMuted(scene.householdId, scene.coordinatorPlayerId, muted);
|
|
97
|
+
}
|
|
66
98
|
async syncAccessories() {
|
|
67
99
|
this.logger.info(`Syncing ${this.config.scenes.length} configured Sonos scene accessory(s).`);
|
|
68
100
|
const activeAccessoryIds = new Set();
|
|
69
101
|
for (const scene of this.config.scenes) {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.sceneAccessories.set(scene.id, wrapper);
|
|
78
|
-
this.api.registerPlatformAccessories(types_1.PLUGIN_NAME, types_1.PLATFORM_NAME, [accessory]);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const wrapper = this.sceneAccessories.get(scene.id) ?? new sceneSwitch_1.SceneSwitchAccessory(this, accessory, scene);
|
|
82
|
-
wrapper.updateScene(scene);
|
|
83
|
-
this.sceneAccessories.set(scene.id, wrapper);
|
|
84
|
-
this.api.updatePlatformAccessories([accessory]);
|
|
102
|
+
const switchUuid = this.api.hap.uuid.generate(`${types_1.PLUGIN_NAME}:${scene.id}:switch`);
|
|
103
|
+
const speakerUuid = this.api.hap.uuid.generate(`${types_1.PLUGIN_NAME}:${scene.id}:speaker`);
|
|
104
|
+
activeAccessoryIds.add(switchUuid);
|
|
105
|
+
activeAccessoryIds.add(speakerUuid);
|
|
106
|
+
const switchAccessory = this.syncSwitchAccessory(scene, switchUuid);
|
|
107
|
+
const speakerAccessory = this.syncSpeakerAccessory(scene, speakerUuid);
|
|
108
|
+
this.api.updatePlatformAccessories([switchAccessory, speakerAccessory]);
|
|
85
109
|
}
|
|
86
110
|
const staleAccessories = Array.from(this.cachedAccessories.entries())
|
|
87
111
|
.filter(([uuid]) => !activeAccessoryIds.has(uuid))
|
|
@@ -91,12 +115,7 @@ class SonosScenesPlatform {
|
|
|
91
115
|
for (const accessory of staleAccessories) {
|
|
92
116
|
this.cachedAccessories.delete(accessory.UUID);
|
|
93
117
|
}
|
|
94
|
-
|
|
95
|
-
if (!this.config.scenes.some((scene) => scene.id === sceneId)) {
|
|
96
|
-
void wrapper;
|
|
97
|
-
this.sceneAccessories.delete(sceneId);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
118
|
+
this.pruneWrapperMaps();
|
|
100
119
|
}
|
|
101
120
|
try {
|
|
102
121
|
const snapshot = await this.discoveryService.refresh();
|
|
@@ -106,6 +125,59 @@ class SonosScenesPlatform {
|
|
|
106
125
|
this.logger.warn(`Initial discovery failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
107
126
|
}
|
|
108
127
|
}
|
|
128
|
+
syncSwitchAccessory(scene, uuid) {
|
|
129
|
+
let accessory = this.cachedAccessories.get(uuid);
|
|
130
|
+
if (!accessory) {
|
|
131
|
+
accessory = new this.api.platformAccessory(scene.name, uuid);
|
|
132
|
+
this.cachedAccessories.set(uuid, accessory);
|
|
133
|
+
const wrapper = new sceneSwitch_1.SceneSwitchAccessory(this, accessory, scene);
|
|
134
|
+
this.switchAccessories.set(scene.id, wrapper);
|
|
135
|
+
this.api.registerPlatformAccessories(types_1.PLUGIN_NAME, types_1.PLATFORM_NAME, [accessory]);
|
|
136
|
+
return accessory;
|
|
137
|
+
}
|
|
138
|
+
const wrapper = this.switchAccessories.get(scene.id) ?? new sceneSwitch_1.SceneSwitchAccessory(this, accessory, scene);
|
|
139
|
+
wrapper.updateScene(scene);
|
|
140
|
+
this.switchAccessories.set(scene.id, wrapper);
|
|
141
|
+
return accessory;
|
|
142
|
+
}
|
|
143
|
+
syncSpeakerAccessory(scene, uuid) {
|
|
144
|
+
let accessory = this.cachedAccessories.get(uuid);
|
|
145
|
+
if (!accessory) {
|
|
146
|
+
accessory = new this.api.platformAccessory(`${scene.name} Volume`, uuid);
|
|
147
|
+
this.cachedAccessories.set(uuid, accessory);
|
|
148
|
+
const wrapper = new sceneSpeaker_1.SceneSpeakerAccessory(this, accessory, scene);
|
|
149
|
+
this.speakerAccessories.set(scene.id, wrapper);
|
|
150
|
+
this.api.registerPlatformAccessories(types_1.PLUGIN_NAME, types_1.PLATFORM_NAME, [accessory]);
|
|
151
|
+
return accessory;
|
|
152
|
+
}
|
|
153
|
+
const wrapper = this.speakerAccessories.get(scene.id) ?? new sceneSpeaker_1.SceneSpeakerAccessory(this, accessory, scene);
|
|
154
|
+
wrapper.updateScene(scene);
|
|
155
|
+
this.speakerAccessories.set(scene.id, wrapper);
|
|
156
|
+
return accessory;
|
|
157
|
+
}
|
|
158
|
+
pruneWrapperMaps() {
|
|
159
|
+
const activeSceneIds = new Set(this.config.scenes.map((scene) => scene.id));
|
|
160
|
+
for (const sceneId of this.switchAccessories.keys()) {
|
|
161
|
+
if (!activeSceneIds.has(sceneId)) {
|
|
162
|
+
this.switchAccessories.delete(sceneId);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
for (const sceneId of this.speakerAccessories.keys()) {
|
|
166
|
+
if (!activeSceneIds.has(sceneId)) {
|
|
167
|
+
this.speakerAccessories.delete(sceneId);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
getRequiredScene(sceneId) {
|
|
172
|
+
const scene = this.getScene(sceneId);
|
|
173
|
+
if (!scene) {
|
|
174
|
+
throw new Error(`Scene "${sceneId}" is not configured.`);
|
|
175
|
+
}
|
|
176
|
+
return scene;
|
|
177
|
+
}
|
|
178
|
+
usesGroupAudio(scene) {
|
|
179
|
+
return scene.memberPlayerIds.length > 0;
|
|
180
|
+
}
|
|
109
181
|
}
|
|
110
182
|
exports.SonosScenesPlatform = SonosScenesPlatform;
|
|
111
183
|
//# sourceMappingURL=platform.js.map
|
package/dist/src/platform.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/platform.ts"],"names":[],"mappings":";;;AACA,qCAAmD;AACnD,yDAAsD;AACtD,qCAA4C;AAC5C,+CAA4C;AAC5C,2DAAiE;AACjE,6CAA+C;AAE/C,mCAAqD;AAE5C,8FAFA,qBAAa,OAEA;AAAE,4FAFA,mBAAW,OAEA;AAEnC,MAAa,mBAAmB;
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ export declare class LocalSonosTransport implements SonosTransport {
|
|
|
6
6
|
readonly kind = "local";
|
|
7
7
|
private livePlayers;
|
|
8
8
|
private fixtureState;
|
|
9
|
+
private fixturePlayerAudio;
|
|
9
10
|
private fixtureLoaded;
|
|
10
11
|
private householdRoots;
|
|
11
12
|
private lastSnapshot;
|
|
@@ -22,7 +23,13 @@ export declare class LocalSonosTransport implements SonosTransport {
|
|
|
22
23
|
loadFavorite(householdId: string, coordinatorPlayerId: string, favoriteId: string): Promise<void>;
|
|
23
24
|
loadTv(householdId: string, coordinatorPlayerId: string, deviceId: string, playOnCompletion?: boolean): Promise<void>;
|
|
24
25
|
setGroupVolume(householdId: string, coordinatorPlayerId: string, volume: number): Promise<void>;
|
|
26
|
+
getGroupVolume(householdId: string, coordinatorPlayerId: string): Promise<number>;
|
|
27
|
+
getPlayerVolume(householdId: string, playerId: string): Promise<number>;
|
|
25
28
|
setPlayerVolume(householdId: string, playerId: string, volume: number): Promise<void>;
|
|
29
|
+
getGroupMuted(householdId: string, coordinatorPlayerId: string): Promise<boolean>;
|
|
30
|
+
setGroupMuted(householdId: string, coordinatorPlayerId: string, muted: boolean): Promise<void>;
|
|
31
|
+
getPlayerMuted(householdId: string, playerId: string): Promise<boolean>;
|
|
32
|
+
setPlayerMuted(householdId: string, playerId: string, muted: boolean): Promise<void>;
|
|
26
33
|
ungroup(householdId: string, coordinatorPlayerId: string, memberPlayerIds?: string[]): Promise<void>;
|
|
27
34
|
private tryLiveDiscovery;
|
|
28
35
|
private loadFixtureSnapshot;
|
|
@@ -33,4 +40,6 @@ export declare class LocalSonosTransport implements SonosTransport {
|
|
|
33
40
|
private fetchFavorites;
|
|
34
41
|
private setFixtureGroupMembers;
|
|
35
42
|
private touchFixture;
|
|
43
|
+
private fixtureAudioState;
|
|
44
|
+
private audioDevice;
|
|
36
45
|
}
|
|
@@ -141,6 +141,15 @@ function normalizeFixtureSnapshot(input) {
|
|
|
141
141
|
origin: "fixture",
|
|
142
142
|
};
|
|
143
143
|
}
|
|
144
|
+
function buildFixtureAudioState(snapshot) {
|
|
145
|
+
return new Map(snapshot.households.flatMap((household) => household.players.map((player) => [
|
|
146
|
+
player.id,
|
|
147
|
+
{
|
|
148
|
+
volume: 0,
|
|
149
|
+
muted: false,
|
|
150
|
+
},
|
|
151
|
+
])));
|
|
152
|
+
}
|
|
144
153
|
function unique(values) {
|
|
145
154
|
return Array.from(new Set(values));
|
|
146
155
|
}
|
|
@@ -208,6 +217,7 @@ class LocalSonosTransport {
|
|
|
208
217
|
kind = "local";
|
|
209
218
|
livePlayers = new Map();
|
|
210
219
|
fixtureState = normalizeFixtureSnapshot(sampleTopology_1.sampleTopology);
|
|
220
|
+
fixturePlayerAudio = buildFixtureAudioState(this.fixtureState);
|
|
211
221
|
fixtureLoaded = false;
|
|
212
222
|
householdRoots = new Map();
|
|
213
223
|
lastSnapshot = normalizeFixtureSnapshot(sampleTopology_1.sampleTopology);
|
|
@@ -355,8 +365,33 @@ class LocalSonosTransport {
|
|
|
355
365
|
await this.setPlayerVolume(householdId, playerId, volume);
|
|
356
366
|
}
|
|
357
367
|
}
|
|
368
|
+
async getGroupVolume(householdId, coordinatorPlayerId) {
|
|
369
|
+
const snapshot = await this.discoverTopology();
|
|
370
|
+
const household = this.requireHousehold(snapshot, householdId);
|
|
371
|
+
const group = household.groups.find((item) => item.coordinatorId === coordinatorPlayerId)
|
|
372
|
+
?? household.groups.find((item) => item.playerIds.includes(coordinatorPlayerId));
|
|
373
|
+
if (!group) {
|
|
374
|
+
return this.getPlayerVolume(householdId, coordinatorPlayerId);
|
|
375
|
+
}
|
|
376
|
+
const volumes = await Promise.all(group.playerIds.map((playerId) => this.getPlayerVolume(householdId, playerId)));
|
|
377
|
+
if (volumes.length === 0) {
|
|
378
|
+
return 0;
|
|
379
|
+
}
|
|
380
|
+
return Math.max(0, Math.min(100, Math.round(volumes.reduce((sum, value) => sum + value, 0) / volumes.length)));
|
|
381
|
+
}
|
|
382
|
+
async getPlayerVolume(householdId, playerId) {
|
|
383
|
+
if (this.livePlayers.size === 0) {
|
|
384
|
+
this.requireHousehold(await this.loadFixtureSnapshot(), householdId);
|
|
385
|
+
return this.fixtureAudioState(playerId).volume;
|
|
386
|
+
}
|
|
387
|
+
this.requireHousehold(await this.discoverTopology(), householdId);
|
|
388
|
+
const player = this.requireLiveRecord(playerId);
|
|
389
|
+
return Math.max(0, Math.min(100, Math.round(await this.audioDevice(player.device).getVolume())));
|
|
390
|
+
}
|
|
358
391
|
async setPlayerVolume(householdId, playerId, volume) {
|
|
359
392
|
if (this.livePlayers.size === 0) {
|
|
393
|
+
this.requireHousehold(await this.loadFixtureSnapshot(), householdId);
|
|
394
|
+
this.fixtureAudioState(playerId).volume = Math.max(0, Math.min(100, Math.round(volume)));
|
|
360
395
|
this.touchFixture(householdId);
|
|
361
396
|
return;
|
|
362
397
|
}
|
|
@@ -364,6 +399,50 @@ class LocalSonosTransport {
|
|
|
364
399
|
const player = this.requireLiveRecord(playerId);
|
|
365
400
|
await player.device.setVolume(Math.max(0, Math.min(100, Math.round(volume))));
|
|
366
401
|
}
|
|
402
|
+
async getGroupMuted(householdId, coordinatorPlayerId) {
|
|
403
|
+
const snapshot = await this.discoverTopology();
|
|
404
|
+
const household = this.requireHousehold(snapshot, householdId);
|
|
405
|
+
const group = household.groups.find((item) => item.coordinatorId === coordinatorPlayerId)
|
|
406
|
+
?? household.groups.find((item) => item.playerIds.includes(coordinatorPlayerId));
|
|
407
|
+
if (!group) {
|
|
408
|
+
return this.getPlayerMuted(householdId, coordinatorPlayerId);
|
|
409
|
+
}
|
|
410
|
+
const states = await Promise.all(group.playerIds.map((playerId) => this.getPlayerMuted(householdId, playerId)));
|
|
411
|
+
return states.length > 0 && states.every(Boolean);
|
|
412
|
+
}
|
|
413
|
+
async setGroupMuted(householdId, coordinatorPlayerId, muted) {
|
|
414
|
+
const snapshot = await this.discoverTopology();
|
|
415
|
+
const household = this.requireHousehold(snapshot, householdId);
|
|
416
|
+
const group = household.groups.find((item) => item.coordinatorId === coordinatorPlayerId)
|
|
417
|
+
?? household.groups.find((item) => item.playerIds.includes(coordinatorPlayerId));
|
|
418
|
+
if (!group) {
|
|
419
|
+
await this.setPlayerMuted(householdId, coordinatorPlayerId, muted);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
for (const playerId of group.playerIds) {
|
|
423
|
+
await this.setPlayerMuted(householdId, playerId, muted);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
async getPlayerMuted(householdId, playerId) {
|
|
427
|
+
if (this.livePlayers.size === 0) {
|
|
428
|
+
this.requireHousehold(await this.loadFixtureSnapshot(), householdId);
|
|
429
|
+
return this.fixtureAudioState(playerId).muted;
|
|
430
|
+
}
|
|
431
|
+
this.requireHousehold(await this.discoverTopology(), householdId);
|
|
432
|
+
const player = this.requireLiveRecord(playerId);
|
|
433
|
+
return await this.audioDevice(player.device).getMuted();
|
|
434
|
+
}
|
|
435
|
+
async setPlayerMuted(householdId, playerId, muted) {
|
|
436
|
+
if (this.livePlayers.size === 0) {
|
|
437
|
+
this.requireHousehold(await this.loadFixtureSnapshot(), householdId);
|
|
438
|
+
this.fixtureAudioState(playerId).muted = muted;
|
|
439
|
+
this.touchFixture(householdId);
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
this.requireHousehold(await this.discoverTopology(), householdId);
|
|
443
|
+
const player = this.requireLiveRecord(playerId);
|
|
444
|
+
await this.audioDevice(player.device).setMuted(muted);
|
|
445
|
+
}
|
|
367
446
|
async ungroup(householdId, coordinatorPlayerId, memberPlayerIds) {
|
|
368
447
|
const snapshot = await this.discoverTopology();
|
|
369
448
|
const household = this.requireHousehold(snapshot, householdId);
|
|
@@ -532,6 +611,7 @@ class LocalSonosTransport {
|
|
|
532
611
|
const resolvedFixturePath = resolveFixturePath(this.config.fixturePath);
|
|
533
612
|
if (!resolvedFixturePath) {
|
|
534
613
|
this.fixtureState = normalizeFixtureSnapshot(this.fixtureState);
|
|
614
|
+
this.fixturePlayerAudio = buildFixtureAudioState(this.fixtureState);
|
|
535
615
|
this.fixtureLoaded = true;
|
|
536
616
|
return clone(this.fixtureState);
|
|
537
617
|
}
|
|
@@ -539,11 +619,13 @@ class LocalSonosTransport {
|
|
|
539
619
|
const raw = await (0, promises_1.readFile)(resolvedFixturePath, "utf8");
|
|
540
620
|
const parsed = JSON.parse(raw);
|
|
541
621
|
this.fixtureState = normalizeFixtureSnapshot(parsed);
|
|
622
|
+
this.fixturePlayerAudio = buildFixtureAudioState(this.fixtureState);
|
|
542
623
|
this.fixtureLoaded = true;
|
|
543
624
|
return clone(this.fixtureState);
|
|
544
625
|
}
|
|
545
626
|
catch {
|
|
546
627
|
this.fixtureState = normalizeFixtureSnapshot(sampleTopology_1.sampleTopology);
|
|
628
|
+
this.fixturePlayerAudio = buildFixtureAudioState(this.fixtureState);
|
|
547
629
|
this.fixtureLoaded = true;
|
|
548
630
|
return clone(this.fixtureState);
|
|
549
631
|
}
|
|
@@ -654,6 +736,21 @@ class LocalSonosTransport {
|
|
|
654
736
|
};
|
|
655
737
|
this.lastSnapshot = clone(this.fixtureState);
|
|
656
738
|
}
|
|
739
|
+
fixtureAudioState(playerId) {
|
|
740
|
+
const existing = this.fixturePlayerAudio.get(playerId);
|
|
741
|
+
if (existing) {
|
|
742
|
+
return existing;
|
|
743
|
+
}
|
|
744
|
+
const state = {
|
|
745
|
+
volume: 0,
|
|
746
|
+
muted: false,
|
|
747
|
+
};
|
|
748
|
+
this.fixturePlayerAudio.set(playerId, state);
|
|
749
|
+
return state;
|
|
750
|
+
}
|
|
751
|
+
audioDevice(device) {
|
|
752
|
+
return device;
|
|
753
|
+
}
|
|
657
754
|
}
|
|
658
755
|
exports.LocalSonosTransport = LocalSonosTransport;
|
|
659
756
|
function randomString() {
|