hap-nodejs 0.12.3-beta.2 → 0.12.3-beta.21
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 +1 -0
- package/dist/accessories/AirConditioner_accessory.js +24 -24
- package/dist/accessories/AirConditioner_accessory.js.map +1 -1
- package/dist/accessories/AppleTVRemote_accessory.js +23 -23
- package/dist/accessories/AppleTVRemote_accessory.js.map +1 -1
- package/dist/accessories/Camera_accessory.js +292 -373
- package/dist/accessories/Camera_accessory.js.map +1 -1
- package/dist/accessories/Fan_accessory.js +15 -21
- package/dist/accessories/Fan_accessory.js.map +1 -1
- package/dist/accessories/GarageDoorOpener_accessory.js +12 -12
- package/dist/accessories/GarageDoorOpener_accessory.js.map +1 -1
- package/dist/accessories/Light-AdaptiveLighting_accessory.js +31 -21
- package/dist/accessories/Light-AdaptiveLighting_accessory.js.map +1 -1
- package/dist/accessories/Light_accessory.js +45 -48
- package/dist/accessories/Light_accessory.js.map +1 -1
- package/dist/accessories/Lock_accessory.js +11 -11
- package/dist/accessories/Lock_accessory.js.map +1 -1
- package/dist/accessories/MotionSensor_accessory.js +8 -8
- package/dist/accessories/MotionSensor_accessory.js.map +1 -1
- package/dist/accessories/Outlet_accessory.js +10 -10
- package/dist/accessories/Outlet_accessory.js.map +1 -1
- package/dist/accessories/SmartSpeaker_accessory.js +11 -11
- package/dist/accessories/SmartSpeaker_accessory.js.map +1 -1
- package/dist/accessories/Sprinkler_accessory.js +19 -19
- package/dist/accessories/Sprinkler_accessory.js.map +1 -1
- package/dist/accessories/TV_accessory.js +17 -17
- package/dist/accessories/TV_accessory.js.map +1 -1
- package/dist/accessories/TemperatureSensor_accessory.js +6 -6
- package/dist/accessories/TemperatureSensor_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiRouter_accessory.js +3 -3
- package/dist/accessories/Wi-FiRouter_accessory.js.map +1 -1
- package/dist/accessories/Wi-FiSatellite_accessory.js +4 -4
- package/dist/accessories/Wi-FiSatellite_accessory.js.map +1 -1
- package/dist/accessories/gstreamer-audioProducer.js +36 -47
- package/dist/accessories/gstreamer-audioProducer.js.map +1 -1
- package/dist/accessories/types.js +2 -2
- package/dist/accessories/types.js.map +1 -1
- package/dist/index.d.ts +0 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -28
- package/dist/index.js.map +1 -1
- package/dist/lib/Accessory.d.ts +1 -58
- package/dist/lib/Accessory.d.ts.map +1 -1
- package/dist/lib/Accessory.js +747 -1149
- package/dist/lib/Accessory.js.map +1 -1
- package/dist/lib/Advertiser.d.ts +1 -2
- package/dist/lib/Advertiser.d.ts.map +1 -1
- package/dist/lib/Advertiser.js +392 -524
- package/dist/lib/Advertiser.js.map +1 -1
- package/dist/lib/Bridge.js +6 -10
- package/dist/lib/Bridge.js.map +1 -1
- package/dist/lib/Characteristic.d.ts +2 -133
- package/dist/lib/Characteristic.d.ts.map +1 -1
- package/dist/lib/Characteristic.js +1467 -669
- package/dist/lib/Characteristic.js.map +1 -1
- package/dist/lib/HAPServer.d.ts +0 -10
- package/dist/lib/HAPServer.d.ts.map +1 -1
- package/dist/lib/HAPServer.js +216 -280
- package/dist/lib/HAPServer.js.map +1 -1
- package/dist/lib/Service.d.ts +1 -51
- package/dist/lib/Service.d.ts.map +1 -1
- package/dist/lib/Service.js +474 -322
- package/dist/lib/Service.js.map +1 -1
- package/dist/lib/camera/RTPProxy.js +112 -104
- package/dist/lib/camera/RTPProxy.js.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.d.ts +0 -65
- package/dist/lib/camera/RTPStreamManagement.d.ts.map +1 -1
- package/dist/lib/camera/RTPStreamManagement.js +255 -278
- package/dist/lib/camera/RTPStreamManagement.js.map +1 -1
- package/dist/lib/camera/RecordingManagement.js +318 -381
- package/dist/lib/camera/RecordingManagement.js.map +1 -1
- package/dist/lib/camera/index.d.ts +0 -1
- package/dist/lib/camera/index.d.ts.map +1 -1
- package/dist/lib/camera/index.js +1 -2
- package/dist/lib/camera/index.js.map +1 -1
- package/dist/lib/controller/AdaptiveLightingController.d.ts +19 -3
- package/dist/lib/controller/AdaptiveLightingController.d.ts.map +1 -1
- package/dist/lib/controller/AdaptiveLightingController.js +217 -218
- package/dist/lib/controller/AdaptiveLightingController.js.map +1 -1
- package/dist/lib/controller/CameraController.d.ts +0 -4
- package/dist/lib/controller/CameraController.d.ts.map +1 -1
- package/dist/lib/controller/CameraController.js +189 -256
- package/dist/lib/controller/CameraController.js.map +1 -1
- package/dist/lib/controller/DoorbellController.js +38 -39
- package/dist/lib/controller/DoorbellController.js.map +1 -1
- package/dist/lib/controller/RemoteController.d.ts +0 -14
- package/dist/lib/controller/RemoteController.d.ts.map +1 -1
- package/dist/lib/controller/RemoteController.js +340 -415
- package/dist/lib/controller/RemoteController.js.map +1 -1
- package/dist/lib/controller/index.js +1 -1
- package/dist/lib/datastream/DataStreamManagement.js +56 -57
- package/dist/lib/datastream/DataStreamManagement.js.map +1 -1
- package/dist/lib/datastream/DataStreamParser.js +259 -304
- package/dist/lib/datastream/DataStreamParser.js.map +1 -1
- package/dist/lib/datastream/DataStreamServer.d.ts +0 -5
- package/dist/lib/datastream/DataStreamServer.d.ts.map +1 -1
- package/dist/lib/datastream/DataStreamServer.js +252 -269
- package/dist/lib/datastream/DataStreamServer.js.map +1 -1
- package/dist/lib/datastream/index.js +1 -1
- package/dist/lib/definitions/CharacteristicDefinitions.d.ts +1 -106
- package/dist/lib/definitions/CharacteristicDefinitions.d.ts.map +1 -1
- package/dist/lib/definitions/CharacteristicDefinitions.js +2000 -2995
- package/dist/lib/definitions/CharacteristicDefinitions.js.map +1 -1
- package/dist/lib/definitions/ServiceDefinitions.d.ts +0 -32
- package/dist/lib/definitions/ServiceDefinitions.d.ts.map +1 -1
- package/dist/lib/definitions/ServiceDefinitions.js +820 -1147
- package/dist/lib/definitions/ServiceDefinitions.js.map +1 -1
- package/dist/lib/definitions/generate-definitions.js +383 -679
- package/dist/lib/definitions/generate-definitions.js.map +1 -1
- package/dist/lib/definitions/generator-configuration.js +29 -29
- package/dist/lib/definitions/generator-configuration.js.map +1 -1
- package/dist/lib/definitions/index.js +1 -1
- package/dist/lib/model/AccessoryInfo.js +101 -136
- package/dist/lib/model/AccessoryInfo.js.map +1 -1
- package/dist/lib/model/ControllerStorage.js +86 -89
- package/dist/lib/model/ControllerStorage.js.map +1 -1
- package/dist/lib/model/HAPStorage.js +15 -16
- package/dist/lib/model/HAPStorage.js.map +1 -1
- package/dist/lib/model/IdentifierCache.js +49 -49
- package/dist/lib/model/IdentifierCache.js.map +1 -1
- package/dist/lib/tv/AccessControlManagement.js +40 -44
- package/dist/lib/tv/AccessControlManagement.js.map +1 -1
- package/dist/lib/util/checkName.d.ts +2 -1
- package/dist/lib/util/checkName.d.ts.map +1 -1
- package/dist/lib/util/checkName.js +7 -11
- package/dist/lib/util/checkName.js.map +1 -1
- package/dist/lib/util/clone.js +5 -27
- package/dist/lib/util/clone.js.map +1 -1
- package/dist/lib/util/color-utils.js +8 -12
- package/dist/lib/util/color-utils.js.map +1 -1
- package/dist/lib/util/eventedhttp.d.ts.map +1 -1
- package/dist/lib/util/eventedhttp.js +301 -409
- package/dist/lib/util/eventedhttp.js.map +1 -1
- package/dist/lib/util/hapCrypto.js +31 -32
- package/dist/lib/util/hapCrypto.js.map +1 -1
- package/dist/lib/util/hapStatusError.js +9 -12
- package/dist/lib/util/hapStatusError.js.map +1 -1
- package/dist/lib/util/net-utils.js +32 -53
- package/dist/lib/util/net-utils.js.map +1 -1
- package/dist/lib/util/once.js +3 -8
- package/dist/lib/util/once.js.map +1 -1
- package/dist/lib/util/promise-utils.js +8 -13
- package/dist/lib/util/promise-utils.js.map +1 -1
- package/dist/lib/util/request-util.js +2 -3
- package/dist/lib/util/request-util.js.map +1 -1
- package/dist/lib/util/time.js +5 -5
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/tlv.d.ts +0 -27
- package/dist/lib/util/tlv.d.ts.map +1 -1
- package/dist/lib/util/tlv.js +71 -113
- package/dist/lib/util/tlv.js.map +1 -1
- package/dist/lib/util/uuid.d.ts +0 -9
- package/dist/lib/util/uuid.d.ts.map +1 -1
- package/dist/lib/util/uuid.js +15 -33
- package/dist/lib/util/uuid.js.map +1 -1
- package/dist/types.d.ts +0 -35
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +10 -10
- package/dist/BridgedCore.d.ts +0 -2
- package/dist/BridgedCore.d.ts.map +0 -1
- package/dist/BridgedCore.js +0 -43
- package/dist/BridgedCore.js.map +0 -1
- package/dist/Core.d.ts +0 -2
- package/dist/Core.d.ts.map +0 -1
- package/dist/Core.js +0 -52
- package/dist/Core.js.map +0 -1
- package/dist/lib/AccessoryLoader.d.ts +0 -28
- package/dist/lib/AccessoryLoader.d.ts.map +0 -1
- package/dist/lib/AccessoryLoader.js +0 -166
- package/dist/lib/AccessoryLoader.js.map +0 -1
- package/dist/lib/camera/Camera.d.ts +0 -43
- package/dist/lib/camera/Camera.d.ts.map +0 -1
- package/dist/lib/camera/Camera.js +0 -36
- package/dist/lib/camera/Camera.js.map +0 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SiriAudioSession = exports.SiriAudioSessionEvents = exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
exports.SiriAudioSession = exports.SiriAudioSessionEvents = exports.RemoteController = exports.RemoteControllerEvents = exports.TargetUpdates = exports.AudioCodecTypes = exports.ButtonState = exports.TargetCategory = exports.ButtonType = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const assert_1 = tslib_1.__importDefault(require("assert"));
|
|
6
|
+
const debug_1 = tslib_1.__importDefault(require("debug"));
|
|
7
|
+
const events_1 = require("events");
|
|
8
|
+
const Characteristic_1 = require("../Characteristic");
|
|
9
|
+
const datastream_1 = require("../datastream");
|
|
10
|
+
const Service_1 = require("../Service");
|
|
11
|
+
const tlv = tslib_1.__importStar(require("../util/tlv"));
|
|
12
|
+
const debug = (0, debug_1.default)("HAP-NodeJS:Remote:Controller");
|
|
13
13
|
var TargetControlCommands;
|
|
14
14
|
(function (TargetControlCommands) {
|
|
15
15
|
TargetControlCommands[TargetControlCommands["MAXIMUM_TARGETS"] = 1] = "MAXIMUM_TARGETS";
|
|
@@ -193,8 +193,39 @@ var RemoteControllerEvents;
|
|
|
193
193
|
* @group Apple TV Remote
|
|
194
194
|
*/
|
|
195
195
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
class RemoteController extends events_1.EventEmitter {
|
|
197
|
+
stateChangeDelegate;
|
|
198
|
+
audioSupported;
|
|
199
|
+
audioProducerConstructor;
|
|
200
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
201
|
+
audioProducerOptions;
|
|
202
|
+
targetControlManagementService;
|
|
203
|
+
targetControlService;
|
|
204
|
+
siriService;
|
|
205
|
+
audioStreamManagementService;
|
|
206
|
+
dataStreamManagement;
|
|
207
|
+
buttons = {}; // internal mapping of buttonId to buttonType for supported buttons
|
|
208
|
+
supportedConfiguration;
|
|
209
|
+
targetConfigurations = new Map();
|
|
210
|
+
targetConfigurationsString = "";
|
|
211
|
+
lastButtonEvent = "";
|
|
212
|
+
activeIdentifier = 0; // id of 0 means no device selected
|
|
213
|
+
activeConnection; // session which marked this remote as active and listens for events and siri
|
|
214
|
+
activeConnectionDisconnectListener;
|
|
215
|
+
supportedAudioConfiguration;
|
|
216
|
+
selectedAudioConfiguration;
|
|
217
|
+
selectedAudioConfigurationString;
|
|
218
|
+
dataStreamConnections = new Map(); // maps targetIdentifiers to active data stream connections
|
|
219
|
+
activeAudioSession;
|
|
220
|
+
nextAudioSession;
|
|
221
|
+
/**
|
|
222
|
+
* @private
|
|
223
|
+
*/
|
|
224
|
+
eventHandler;
|
|
225
|
+
/**
|
|
226
|
+
* @private
|
|
227
|
+
*/
|
|
228
|
+
requestHandler;
|
|
198
229
|
/**
|
|
199
230
|
* Creates a new RemoteController.
|
|
200
231
|
* If siri voice input is supported the constructor to an SiriAudioStreamProducer needs to be supplied.
|
|
@@ -207,22 +238,16 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
207
238
|
* constructor. This should be used to supply configurations to the stream producer.
|
|
208
239
|
*/
|
|
209
240
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/explicit-module-boundary-types
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
_this.audioProducerOptions = producerOptions;
|
|
221
|
-
var configuration = _this.constructSupportedConfiguration();
|
|
222
|
-
_this.supportedConfiguration = _this.buildTargetControlSupportedConfigurationTLV(configuration);
|
|
223
|
-
var audioConfiguration = _this.constructSupportedAudioConfiguration();
|
|
224
|
-
_this.supportedAudioConfiguration = RemoteController.buildSupportedAudioConfigurationTLV(audioConfiguration);
|
|
225
|
-
_this.selectedAudioConfiguration = {
|
|
241
|
+
constructor(audioProducerConstructor, producerOptions) {
|
|
242
|
+
super();
|
|
243
|
+
this.audioSupported = audioProducerConstructor !== undefined;
|
|
244
|
+
this.audioProducerConstructor = audioProducerConstructor;
|
|
245
|
+
this.audioProducerOptions = producerOptions;
|
|
246
|
+
const configuration = this.constructSupportedConfiguration();
|
|
247
|
+
this.supportedConfiguration = this.buildTargetControlSupportedConfigurationTLV(configuration);
|
|
248
|
+
const audioConfiguration = this.constructSupportedAudioConfiguration();
|
|
249
|
+
this.supportedAudioConfiguration = RemoteController.buildSupportedAudioConfigurationTLV(audioConfiguration);
|
|
250
|
+
this.selectedAudioConfiguration = {
|
|
226
251
|
codecType: 3 /* AudioCodecTypes.OPUS */,
|
|
227
252
|
parameters: {
|
|
228
253
|
channels: 1,
|
|
@@ -231,24 +256,22 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
231
256
|
rtpTime: 20,
|
|
232
257
|
},
|
|
233
258
|
};
|
|
234
|
-
|
|
235
|
-
audioCodecConfiguration:
|
|
259
|
+
this.selectedAudioConfigurationString = RemoteController.buildSelectedAudioConfigurationTLV({
|
|
260
|
+
audioCodecConfiguration: this.selectedAudioConfiguration,
|
|
236
261
|
});
|
|
237
|
-
return _this;
|
|
238
262
|
}
|
|
239
263
|
/**
|
|
240
264
|
* @private
|
|
241
265
|
*/
|
|
242
|
-
|
|
266
|
+
controllerId() {
|
|
243
267
|
return "remote" /* DefaultControllerType.REMOTE */;
|
|
244
|
-
}
|
|
268
|
+
}
|
|
245
269
|
/**
|
|
246
270
|
* Set a new target as active target. A value of 0 indicates that no target is selected currently.
|
|
247
271
|
*
|
|
248
272
|
* @param activeIdentifier - target identifier
|
|
249
273
|
*/
|
|
250
|
-
|
|
251
|
-
var _this = this;
|
|
274
|
+
setActiveIdentifier(activeIdentifier) {
|
|
252
275
|
if (activeIdentifier === this.activeIdentifier) {
|
|
253
276
|
return;
|
|
254
277
|
}
|
|
@@ -261,96 +284,73 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
261
284
|
if (this.activeAudioSession) {
|
|
262
285
|
this.handleSiriAudioStop();
|
|
263
286
|
}
|
|
264
|
-
setTimeout(
|
|
287
|
+
setTimeout(() => this.emit("active-identifier-change" /* RemoteControllerEvents.ACTIVE_IDENTIFIER_CHANGE */, activeIdentifier), 0);
|
|
265
288
|
this.setInactive();
|
|
266
|
-
}
|
|
289
|
+
}
|
|
267
290
|
/**
|
|
268
291
|
* @returns if the current target is active, meaning the active device is listening for button events or audio sessions
|
|
269
292
|
*/
|
|
270
|
-
|
|
293
|
+
isActive() {
|
|
271
294
|
return !!this.activeConnection;
|
|
272
|
-
}
|
|
295
|
+
}
|
|
273
296
|
/**
|
|
274
297
|
* Checks if the supplied targetIdentifier is configured.
|
|
275
298
|
*
|
|
276
299
|
* @param targetIdentifier - The target identifier.
|
|
277
300
|
*/
|
|
278
|
-
|
|
301
|
+
isConfigured(targetIdentifier) {
|
|
279
302
|
return this.targetConfigurations.has(targetIdentifier);
|
|
280
|
-
}
|
|
303
|
+
}
|
|
281
304
|
/**
|
|
282
305
|
* Returns the targetIdentifier for a give device name
|
|
283
306
|
*
|
|
284
307
|
* @param name - The name of the device.
|
|
285
308
|
* @returns The targetIdentifier of the device or undefined if not existent.
|
|
286
309
|
*/
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
var _d = tslib_1.__read(_c.value, 2), activeIdentifier = _d[0], configuration = _d[1];
|
|
292
|
-
if (configuration.targetName === name) {
|
|
293
|
-
return parseInt(activeIdentifier, 10);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
298
|
-
finally {
|
|
299
|
-
try {
|
|
300
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
310
|
+
getTargetIdentifierByName(name) {
|
|
311
|
+
for (const [activeIdentifier, configuration] of Object.entries(this.targetConfigurations)) {
|
|
312
|
+
if (configuration.targetName === name) {
|
|
313
|
+
return parseInt(activeIdentifier, 10);
|
|
301
314
|
}
|
|
302
|
-
finally { if (e_1) throw e_1.error; }
|
|
303
315
|
}
|
|
304
316
|
return undefined;
|
|
305
|
-
}
|
|
317
|
+
}
|
|
306
318
|
/**
|
|
307
319
|
* Sends a button event to press the supplied button.
|
|
308
320
|
*
|
|
309
321
|
* @param button - button to be pressed
|
|
310
322
|
*/
|
|
311
|
-
|
|
323
|
+
pushButton(button) {
|
|
312
324
|
this.sendButtonEvent(button, 1 /* ButtonState.DOWN */);
|
|
313
|
-
}
|
|
325
|
+
}
|
|
314
326
|
/**
|
|
315
327
|
* Sends a button event that the supplied button was released.
|
|
316
328
|
*
|
|
317
329
|
* @param button - button which was released
|
|
318
330
|
*/
|
|
319
|
-
|
|
331
|
+
releaseButton(button) {
|
|
320
332
|
this.sendButtonEvent(button, 0 /* ButtonState.UP */);
|
|
321
|
-
}
|
|
333
|
+
}
|
|
322
334
|
/**
|
|
323
335
|
* Presses a supplied button for a given time.
|
|
324
336
|
*
|
|
325
337
|
* @param button - button to be pressed and released
|
|
326
338
|
* @param time - time in milliseconds (defaults to 200ms)
|
|
327
339
|
*/
|
|
328
|
-
|
|
329
|
-
var _this = this;
|
|
330
|
-
if (time === void 0) { time = 200; }
|
|
340
|
+
pushAndReleaseButton(button, time = 200) {
|
|
331
341
|
this.pushButton(button);
|
|
332
|
-
setTimeout(
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* This method adds and configures the remote services for a give accessory.
|
|
336
|
-
*
|
|
337
|
-
* @param accessory - the give accessory this remote should be added to
|
|
338
|
-
* @deprecated - use {@link Accessory.configureController} instead
|
|
339
|
-
*/
|
|
340
|
-
RemoteController.prototype.addServicesToAccessory = function (accessory) {
|
|
341
|
-
accessory.configureController(this);
|
|
342
|
-
};
|
|
342
|
+
setTimeout(() => this.releaseButton(button), time);
|
|
343
|
+
}
|
|
343
344
|
// ---------------------------------- CONFIGURATION ----------------------------------
|
|
344
345
|
// override methods if you would like to change anything (but should not be necessary most likely)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
var configuration = {
|
|
346
|
+
constructSupportedConfiguration() {
|
|
347
|
+
const configuration = {
|
|
348
348
|
maximumTargets: 10, // some random number. (ten should be okay?)
|
|
349
349
|
ticksPerSecond: 1000, // we rely on unix timestamps
|
|
350
350
|
supportedButtonConfiguration: [],
|
|
351
351
|
hardwareImplemented: this.audioSupported, // siri is only allowed for hardware implemented remotes
|
|
352
352
|
};
|
|
353
|
-
|
|
353
|
+
const supportedButtons = [
|
|
354
354
|
1 /* ButtonType.MENU */, 2 /* ButtonType.PLAY_PAUSE */, 3 /* ButtonType.TV_HOME */, 4 /* ButtonType.SELECT */,
|
|
355
355
|
5 /* ButtonType.ARROW_UP */, 6 /* ButtonType.ARROW_RIGHT */, 7 /* ButtonType.ARROW_DOWN */, 8 /* ButtonType.ARROW_LEFT */,
|
|
356
356
|
9 /* ButtonType.VOLUME_UP */, 10 /* ButtonType.VOLUME_DOWN */, 12 /* ButtonType.POWER */, 13 /* ButtonType.GENERIC */,
|
|
@@ -358,17 +358,17 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
358
358
|
if (this.audioSupported) { // add siri button if this remote supports it
|
|
359
359
|
supportedButtons.push(11 /* ButtonType.SIRI */);
|
|
360
360
|
}
|
|
361
|
-
supportedButtons.forEach(
|
|
362
|
-
|
|
361
|
+
supportedButtons.forEach(button => {
|
|
362
|
+
const buttonConfiguration = {
|
|
363
363
|
buttonID: 100 + button,
|
|
364
364
|
buttonType: button,
|
|
365
365
|
};
|
|
366
366
|
configuration.supportedButtonConfiguration.push(buttonConfiguration);
|
|
367
|
-
|
|
367
|
+
this.buttons[button] = buttonConfiguration.buttonID; // also saving mapping of type to id locally
|
|
368
368
|
});
|
|
369
369
|
return configuration;
|
|
370
|
-
}
|
|
371
|
-
|
|
370
|
+
}
|
|
371
|
+
constructSupportedAudioConfiguration() {
|
|
372
372
|
// the following parameters are expected from HomeKit for a remote
|
|
373
373
|
return {
|
|
374
374
|
audioCodecConfiguration: {
|
|
@@ -380,19 +380,19 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
380
380
|
},
|
|
381
381
|
},
|
|
382
382
|
};
|
|
383
|
-
}
|
|
383
|
+
}
|
|
384
384
|
// --------------------------------- TARGET CONTROL ----------------------------------
|
|
385
385
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
386
|
+
handleTargetControlWrite(value, callback) {
|
|
387
|
+
const data = Buffer.from(value, "base64");
|
|
388
|
+
const objects = tlv.decode(data);
|
|
389
|
+
const operation = objects[1 /* TargetControlList.OPERATION */][0];
|
|
390
|
+
let targetConfiguration = undefined;
|
|
391
391
|
if (objects[2 /* TargetControlList.TARGET_CONFIGURATION */]) { // if target configuration was sent, parse it
|
|
392
392
|
targetConfiguration = this.parseTargetConfigurationTLV(objects[2 /* TargetControlList.TARGET_CONFIGURATION */]);
|
|
393
393
|
}
|
|
394
394
|
debug("Received TargetControl write operation %s", Operation[operation]);
|
|
395
|
-
|
|
395
|
+
let handler;
|
|
396
396
|
switch (operation) {
|
|
397
397
|
case Operation.ADD:
|
|
398
398
|
handler = this.handleAddTarget.bind(this);
|
|
@@ -413,7 +413,7 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
413
413
|
callback(-70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */, undefined);
|
|
414
414
|
return;
|
|
415
415
|
}
|
|
416
|
-
|
|
416
|
+
const status = handler(targetConfiguration);
|
|
417
417
|
if (status === 0 /* HAPStatus.SUCCESS */) {
|
|
418
418
|
callback(undefined, this.targetConfigurationsString); // passing value for write response
|
|
419
419
|
if (operation === Operation.ADD && this.activeIdentifier === 0) {
|
|
@@ -423,26 +423,23 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
423
423
|
else {
|
|
424
424
|
callback(new Error(status + ""));
|
|
425
425
|
}
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
var _this = this;
|
|
426
|
+
}
|
|
427
|
+
handleAddTarget(targetConfiguration) {
|
|
429
428
|
if (!targetConfiguration) {
|
|
430
429
|
return -70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */;
|
|
431
430
|
}
|
|
432
431
|
this.targetConfigurations.set(targetConfiguration.targetIdentifier, targetConfiguration);
|
|
433
432
|
debug("Configured new target '" + targetConfiguration.targetName + "' with targetIdentifier '" + targetConfiguration.targetIdentifier + "'");
|
|
434
|
-
setTimeout(
|
|
433
|
+
setTimeout(() => this.emit("target-add" /* RemoteControllerEvents.TARGET_ADDED */, targetConfiguration), 0);
|
|
435
434
|
this.updatedTargetConfiguration(); // set response
|
|
436
435
|
return 0 /* HAPStatus.SUCCESS */;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
var e_2, _a;
|
|
440
|
-
var _this = this;
|
|
436
|
+
}
|
|
437
|
+
handleUpdateTarget(targetConfiguration) {
|
|
441
438
|
if (!targetConfiguration) {
|
|
442
439
|
return -70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */;
|
|
443
440
|
}
|
|
444
|
-
|
|
445
|
-
|
|
441
|
+
const updates = [];
|
|
442
|
+
const configuredTarget = this.targetConfigurations.get(targetConfiguration.targetIdentifier);
|
|
446
443
|
if (!configuredTarget) {
|
|
447
444
|
return -70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */;
|
|
448
445
|
}
|
|
@@ -458,76 +455,64 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
458
455
|
}
|
|
459
456
|
if (targetConfiguration.buttonConfiguration) {
|
|
460
457
|
debug("%d button configurations were updated for target '%s' (%d)", Object.keys(targetConfiguration.buttonConfiguration).length, configuredTarget.targetName, configuredTarget.targetIdentifier);
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
savedConfiguration.buttonType = configuration.buttonType;
|
|
466
|
-
savedConfiguration.buttonName = configuration.buttonName;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
470
|
-
finally {
|
|
471
|
-
try {
|
|
472
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
473
|
-
}
|
|
474
|
-
finally { if (e_2) throw e_2.error; }
|
|
458
|
+
for (const configuration of Object.values(targetConfiguration.buttonConfiguration)) {
|
|
459
|
+
const savedConfiguration = configuredTarget.buttonConfiguration[configuration.buttonID];
|
|
460
|
+
savedConfiguration.buttonType = configuration.buttonType;
|
|
461
|
+
savedConfiguration.buttonName = configuration.buttonName;
|
|
475
462
|
}
|
|
476
463
|
updates.push(2 /* TargetUpdates.UPDATED_BUTTONS */);
|
|
477
464
|
}
|
|
478
|
-
setTimeout(
|
|
465
|
+
setTimeout(() => this.emit("target-update" /* RemoteControllerEvents.TARGET_UPDATED */, targetConfiguration, updates), 0);
|
|
479
466
|
this.updatedTargetConfiguration(); // set response
|
|
480
467
|
return 0 /* HAPStatus.SUCCESS */;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
var _this = this;
|
|
468
|
+
}
|
|
469
|
+
handleRemoveTarget(targetConfiguration) {
|
|
484
470
|
if (!targetConfiguration) {
|
|
485
471
|
return -70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */;
|
|
486
472
|
}
|
|
487
|
-
|
|
473
|
+
const configuredTarget = this.targetConfigurations.get(targetConfiguration.targetIdentifier);
|
|
488
474
|
if (!configuredTarget) {
|
|
489
475
|
return -70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */;
|
|
490
476
|
}
|
|
491
477
|
if (targetConfiguration.buttonConfiguration) {
|
|
492
|
-
for (
|
|
478
|
+
for (const key in targetConfiguration.buttonConfiguration) {
|
|
493
479
|
if (Object.prototype.hasOwnProperty.call(targetConfiguration.buttonConfiguration, key)) {
|
|
494
480
|
delete configuredTarget.buttonConfiguration[key];
|
|
495
481
|
}
|
|
496
482
|
}
|
|
497
483
|
debug("Removed %d button configurations of target '%s' (%d)", Object.keys(targetConfiguration.buttonConfiguration).length, configuredTarget.targetName, configuredTarget.targetIdentifier);
|
|
498
|
-
setTimeout(
|
|
484
|
+
setTimeout(() => this.emit("target-update" /* RemoteControllerEvents.TARGET_UPDATED */, configuredTarget, [3 /* TargetUpdates.REMOVED_BUTTONS */]), 0);
|
|
499
485
|
}
|
|
500
486
|
else {
|
|
501
487
|
this.targetConfigurations.delete(targetConfiguration.targetIdentifier);
|
|
502
488
|
debug("Target '%s' (%d) was removed", configuredTarget.targetName, configuredTarget.targetIdentifier);
|
|
503
|
-
setTimeout(
|
|
504
|
-
|
|
489
|
+
setTimeout(() => this.emit("target-remove" /* RemoteControllerEvents.TARGET_REMOVED */, targetConfiguration.targetIdentifier), 0);
|
|
490
|
+
const keys = Object.keys(this.targetConfigurations);
|
|
505
491
|
this.setActiveIdentifier(keys.length === 0 ? 0 : parseInt(keys[0], 10)); // switch to next available remote
|
|
506
492
|
}
|
|
507
493
|
this.updatedTargetConfiguration(); // set response
|
|
508
494
|
return 0 /* HAPStatus.SUCCESS */;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
var _this = this;
|
|
495
|
+
}
|
|
496
|
+
handleResetTargets(targetConfiguration) {
|
|
512
497
|
if (targetConfiguration) {
|
|
513
498
|
return -70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */;
|
|
514
499
|
}
|
|
515
500
|
debug("Resetting all target configurations");
|
|
516
501
|
this.targetConfigurations = new Map();
|
|
517
502
|
this.updatedTargetConfiguration(); // set response
|
|
518
|
-
setTimeout(
|
|
503
|
+
setTimeout(() => this.emit("targets-reset" /* RemoteControllerEvents.TARGETS_RESET */), 0);
|
|
519
504
|
this.setActiveIdentifier(0); // resetting active identifier (also sets active to false)
|
|
520
505
|
return 0 /* HAPStatus.SUCCESS */;
|
|
521
|
-
}
|
|
522
|
-
|
|
506
|
+
}
|
|
507
|
+
handleListTargets(targetConfiguration) {
|
|
523
508
|
if (targetConfiguration) {
|
|
524
509
|
return -70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */;
|
|
525
510
|
}
|
|
526
511
|
// this.targetConfigurationsString is updated after each change, so we basically don't need to do anything here
|
|
527
512
|
debug("Returning " + Object.keys(this.targetConfigurations).length + " target configurations");
|
|
528
513
|
return 0 /* HAPStatus.SUCCESS */;
|
|
529
|
-
}
|
|
530
|
-
|
|
514
|
+
}
|
|
515
|
+
handleActiveWrite(value, callback, connection) {
|
|
531
516
|
if (this.activeIdentifier === 0) {
|
|
532
517
|
debug("Tried to change active state. There is no active target set though");
|
|
533
518
|
callback(-70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */);
|
|
@@ -543,7 +528,7 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
543
528
|
this.activeConnectionDisconnectListener = this.handleActiveSessionDisconnected.bind(this, this.activeConnection);
|
|
544
529
|
this.activeConnection.on("closed" /* HAPConnectionEvent.CLOSED */, this.activeConnectionDisconnectListener);
|
|
545
530
|
}
|
|
546
|
-
|
|
531
|
+
const activeTarget = this.targetConfigurations.get(this.activeIdentifier);
|
|
547
532
|
if (!activeTarget) {
|
|
548
533
|
callback(-70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */);
|
|
549
534
|
return;
|
|
@@ -551,9 +536,8 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
551
536
|
debug("Remote with activeTarget '%s' (%d) was set to %s", activeTarget.targetName, this.activeIdentifier, value ? "ACTIVE" : "INACTIVE");
|
|
552
537
|
callback();
|
|
553
538
|
this.emit("active-change" /* RemoteControllerEvents.ACTIVE_CHANGE */, value);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
var _this = this;
|
|
539
|
+
}
|
|
540
|
+
setInactive() {
|
|
557
541
|
if (this.activeConnection === undefined) {
|
|
558
542
|
return;
|
|
559
543
|
}
|
|
@@ -562,17 +546,17 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
562
546
|
this.activeConnectionDisconnectListener = undefined;
|
|
563
547
|
this.targetControlService.getCharacteristic(Characteristic_1.Characteristic.Active).updateValue(false);
|
|
564
548
|
debug("Remote was set to INACTIVE");
|
|
565
|
-
setTimeout(
|
|
566
|
-
}
|
|
567
|
-
|
|
549
|
+
setTimeout(() => this.emit("active-change" /* RemoteControllerEvents.ACTIVE_CHANGE */, false), 0);
|
|
550
|
+
}
|
|
551
|
+
handleActiveSessionDisconnected(connection) {
|
|
568
552
|
if (connection !== this.activeConnection) {
|
|
569
553
|
return;
|
|
570
554
|
}
|
|
571
555
|
debug("Active hap session disconnected!");
|
|
572
556
|
this.setInactive();
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
|
|
557
|
+
}
|
|
558
|
+
sendButtonEvent(button, buttonState) {
|
|
559
|
+
const buttonID = this.buttons[button];
|
|
576
560
|
if (buttonID === undefined || buttonID === 0) {
|
|
577
561
|
throw new Error("Tried sending button event for unsupported button (" + button + ")");
|
|
578
562
|
}
|
|
@@ -591,33 +575,33 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
591
575
|
}
|
|
592
576
|
return;
|
|
593
577
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
578
|
+
const buttonIdTlv = tlv.encode(1 /* ButtonEvent.BUTTON_ID */, buttonID);
|
|
579
|
+
const buttonStateTlv = tlv.encode(2 /* ButtonEvent.BUTTON_STATE */, buttonState);
|
|
580
|
+
const timestampTlv = tlv.encode(3 /* ButtonEvent.TIMESTAMP */, tlv.writeVariableUIntLE(new Date().getTime()));
|
|
581
|
+
const activeIdentifierTlv = tlv.encode(4 /* ButtonEvent.ACTIVE_IDENTIFIER */, tlv.writeUInt32(this.activeIdentifier));
|
|
598
582
|
this.lastButtonEvent = Buffer.concat([
|
|
599
583
|
buttonIdTlv, buttonStateTlv, timestampTlv, activeIdentifierTlv,
|
|
600
584
|
]).toString("base64");
|
|
601
585
|
this.targetControlService.getCharacteristic(Characteristic_1.Characteristic.ButtonEvent).sendEventNotification(this.lastButtonEvent);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
586
|
+
}
|
|
587
|
+
parseTargetConfigurationTLV(data) {
|
|
588
|
+
const configTLV = tlv.decode(data);
|
|
589
|
+
const identifier = tlv.readUInt32(configTLV[1 /* TargetConfigurationTypes.TARGET_IDENTIFIER */]);
|
|
590
|
+
let name = undefined;
|
|
607
591
|
if (configTLV[2 /* TargetConfigurationTypes.TARGET_NAME */]) {
|
|
608
592
|
name = configTLV[2 /* TargetConfigurationTypes.TARGET_NAME */].toString();
|
|
609
593
|
}
|
|
610
|
-
|
|
594
|
+
let category = undefined;
|
|
611
595
|
if (configTLV[3 /* TargetConfigurationTypes.TARGET_CATEGORY */]) {
|
|
612
596
|
category = tlv.readUInt16(configTLV[3 /* TargetConfigurationTypes.TARGET_CATEGORY */]);
|
|
613
597
|
}
|
|
614
|
-
|
|
598
|
+
const buttonConfiguration = {};
|
|
615
599
|
if (configTLV[4 /* TargetConfigurationTypes.BUTTON_CONFIGURATION */]) {
|
|
616
|
-
|
|
617
|
-
buttonConfigurationTLV.forEach(
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
600
|
+
const buttonConfigurationTLV = tlv.decodeList(configTLV[4 /* TargetConfigurationTypes.BUTTON_CONFIGURATION */], 1 /* ButtonConfigurationTypes.BUTTON_ID */);
|
|
601
|
+
buttonConfigurationTLV.forEach(entry => {
|
|
602
|
+
const buttonId = entry[1 /* ButtonConfigurationTypes.BUTTON_ID */][0];
|
|
603
|
+
const buttonType = tlv.readUInt16(entry[2 /* ButtonConfigurationTypes.BUTTON_TYPE */]);
|
|
604
|
+
let buttonName;
|
|
621
605
|
if (entry[3 /* ButtonConfigurationTypes.BUTTON_NAME */]) {
|
|
622
606
|
buttonName = entry[3 /* ButtonConfigurationTypes.BUTTON_NAME */].toString();
|
|
623
607
|
}
|
|
@@ -638,74 +622,52 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
638
622
|
targetCategory: category,
|
|
639
623
|
buttonConfiguration: buttonConfiguration,
|
|
640
624
|
};
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
var tlvBuffer = tlv.encode(1 /* ButtonConfigurationTypes.BUTTON_ID */, value.buttonID, 2 /* ButtonConfigurationTypes.BUTTON_TYPE */, tlv.writeUInt16(value.buttonType));
|
|
657
|
-
if (value.buttonName) {
|
|
658
|
-
tlvBuffer = Buffer.concat([
|
|
659
|
-
tlvBuffer,
|
|
660
|
-
tlv.encode(3 /* ButtonConfigurationTypes.BUTTON_NAME */, value.buttonName),
|
|
661
|
-
]);
|
|
662
|
-
}
|
|
663
|
-
buttonConfigurationBuffers.push(tlvBuffer);
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
667
|
-
finally {
|
|
668
|
-
try {
|
|
669
|
-
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
|
|
670
|
-
}
|
|
671
|
-
finally { if (e_4) throw e_4.error; }
|
|
625
|
+
}
|
|
626
|
+
updatedTargetConfiguration() {
|
|
627
|
+
const bufferList = [];
|
|
628
|
+
for (const configuration of Object.values(this.targetConfigurations)) {
|
|
629
|
+
const targetIdentifier = tlv.encode(1 /* TargetConfigurationTypes.TARGET_IDENTIFIER */, tlv.writeUInt32(configuration.targetIdentifier));
|
|
630
|
+
const targetName = tlv.encode(2 /* TargetConfigurationTypes.TARGET_NAME */, configuration.targetName);
|
|
631
|
+
const targetCategory = tlv.encode(3 /* TargetConfigurationTypes.TARGET_CATEGORY */, tlv.writeUInt16(configuration.targetCategory));
|
|
632
|
+
const buttonConfigurationBuffers = [];
|
|
633
|
+
for (const value of configuration.buttonConfiguration.values()) {
|
|
634
|
+
let tlvBuffer = tlv.encode(1 /* ButtonConfigurationTypes.BUTTON_ID */, value.buttonID, 2 /* ButtonConfigurationTypes.BUTTON_TYPE */, tlv.writeUInt16(value.buttonType));
|
|
635
|
+
if (value.buttonName) {
|
|
636
|
+
tlvBuffer = Buffer.concat([
|
|
637
|
+
tlvBuffer,
|
|
638
|
+
tlv.encode(3 /* ButtonConfigurationTypes.BUTTON_NAME */, value.buttonName),
|
|
639
|
+
]);
|
|
672
640
|
}
|
|
673
|
-
|
|
674
|
-
var targetConfiguration = Buffer.concat([targetIdentifier, targetName, targetCategory, buttonConfiguration]);
|
|
675
|
-
bufferList.push(tlv.encode(2 /* TargetControlList.TARGET_CONFIGURATION */, targetConfiguration));
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
679
|
-
finally {
|
|
680
|
-
try {
|
|
681
|
-
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
641
|
+
buttonConfigurationBuffers.push(tlvBuffer);
|
|
682
642
|
}
|
|
683
|
-
|
|
643
|
+
const buttonConfiguration = tlv.encode(4 /* TargetConfigurationTypes.BUTTON_CONFIGURATION */, Buffer.concat(buttonConfigurationBuffers));
|
|
644
|
+
const targetConfiguration = Buffer.concat([targetIdentifier, targetName, targetCategory, buttonConfiguration]);
|
|
645
|
+
bufferList.push(tlv.encode(2 /* TargetControlList.TARGET_CONFIGURATION */, targetConfiguration));
|
|
684
646
|
}
|
|
685
647
|
this.targetConfigurationsString = Buffer.concat(bufferList).toString("base64");
|
|
686
|
-
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
configuration.supportedButtonConfiguration.forEach(
|
|
693
|
-
|
|
648
|
+
this.stateChangeDelegate?.();
|
|
649
|
+
}
|
|
650
|
+
buildTargetControlSupportedConfigurationTLV(configuration) {
|
|
651
|
+
const maximumTargets = tlv.encode(1 /* TargetControlCommands.MAXIMUM_TARGETS */, configuration.maximumTargets);
|
|
652
|
+
const ticksPerSecond = tlv.encode(2 /* TargetControlCommands.TICKS_PER_SECOND */, tlv.writeVariableUIntLE(configuration.ticksPerSecond));
|
|
653
|
+
const supportedButtonConfigurationBuffers = [];
|
|
654
|
+
configuration.supportedButtonConfiguration.forEach(value => {
|
|
655
|
+
const tlvBuffer = tlv.encode(1 /* SupportedButtonConfigurationTypes.BUTTON_ID */, value.buttonID, 2 /* SupportedButtonConfigurationTypes.BUTTON_TYPE */, tlv.writeUInt16(value.buttonType));
|
|
694
656
|
supportedButtonConfigurationBuffers.push(tlvBuffer);
|
|
695
657
|
});
|
|
696
|
-
|
|
697
|
-
|
|
658
|
+
const supportedButtonConfiguration = tlv.encode(3 /* TargetControlCommands.SUPPORTED_BUTTON_CONFIGURATION */, Buffer.concat(supportedButtonConfigurationBuffers));
|
|
659
|
+
const type = tlv.encode(4 /* TargetControlCommands.TYPE */, configuration.hardwareImplemented ? 1 : 0);
|
|
698
660
|
return Buffer.concat([maximumTargets, ticksPerSecond, supportedButtonConfiguration, type]).toString("base64");
|
|
699
|
-
}
|
|
661
|
+
}
|
|
700
662
|
// --------------------------------- SIRI/DATA STREAM --------------------------------
|
|
701
663
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
702
|
-
|
|
703
|
-
|
|
664
|
+
handleTargetControlWhoAmI(connection, message) {
|
|
665
|
+
const targetIdentifier = message.identifier;
|
|
704
666
|
this.dataStreamConnections.set(targetIdentifier, connection);
|
|
705
667
|
debug("Discovered HDS connection for targetIdentifier %s", targetIdentifier);
|
|
706
668
|
connection.addProtocolHandler("dataSend" /* Protocols.DATA_SEND */, this);
|
|
707
|
-
}
|
|
708
|
-
|
|
669
|
+
}
|
|
670
|
+
handleSiriAudioStart() {
|
|
709
671
|
if (!this.audioSupported) {
|
|
710
672
|
throw new Error("Cannot start siri stream on remote where siri is not supported");
|
|
711
673
|
}
|
|
@@ -719,13 +681,13 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
719
681
|
debug("Tried opening Siri audio stream, however there is already one in progress");
|
|
720
682
|
return;
|
|
721
683
|
}
|
|
722
|
-
|
|
684
|
+
const connection = this.dataStreamConnections.get(this.activeIdentifier); // get connection for current target
|
|
723
685
|
if (connection === undefined) { // target seems not connected, ignore it
|
|
724
686
|
debug("Tried opening Siri audio stream however target is not connected via HDS");
|
|
725
687
|
return;
|
|
726
688
|
}
|
|
727
689
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
728
|
-
|
|
690
|
+
const audioSession = new SiriAudioSession(connection, this.selectedAudioConfiguration, this.audioProducerConstructor, this.audioProducerOptions);
|
|
729
691
|
if (!this.activeAudioSession) {
|
|
730
692
|
this.activeAudioSession = audioSession;
|
|
731
693
|
}
|
|
@@ -736,8 +698,8 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
736
698
|
}
|
|
737
699
|
audioSession.on("close" /* SiriAudioSessionEvents.CLOSE */, this.handleSiriAudioSessionClosed.bind(this, audioSession));
|
|
738
700
|
audioSession.start();
|
|
739
|
-
}
|
|
740
|
-
|
|
701
|
+
}
|
|
702
|
+
handleSiriAudioStop() {
|
|
741
703
|
if (this.activeAudioSession) {
|
|
742
704
|
if (!this.activeAudioSession.isClosing()) {
|
|
743
705
|
this.activeAudioSession.stop();
|
|
@@ -749,11 +711,11 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
749
711
|
}
|
|
750
712
|
}
|
|
751
713
|
debug("handleSiriAudioStop called although no audio session was started");
|
|
752
|
-
}
|
|
714
|
+
}
|
|
753
715
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
716
|
+
handleDataSendAckEvent(message) {
|
|
717
|
+
const streamId = message.streamId;
|
|
718
|
+
const endOfStream = message.endOfStream;
|
|
757
719
|
if (this.activeAudioSession && this.activeAudioSession.streamId === streamId) {
|
|
758
720
|
this.activeAudioSession.handleDataSendAckEvent(endOfStream);
|
|
759
721
|
}
|
|
@@ -763,11 +725,11 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
763
725
|
else {
|
|
764
726
|
debug("Received dataSend acknowledgment event for unknown streamId '%s'", streamId);
|
|
765
727
|
}
|
|
766
|
-
}
|
|
728
|
+
}
|
|
767
729
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
730
|
+
handleDataSendCloseEvent(message) {
|
|
731
|
+
const streamId = message.streamId;
|
|
732
|
+
const reason = message.reason;
|
|
771
733
|
if (this.activeAudioSession && this.activeAudioSession.streamId === streamId) {
|
|
772
734
|
this.activeAudioSession.handleDataSendCloseEvent(reason);
|
|
773
735
|
}
|
|
@@ -777,8 +739,8 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
777
739
|
else {
|
|
778
740
|
debug("Received dataSend close event for unknown streamId '%s'", streamId);
|
|
779
741
|
}
|
|
780
|
-
}
|
|
781
|
-
|
|
742
|
+
}
|
|
743
|
+
handleSiriAudioSessionClosed(session) {
|
|
782
744
|
if (session === this.activeAudioSession) {
|
|
783
745
|
this.activeAudioSession = this.nextAudioSession;
|
|
784
746
|
this.nextAudioSession = undefined;
|
|
@@ -786,38 +748,27 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
786
748
|
else if (session === this.nextAudioSession) {
|
|
787
749
|
this.nextAudioSession = undefined;
|
|
788
750
|
}
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
debug("HDS connection disconnected for targetIdentifier %s", targetIdentifier);
|
|
797
|
-
this.dataStreamConnections.delete(targetIdentifier);
|
|
798
|
-
break;
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
catch (e_5_1) { e_5 = { error: e_5_1 }; }
|
|
803
|
-
finally {
|
|
804
|
-
try {
|
|
805
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
751
|
+
}
|
|
752
|
+
handleDataStreamConnectionClosed(connection) {
|
|
753
|
+
for (const [targetIdentifier, connection0] of this.dataStreamConnections) {
|
|
754
|
+
if (connection === connection0) {
|
|
755
|
+
debug("HDS connection disconnected for targetIdentifier %s", targetIdentifier);
|
|
756
|
+
this.dataStreamConnections.delete(targetIdentifier);
|
|
757
|
+
break;
|
|
806
758
|
}
|
|
807
|
-
finally { if (e_5) throw e_5.error; }
|
|
808
759
|
}
|
|
809
|
-
}
|
|
760
|
+
}
|
|
810
761
|
// ------------------------------- AUDIO CONFIGURATION -------------------------------
|
|
811
762
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
763
|
+
handleSelectedAudioConfigurationWrite(value, callback) {
|
|
764
|
+
const data = Buffer.from(value, "base64");
|
|
765
|
+
const objects = tlv.decode(data);
|
|
766
|
+
const selectedAudioStreamConfiguration = tlv.decode(objects[1 /* SelectedAudioInputStreamConfigurationTypes.SELECTED_AUDIO_INPUT_STREAM_CONFIGURATION */]);
|
|
767
|
+
const codec = selectedAudioStreamConfiguration[1 /* AudioCodecConfigurationTypes.CODEC_TYPE */][0];
|
|
768
|
+
const parameters = tlv.decode(selectedAudioStreamConfiguration[2 /* AudioCodecConfigurationTypes.CODEC_PARAMETERS */]);
|
|
769
|
+
const channels = parameters[1 /* AudioCodecParametersTypes.CHANNEL */][0];
|
|
770
|
+
const bitrate = parameters[2 /* AudioCodecParametersTypes.BIT_RATE */][0];
|
|
771
|
+
const samplerate = parameters[3 /* AudioCodecParametersTypes.SAMPLE_RATE */][0];
|
|
821
772
|
this.selectedAudioConfiguration = {
|
|
822
773
|
codecType: codec,
|
|
823
774
|
parameters: {
|
|
@@ -831,20 +782,20 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
831
782
|
audioCodecConfiguration: this.selectedAudioConfiguration,
|
|
832
783
|
});
|
|
833
784
|
callback();
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
785
|
+
}
|
|
786
|
+
static buildSupportedAudioConfigurationTLV(configuration) {
|
|
787
|
+
const codecConfigurationTLV = RemoteController.buildCodecConfigurationTLV(configuration.audioCodecConfiguration);
|
|
788
|
+
const supportedAudioStreamConfiguration = tlv.encode(1 /* SupportedAudioStreamConfigurationTypes.AUDIO_CODEC_CONFIGURATION */, codecConfigurationTLV);
|
|
838
789
|
return supportedAudioStreamConfiguration.toString("base64");
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
790
|
+
}
|
|
791
|
+
static buildSelectedAudioConfigurationTLV(configuration) {
|
|
792
|
+
const codecConfigurationTLV = RemoteController.buildCodecConfigurationTLV(configuration.audioCodecConfiguration);
|
|
793
|
+
const supportedAudioStreamConfiguration = tlv.encode(1 /* SelectedAudioInputStreamConfigurationTypes.SELECTED_AUDIO_INPUT_STREAM_CONFIGURATION */, codecConfigurationTLV);
|
|
843
794
|
return supportedAudioStreamConfiguration.toString("base64");
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
795
|
+
}
|
|
796
|
+
static buildCodecConfigurationTLV(codecConfiguration) {
|
|
797
|
+
const parameters = codecConfiguration.parameters;
|
|
798
|
+
let parametersTLV = tlv.encode(1 /* AudioCodecParametersTypes.CHANNEL */, parameters.channels, 2 /* AudioCodecParametersTypes.BIT_RATE */, parameters.bitrate, 3 /* AudioCodecParametersTypes.SAMPLE_RATE */, parameters.samplerate);
|
|
848
799
|
if (parameters.rtpTime) {
|
|
849
800
|
parametersTLV = Buffer.concat([
|
|
850
801
|
parametersTLV,
|
|
@@ -852,13 +803,12 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
852
803
|
]);
|
|
853
804
|
}
|
|
854
805
|
return tlv.encode(1 /* AudioCodecConfigurationTypes.CODEC_TYPE */, codecConfiguration.codecType, 2 /* AudioCodecConfigurationTypes.CODEC_PARAMETERS */, parametersTLV);
|
|
855
|
-
}
|
|
806
|
+
}
|
|
856
807
|
// -----------------------------------------------------------------------------------
|
|
857
808
|
/**
|
|
858
809
|
* @private
|
|
859
810
|
*/
|
|
860
|
-
|
|
861
|
-
var _a;
|
|
811
|
+
constructServices() {
|
|
862
812
|
this.targetControlManagementService = new Service_1.Service.TargetControlManagement("", "");
|
|
863
813
|
this.targetControlManagementService.setCharacteristic(Characteristic_1.Characteristic.TargetControlSupportedConfiguration, this.supportedConfiguration);
|
|
864
814
|
this.targetControlManagementService.setCharacteristic(Characteristic_1.Characteristic.TargetControlList, this.targetConfigurationsString);
|
|
@@ -884,146 +834,127 @@ var RemoteController = /** @class */ (function (_super) {
|
|
|
884
834
|
targetControl: this.targetControlService,
|
|
885
835
|
siri: this.siriService,
|
|
886
836
|
audioStreamManagement: this.audioStreamManagementService,
|
|
887
|
-
dataStreamTransportManagement:
|
|
837
|
+
dataStreamTransportManagement: this.dataStreamManagement?.getService(),
|
|
888
838
|
};
|
|
889
|
-
}
|
|
839
|
+
}
|
|
890
840
|
/**
|
|
891
841
|
* @private
|
|
892
842
|
*/
|
|
893
|
-
|
|
843
|
+
initWithServices(serviceMap) {
|
|
894
844
|
this.targetControlManagementService = serviceMap.targetControlManagement;
|
|
895
845
|
this.targetControlService = serviceMap.targetControl;
|
|
896
846
|
this.siriService = serviceMap.siri;
|
|
897
847
|
this.audioStreamManagementService = serviceMap.audioStreamManagement;
|
|
898
848
|
this.dataStreamManagement = new datastream_1.DataStreamManagement(serviceMap.dataStreamTransportManagement);
|
|
899
|
-
}
|
|
849
|
+
}
|
|
900
850
|
/**
|
|
901
851
|
* @private
|
|
902
852
|
*/
|
|
903
|
-
|
|
904
|
-
var _a;
|
|
905
|
-
var _this = this;
|
|
853
|
+
configureServices() {
|
|
906
854
|
if (!this.targetControlManagementService || !this.targetControlService) {
|
|
907
855
|
throw new Error("Unexpected state: Services not configured!"); // playing it save
|
|
908
856
|
}
|
|
909
857
|
this.targetControlManagementService.getCharacteristic(Characteristic_1.Characteristic.TargetControlList)
|
|
910
|
-
.on("get" /* CharacteristicEventTypes.GET */,
|
|
911
|
-
callback(null,
|
|
858
|
+
.on("get" /* CharacteristicEventTypes.GET */, callback => {
|
|
859
|
+
callback(null, this.targetConfigurationsString);
|
|
912
860
|
})
|
|
913
861
|
.on("set" /* CharacteristicEventTypes.SET */, this.handleTargetControlWrite.bind(this));
|
|
914
862
|
this.targetControlService.getCharacteristic(Characteristic_1.Characteristic.ActiveIdentifier)
|
|
915
|
-
.on("get" /* CharacteristicEventTypes.GET */,
|
|
916
|
-
callback(undefined,
|
|
863
|
+
.on("get" /* CharacteristicEventTypes.GET */, callback => {
|
|
864
|
+
callback(undefined, this.activeIdentifier);
|
|
917
865
|
});
|
|
918
866
|
this.targetControlService.getCharacteristic(Characteristic_1.Characteristic.Active)
|
|
919
|
-
.on("get" /* CharacteristicEventTypes.GET */,
|
|
920
|
-
callback(undefined,
|
|
867
|
+
.on("get" /* CharacteristicEventTypes.GET */, callback => {
|
|
868
|
+
callback(undefined, this.isActive());
|
|
921
869
|
})
|
|
922
|
-
.on("set" /* CharacteristicEventTypes.SET */,
|
|
870
|
+
.on("set" /* CharacteristicEventTypes.SET */, (value, callback, context, connection) => {
|
|
923
871
|
if (!connection) {
|
|
924
872
|
debug("Set event handler for Remote.Active cannot be called from plugin. Connection undefined!");
|
|
925
873
|
callback(-70410 /* HAPStatus.INVALID_VALUE_IN_REQUEST */);
|
|
926
874
|
return;
|
|
927
875
|
}
|
|
928
|
-
|
|
876
|
+
this.handleActiveWrite(value, callback, connection);
|
|
929
877
|
});
|
|
930
878
|
this.targetControlService.getCharacteristic(Characteristic_1.Characteristic.ButtonEvent)
|
|
931
|
-
.on("get" /* CharacteristicEventTypes.GET */,
|
|
932
|
-
callback(undefined,
|
|
879
|
+
.on("get" /* CharacteristicEventTypes.GET */, (callback) => {
|
|
880
|
+
callback(undefined, this.lastButtonEvent);
|
|
933
881
|
});
|
|
934
882
|
if (this.audioSupported) {
|
|
935
883
|
this.audioStreamManagementService.getCharacteristic(Characteristic_1.Characteristic.SelectedAudioStreamConfiguration)
|
|
936
|
-
.on("get" /* CharacteristicEventTypes.GET */,
|
|
937
|
-
callback(null,
|
|
884
|
+
.on("get" /* CharacteristicEventTypes.GET */, callback => {
|
|
885
|
+
callback(null, this.selectedAudioConfigurationString);
|
|
938
886
|
})
|
|
939
887
|
.on("set" /* CharacteristicEventTypes.SET */, this.handleSelectedAudioConfigurationWrite.bind(this))
|
|
940
888
|
.updateValue(this.selectedAudioConfigurationString);
|
|
941
889
|
this.dataStreamManagement
|
|
942
890
|
.onEventMessage("targetControl" /* Protocols.TARGET_CONTROL */, "whoami" /* Topics.WHOAMI */, this.handleTargetControlWhoAmI.bind(this))
|
|
943
891
|
.onServerEvent("connection-closed" /* DataStreamServerEvent.CONNECTION_CLOSED */, this.handleDataStreamConnectionClosed.bind(this));
|
|
944
|
-
this.eventHandler =
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
892
|
+
this.eventHandler = {
|
|
893
|
+
["ack" /* Topics.ACK */]: this.handleDataSendAckEvent.bind(this),
|
|
894
|
+
["close" /* Topics.CLOSE */]: this.handleDataSendCloseEvent.bind(this),
|
|
895
|
+
};
|
|
948
896
|
}
|
|
949
|
-
}
|
|
897
|
+
}
|
|
950
898
|
/**
|
|
951
899
|
* @private
|
|
952
900
|
*/
|
|
953
|
-
|
|
954
|
-
var _a;
|
|
901
|
+
handleControllerRemoved() {
|
|
955
902
|
this.targetControlManagementService = undefined;
|
|
956
903
|
this.targetControlService = undefined;
|
|
957
904
|
this.siriService = undefined;
|
|
958
905
|
this.audioStreamManagementService = undefined;
|
|
959
906
|
this.eventHandler = undefined;
|
|
960
907
|
this.requestHandler = undefined;
|
|
961
|
-
|
|
908
|
+
this.dataStreamManagement?.destroy();
|
|
962
909
|
this.dataStreamManagement = undefined;
|
|
963
910
|
// the call to dataStreamManagement.destroy will close any open data stream connection
|
|
964
911
|
// which will result in a call to this.handleDataStreamConnectionClosed, cleaning up this.dataStreamConnections.
|
|
965
912
|
// It will also result in a call to SiriAudioSession.handleDataStreamConnectionClosed (if there are any open session)
|
|
966
913
|
// which again results in a call to this.handleSiriAudioSessionClosed,cleaning up this.activeAudioSession and this.nextAudioSession.
|
|
967
|
-
}
|
|
914
|
+
}
|
|
968
915
|
/**
|
|
969
916
|
* @private
|
|
970
917
|
*/
|
|
971
|
-
|
|
918
|
+
handleFactoryReset() {
|
|
972
919
|
debug("Running factory reset. Resetting targets...");
|
|
973
920
|
this.handleResetTargets(undefined);
|
|
974
921
|
this.lastButtonEvent = "";
|
|
975
|
-
}
|
|
922
|
+
}
|
|
976
923
|
/**
|
|
977
924
|
* @private
|
|
978
925
|
*/
|
|
979
|
-
|
|
926
|
+
serialize() {
|
|
980
927
|
if (!this.activeIdentifier && Object.keys(this.targetConfigurations).length === 0) {
|
|
981
928
|
return undefined;
|
|
982
929
|
}
|
|
983
930
|
return {
|
|
984
931
|
activeIdentifier: this.activeIdentifier,
|
|
985
|
-
targetConfigurations:
|
|
986
|
-
var _b = tslib_1.__read(_a, 2), key = _b[0], value = _b[1];
|
|
932
|
+
targetConfigurations: [...this.targetConfigurations].reduce((obj, [key, value]) => {
|
|
987
933
|
obj[key] = value;
|
|
988
934
|
return obj;
|
|
989
935
|
}, {}),
|
|
990
936
|
};
|
|
991
|
-
}
|
|
937
|
+
}
|
|
992
938
|
/**
|
|
993
939
|
* @private
|
|
994
940
|
*/
|
|
995
|
-
|
|
941
|
+
deserialize(serialized) {
|
|
996
942
|
this.activeIdentifier = serialized.activeIdentifier;
|
|
997
|
-
this.targetConfigurations = Object.entries(serialized.targetConfigurations).reduce(
|
|
998
|
-
|
|
999
|
-
var identifier = parseInt(key, 10);
|
|
943
|
+
this.targetConfigurations = Object.entries(serialized.targetConfigurations).reduce((map, [key, value]) => {
|
|
944
|
+
const identifier = parseInt(key, 10);
|
|
1000
945
|
map.set(identifier, value);
|
|
1001
946
|
return map;
|
|
1002
947
|
}, new Map());
|
|
1003
948
|
this.updatedTargetConfiguration();
|
|
1004
|
-
}
|
|
949
|
+
}
|
|
1005
950
|
/**
|
|
1006
951
|
* @private
|
|
1007
952
|
*/
|
|
1008
|
-
|
|
953
|
+
setupStateChangeDelegate(delegate) {
|
|
1009
954
|
this.stateChangeDelegate = delegate;
|
|
1010
|
-
};
|
|
1011
|
-
return RemoteController;
|
|
1012
|
-
}(events_1.EventEmitter));
|
|
1013
|
-
exports.RemoteController = RemoteController;
|
|
1014
|
-
// noinspection JSUnusedGlobalSymbols
|
|
1015
|
-
/**
|
|
1016
|
-
* @deprecated - only there for backwards compatibility, please use {@link RemoteController} directly
|
|
1017
|
-
* @group Apple TV Remote
|
|
1018
|
-
*/
|
|
1019
|
-
var HomeKitRemoteController = /** @class */ (function (_super) {
|
|
1020
|
-
tslib_1.__extends(HomeKitRemoteController, _super);
|
|
1021
|
-
function HomeKitRemoteController() {
|
|
1022
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
1023
955
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
exports.HomeKitRemoteController = HomeKitRemoteController;
|
|
956
|
+
}
|
|
957
|
+
exports.RemoteController = RemoteController;
|
|
1027
958
|
/**
|
|
1028
959
|
* @group Apple TV Remote
|
|
1029
960
|
*/
|
|
@@ -1036,44 +967,47 @@ var SiriAudioSessionEvents;
|
|
|
1036
967
|
* @group Apple TV Remote
|
|
1037
968
|
*/
|
|
1038
969
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
970
|
+
class SiriAudioSession extends events_1.EventEmitter {
|
|
971
|
+
connection;
|
|
972
|
+
selectedAudioConfiguration;
|
|
973
|
+
producer;
|
|
974
|
+
producerRunning = false; // indicates if the producer is running
|
|
975
|
+
producerTimer; // producer has a 3s timeout to produce the first frame, otherwise transmission will be cancelled
|
|
976
|
+
/**
|
|
977
|
+
* @private file private API
|
|
978
|
+
*/
|
|
979
|
+
state = 0 /* SiriAudioSessionState.STARTING */;
|
|
980
|
+
streamId; // present when state >= SENDING
|
|
981
|
+
endOfStream = false;
|
|
982
|
+
audioFrameQueue = [];
|
|
983
|
+
maxQueueSize = 1024;
|
|
984
|
+
sequenceNumber = 0;
|
|
985
|
+
closeListener;
|
|
986
|
+
constructor(connection, selectedAudioConfiguration, producerConstructor,
|
|
1042
987
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types,@typescript-eslint/no-explicit-any
|
|
1043
988
|
producerOptions) {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
_this.state = 0 /* SiriAudioSessionState.STARTING */;
|
|
1050
|
-
_this.endOfStream = false;
|
|
1051
|
-
_this.audioFrameQueue = [];
|
|
1052
|
-
_this.maxQueueSize = 1024;
|
|
1053
|
-
_this.sequenceNumber = 0;
|
|
1054
|
-
_this.connection = connection;
|
|
1055
|
-
_this.selectedAudioConfiguration = selectedAudioConfiguration;
|
|
1056
|
-
_this.producer = new producerConstructor(_this.handleSiriAudioFrame.bind(_this), _this.handleProducerError.bind(_this), producerOptions);
|
|
1057
|
-
_this.connection.on("closed" /* DataStreamConnectionEvent.CLOSED */, _this.closeListener = _this.handleDataStreamConnectionClosed.bind(_this));
|
|
1058
|
-
return _this;
|
|
989
|
+
super();
|
|
990
|
+
this.connection = connection;
|
|
991
|
+
this.selectedAudioConfiguration = selectedAudioConfiguration;
|
|
992
|
+
this.producer = new producerConstructor(this.handleSiriAudioFrame.bind(this), this.handleProducerError.bind(this), producerOptions);
|
|
993
|
+
this.connection.on("closed" /* DataStreamConnectionEvent.CLOSED */, this.closeListener = this.handleDataStreamConnectionClosed.bind(this));
|
|
1059
994
|
}
|
|
1060
995
|
/**
|
|
1061
996
|
* Called when siri button is pressed
|
|
1062
997
|
*/
|
|
1063
|
-
|
|
1064
|
-
var _this = this;
|
|
998
|
+
start() {
|
|
1065
999
|
debug("Sending request to start siri audio stream");
|
|
1066
1000
|
// opening dataSend
|
|
1067
1001
|
this.connection.sendRequest("dataSend" /* Protocols.DATA_SEND */, "open" /* Topics.OPEN */, {
|
|
1068
1002
|
target: "controller",
|
|
1069
1003
|
type: "audio.siri",
|
|
1070
|
-
},
|
|
1071
|
-
if (
|
|
1004
|
+
}, (error, status, message) => {
|
|
1005
|
+
if (this.state === 3 /* SiriAudioSessionState.CLOSED */) {
|
|
1072
1006
|
debug("Ignoring dataSend open response as the session is already closed");
|
|
1073
1007
|
return;
|
|
1074
1008
|
}
|
|
1075
|
-
assert_1.default.strictEqual(
|
|
1076
|
-
|
|
1009
|
+
assert_1.default.strictEqual(this.state, 0 /* SiriAudioSessionState.STARTING */);
|
|
1010
|
+
this.state = 1 /* SiriAudioSessionState.SENDING */;
|
|
1077
1011
|
if (error || status) {
|
|
1078
1012
|
if (error) { // errors get produced by hap-nodejs
|
|
1079
1013
|
debug("Error occurred trying to start siri audio stream: %s", error.message);
|
|
@@ -1081,30 +1015,30 @@ var SiriAudioSession = /** @class */ (function (_super) {
|
|
|
1081
1015
|
else if (status) { // status codes are those returned by the hds response
|
|
1082
1016
|
debug("Controller responded with non-zero status code: %s", datastream_1.HDSStatus[status]);
|
|
1083
1017
|
}
|
|
1084
|
-
|
|
1018
|
+
this.closed();
|
|
1085
1019
|
}
|
|
1086
1020
|
else {
|
|
1087
|
-
|
|
1088
|
-
if (!
|
|
1089
|
-
|
|
1021
|
+
this.streamId = message.streamId;
|
|
1022
|
+
if (!this.producerRunning) { // audio producer errored in the meantime
|
|
1023
|
+
this.sendDataSendCloseEvent(3 /* HDSProtocolSpecificErrorReason.CANCELLED */);
|
|
1090
1024
|
}
|
|
1091
1025
|
else {
|
|
1092
|
-
debug("Successfully setup siri audio stream with streamId %d",
|
|
1026
|
+
debug("Successfully setup siri audio stream with streamId %d", this.streamId);
|
|
1093
1027
|
}
|
|
1094
1028
|
}
|
|
1095
1029
|
});
|
|
1096
1030
|
this.startAudioProducer(); // start audio producer and queue frames in the meantime
|
|
1097
|
-
}
|
|
1031
|
+
}
|
|
1098
1032
|
/**
|
|
1099
1033
|
* @returns if the audio session is closing
|
|
1100
1034
|
*/
|
|
1101
|
-
|
|
1035
|
+
isClosing() {
|
|
1102
1036
|
return this.state >= 2 /* SiriAudioSessionState.CLOSING */;
|
|
1103
|
-
}
|
|
1037
|
+
}
|
|
1104
1038
|
/**
|
|
1105
1039
|
* Called when siri button is released (or active identifier is changed to another device)
|
|
1106
1040
|
*/
|
|
1107
|
-
|
|
1041
|
+
stop() {
|
|
1108
1042
|
(0, assert_1.default)(this.state <= 1 /* SiriAudioSessionState.SENDING */, "state was higher than SENDING");
|
|
1109
1043
|
debug("Stopping siri audio stream with streamId %d", this.streamId);
|
|
1110
1044
|
this.endOfStream = true; // mark as endOfStream
|
|
@@ -1116,28 +1050,26 @@ var SiriAudioSession = /** @class */ (function (_super) {
|
|
|
1116
1050
|
else { // if state is not SENDING (aka state is STARTING) the callback for DATA_SEND OPEN did not yet return (or never will)
|
|
1117
1051
|
this.closed();
|
|
1118
1052
|
}
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
var _this = this;
|
|
1053
|
+
}
|
|
1054
|
+
startAudioProducer() {
|
|
1122
1055
|
this.producer.startAudioProduction(this.selectedAudioConfiguration);
|
|
1123
1056
|
this.producerRunning = true;
|
|
1124
|
-
this.producerTimer = setTimeout(
|
|
1125
|
-
debug("Didn't receive any frames from audio producer for stream with streamId %s. Canceling the stream now.",
|
|
1126
|
-
|
|
1127
|
-
|
|
1057
|
+
this.producerTimer = setTimeout(() => {
|
|
1058
|
+
debug("Didn't receive any frames from audio producer for stream with streamId %s. Canceling the stream now.", this.streamId);
|
|
1059
|
+
this.producerTimer = undefined;
|
|
1060
|
+
this.handleProducerError(3 /* HDSProtocolSpecificErrorReason.CANCELLED */);
|
|
1128
1061
|
}, 3000);
|
|
1129
1062
|
this.producerTimer.unref();
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1063
|
+
}
|
|
1064
|
+
stopAudioProducer() {
|
|
1132
1065
|
this.producer.stopAudioProduction();
|
|
1133
1066
|
this.producerRunning = false;
|
|
1134
1067
|
if (this.producerTimer) {
|
|
1135
1068
|
clearTimeout(this.producerTimer);
|
|
1136
1069
|
this.producerTimer = undefined;
|
|
1137
1070
|
}
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
var _this = this;
|
|
1071
|
+
}
|
|
1072
|
+
handleSiriAudioFrame(frame) {
|
|
1141
1073
|
if (this.state >= 2 /* SiriAudioSessionState.CLOSING */) {
|
|
1142
1074
|
return;
|
|
1143
1075
|
}
|
|
@@ -1151,44 +1083,38 @@ var SiriAudioSession = /** @class */ (function (_super) {
|
|
|
1151
1083
|
if (this.state !== 1 /* SiriAudioSessionState.SENDING */) { // dataSend isn't open yet
|
|
1152
1084
|
return;
|
|
1153
1085
|
}
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
queued.forEach(
|
|
1158
|
-
|
|
1086
|
+
let queued;
|
|
1087
|
+
while ((queued = this.popSome()) !== null) { // send packets
|
|
1088
|
+
const packets = [];
|
|
1089
|
+
queued.forEach(frame => {
|
|
1090
|
+
const packetData = {
|
|
1159
1091
|
data: frame.data,
|
|
1160
1092
|
metadata: {
|
|
1161
1093
|
rms: new datastream_1.Float32(frame.rms),
|
|
1162
|
-
sequenceNumber: new datastream_1.Int64(
|
|
1094
|
+
sequenceNumber: new datastream_1.Int64(this.sequenceNumber++),
|
|
1163
1095
|
},
|
|
1164
1096
|
};
|
|
1165
1097
|
packets.push(packetData);
|
|
1166
1098
|
});
|
|
1167
|
-
|
|
1099
|
+
const message = {
|
|
1168
1100
|
packets: packets,
|
|
1169
|
-
streamId: new datastream_1.Int64(
|
|
1170
|
-
endOfStream:
|
|
1101
|
+
streamId: new datastream_1.Int64(this.streamId),
|
|
1102
|
+
endOfStream: this.endOfStream,
|
|
1171
1103
|
};
|
|
1172
1104
|
try {
|
|
1173
|
-
|
|
1105
|
+
this.connection.sendEvent("dataSend" /* Protocols.DATA_SEND */, "data" /* Topics.DATA */, message);
|
|
1174
1106
|
}
|
|
1175
1107
|
catch (error) {
|
|
1176
1108
|
debug("Error occurred when trying to send audio frame of hds connection: %s", error.message);
|
|
1177
|
-
|
|
1178
|
-
|
|
1109
|
+
this.stopAudioProducer();
|
|
1110
|
+
this.closed();
|
|
1179
1111
|
}
|
|
1180
|
-
if (
|
|
1181
|
-
|
|
1112
|
+
if (this.endOfStream) {
|
|
1113
|
+
break; // popSome() returns empty list if endOfStream=true
|
|
1182
1114
|
}
|
|
1183
|
-
};
|
|
1184
|
-
var this_1 = this;
|
|
1185
|
-
while ((queued = this.popSome()) !== null) {
|
|
1186
|
-
var state_1 = _loop_1();
|
|
1187
|
-
if (state_1 === "break")
|
|
1188
|
-
break;
|
|
1189
1115
|
}
|
|
1190
|
-
}
|
|
1191
|
-
|
|
1116
|
+
}
|
|
1117
|
+
handleProducerError(error) {
|
|
1192
1118
|
if (this.state >= 2 /* SiriAudioSessionState.CLOSING */) {
|
|
1193
1119
|
return;
|
|
1194
1120
|
}
|
|
@@ -1196,21 +1122,21 @@ var SiriAudioSession = /** @class */ (function (_super) {
|
|
|
1196
1122
|
if (this.state === 1 /* SiriAudioSessionState.SENDING */) { // if state is less than sending dataSend isn't open (yet)
|
|
1197
1123
|
this.sendDataSendCloseEvent(error); // cancel submission
|
|
1198
1124
|
}
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1125
|
+
}
|
|
1126
|
+
handleDataSendAckEvent(endOfStream) {
|
|
1201
1127
|
assert_1.default.strictEqual(endOfStream, true);
|
|
1202
1128
|
debug("Received acknowledgment for siri audio stream with streamId %s, closing it now", this.streamId);
|
|
1203
1129
|
this.sendDataSendCloseEvent(0 /* HDSProtocolSpecificErrorReason.NORMAL */);
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1130
|
+
}
|
|
1131
|
+
handleDataSendCloseEvent(reason) {
|
|
1206
1132
|
// @ts-expect-error: forceConsistentCasingInFileNames compiler option
|
|
1207
1133
|
debug("Received close event from controller with reason %s for stream with streamId %s", datastream_1.HDSProtocolSpecificErrorReason[reason], this.streamId);
|
|
1208
1134
|
if (this.state <= 1 /* SiriAudioSessionState.SENDING */) {
|
|
1209
1135
|
this.stopAudioProducer();
|
|
1210
1136
|
}
|
|
1211
1137
|
this.closed();
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1138
|
+
}
|
|
1139
|
+
sendDataSendCloseEvent(reason) {
|
|
1214
1140
|
(0, assert_1.default)(this.state >= 1 /* SiriAudioSessionState.SENDING */, "state was less than SENDING");
|
|
1215
1141
|
(0, assert_1.default)(this.state <= 2 /* SiriAudioSessionState.CLOSING */, "state was higher than CLOSING");
|
|
1216
1142
|
this.connection.sendEvent("dataSend" /* Protocols.DATA_SEND */, "close" /* Topics.CLOSE */, {
|
|
@@ -1218,36 +1144,35 @@ var SiriAudioSession = /** @class */ (function (_super) {
|
|
|
1218
1144
|
reason: new datastream_1.Int64(reason),
|
|
1219
1145
|
});
|
|
1220
1146
|
this.closed();
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1147
|
+
}
|
|
1148
|
+
handleDataStreamConnectionClosed() {
|
|
1223
1149
|
debug("Closing audio session with streamId %d", this.streamId);
|
|
1224
1150
|
if (this.state <= 1 /* SiriAudioSessionState.SENDING */) {
|
|
1225
1151
|
this.stopAudioProducer();
|
|
1226
1152
|
}
|
|
1227
1153
|
this.closed();
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1154
|
+
}
|
|
1155
|
+
closed() {
|
|
1156
|
+
const lastState = this.state;
|
|
1231
1157
|
this.state = 3 /* SiriAudioSessionState.CLOSED */;
|
|
1232
1158
|
if (lastState !== 3 /* SiriAudioSessionState.CLOSED */) {
|
|
1233
1159
|
this.emit("close" /* SiriAudioSessionEvents.CLOSE */);
|
|
1234
1160
|
this.connection.removeListener("closed" /* DataStreamConnectionEvent.CLOSED */, this.closeListener);
|
|
1235
1161
|
}
|
|
1236
1162
|
this.removeAllListeners();
|
|
1237
|
-
}
|
|
1238
|
-
|
|
1163
|
+
}
|
|
1164
|
+
popSome() {
|
|
1239
1165
|
if (this.audioFrameQueue.length < 5 && !this.endOfStream) {
|
|
1240
1166
|
return null;
|
|
1241
1167
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
for (
|
|
1245
|
-
|
|
1168
|
+
const size = Math.min(this.audioFrameQueue.length, 5); // 5 frames per hap packet seems fine
|
|
1169
|
+
const result = [];
|
|
1170
|
+
for (let i = 0; i < size; i++) {
|
|
1171
|
+
const element = this.audioFrameQueue.shift(); // removes first element
|
|
1246
1172
|
result.push(element);
|
|
1247
1173
|
}
|
|
1248
1174
|
return result;
|
|
1249
|
-
}
|
|
1250
|
-
|
|
1251
|
-
}(events_1.EventEmitter));
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1252
1177
|
exports.SiriAudioSession = SiriAudioSession;
|
|
1253
1178
|
//# sourceMappingURL=RemoteController.js.map
|