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