node-red-contrib-tts-ultimate 1.0.43 → 1.0.46
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/CHANGELOG.md +14 -0
- package/README.md +11 -7
- package/package.json +1 -1
- package/ttsultimate/ttsultimate-config.js +1 -1
- package/ttsultimate/ttsultimate.html +31 -14
- package/ttsultimate/ttsultimate.js +99 -57
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.paypal.me/techtoday)
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
<p>
|
|
7
|
+
<b>Version 1.0.46</b> Mai 2022<br/>
|
|
8
|
+
- Fixed a compatibility issue with Node 18, where a breaking change has been introduced.<br/>
|
|
9
|
+
</p>
|
|
10
|
+
<p>
|
|
11
|
+
<b>Version 1.0.45</b> April 2022<br/>
|
|
12
|
+
- NEW: Additional players now resumes the queue as well (previously, only the main player was doing so).<br/>
|
|
13
|
+
</p>
|
|
14
|
+
<p>
|
|
15
|
+
<b>Version 1.0.44</b> April 2022<br/>
|
|
16
|
+
- NEW: you can now adjust the additional player's volume, adapting it to the main sonos player volume. This is useful in case you've some recessed speakers, "speaking" too low or some too near speakers, "speaking" too high. You can adapt the volume in the config window or dinamically via msg input.<br/>
|
|
17
|
+
- Updated the README.<br/>
|
|
18
|
+
</p>
|
|
5
19
|
<p>
|
|
6
20
|
<b>Version 1.0.43</b> March 2022<br/>
|
|
7
21
|
- Simplified the configuration by auto discover some IP.<br/>
|
package/README.md
CHANGED
|
@@ -169,7 +169,8 @@ Select your Sonos primary player. (It's strongly suggested to set a fixed IP for
|
|
|
169
169
|
It's possibile to group players, so your announcement can be played on all selected players. For this to happen, you need to select your primary coordinator player. All other players will be then controlled by this coordinator.
|
|
170
170
|
|
|
171
171
|
**Additional Players** <br/>
|
|
172
|
-
Here you can add all additional players that will be grouped toghether to the *Main Sonos Player* coordinator group. You can add a player using the "ADD" button, below the list
|
|
172
|
+
Here you can add all additional players that will be grouped toghether to the *Main Sonos Player* coordinator group. You can add a player using the "ADD" button, below the list.<br/>
|
|
173
|
+
For each additional player, you can adjust their volume, based on the **Main Sonos Player** volume -+100.
|
|
173
174
|
|
|
174
175
|
|
|
175
176
|
## INPUT MESSAGES TO THE NODE <br/>
|
|
@@ -287,7 +288,9 @@ The setting is retained until the node receives another msg.setConfig or until n
|
|
|
287
288
|
|
|
288
289
|
> **property setPlayerGroupArray**<br/>
|
|
289
290
|
Sets the array of players beloging to the group, if any.<br/>
|
|
290
|
-
|
|
291
|
+
You can also specify the volume variation from the main volume player, to adapt the additional player's perceived volume to the main sonos player volume.<br/>
|
|
292
|
+
For example, if you have a speaker mounted in celiling, having less perceived volume, you can "push" the volume up, to match the whole perceived volume. Just add **#** after the IP and a number from -100 to 100 to subtract or add volume ***compared to the main sonos volume***. For example, if the sonos main player volume is 40, you can push this celing speaker's volume to further 10, so it'll have the real volume of 50. See below, the example.<br/>
|
|
293
|
+
Note: Even if you have only one additional player, you need to put it into an array.
|
|
291
294
|
|
|
292
295
|
```js
|
|
293
296
|
// Set main player IP
|
|
@@ -300,14 +303,15 @@ return msg;
|
|
|
300
303
|
```
|
|
301
304
|
|
|
302
305
|
```js
|
|
303
|
-
// Set player IP and additional players
|
|
306
|
+
// Set player IP and additional players with their optional adapted volume, relative to the main sonos player volume.
|
|
307
|
+
// You can specify the aditional player's volume adaptation
|
|
304
308
|
// The setting is retained until the node receives another msg.setConfig or until node-red is restarted.
|
|
305
309
|
var config= {
|
|
306
310
|
setMainPlayerIP:"192.168.1.109",
|
|
307
311
|
setPlayerGroupArray:[
|
|
308
|
-
"192.168.1.110",
|
|
309
|
-
"192.168.1.111",
|
|
310
|
-
"192.168.1.112"
|
|
312
|
+
"192.168.1.110", // This additional player will use the same volume as the main sonos player.
|
|
313
|
+
"192.168.1.111#-10", // This additional player will use the main sonos player's volume, minus 10.
|
|
314
|
+
"192.168.1.112#20" // This additional player will use the main sonos player's volume, plus 20.
|
|
311
315
|
]
|
|
312
316
|
};
|
|
313
317
|
msg.setConfig = config;
|
|
@@ -315,7 +319,7 @@ return msg;
|
|
|
315
319
|
```
|
|
316
320
|
|
|
317
321
|
```js
|
|
318
|
-
// If you have only one additional player
|
|
322
|
+
// If you have only one additional player, without setting their adjusted volume.
|
|
319
323
|
// The setting is retained until the node receives another msg.setConfig or until node-red is restarted.
|
|
320
324
|
var config= {
|
|
321
325
|
setMainPlayerIP:"192.168.1.109",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-tts-ultimate",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.46",
|
|
4
4
|
"description": "Transforms the text in speech and hear it using Sonos player or generate an audio file to be used with third parties nodes. Works with voices from Amazon, Google (without credentials as well), Microsoft TTS Azure, or your own voice. You can also only create a TTS file to be read by third party nodes. Update of the popular SonosPollyTTS node.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -229,7 +229,7 @@ module.exports = function (RED) {
|
|
|
229
229
|
} else {
|
|
230
230
|
var sAddresses = "";
|
|
231
231
|
oiFaces[ifname].forEach(function (iface) {
|
|
232
|
-
if (iface.internal == false && iface.family
|
|
232
|
+
if (iface.internal == false && iface.family.toString().includes("4")) sAddresses = iface.address;
|
|
233
233
|
});
|
|
234
234
|
if (sAddresses !== "") jListInterfaces.push({ name: ifname, address: sAddresses });
|
|
235
235
|
}
|
|
@@ -402,16 +402,32 @@
|
|
|
402
402
|
//#region ADDITIONAL PLAYERS
|
|
403
403
|
// 20/03/2020 ADDITIONAL PLAYERS
|
|
404
404
|
// ##########################################################
|
|
405
|
-
var previousValueType = { value: "prev", label: this._("switch.previous"), hasValue: false };
|
|
405
|
+
//var previousValueType = { value: "prev", label: this._("switch.previous"), hasValue: false };
|
|
406
|
+
|
|
407
|
+
// Add Selectbox with the volume for the additional players
|
|
408
|
+
function addAdditionalPlayerVolumeUI(row, _currentVolume = 0) {
|
|
409
|
+
let oAdjustVolume = $('<select/>', { class: "rowRulePlayerHostAdjustVolume", type: "text", style: "width:200px; margin-left: 5px; text-align: left;" }).appendTo(row);
|
|
410
|
+
for (let index = -100; index < 100; index += 5) {
|
|
411
|
+
let sTesto = "";
|
|
412
|
+
if (index === 0) sTesto = "Same volume as Main Sonos Player";
|
|
413
|
+
if (index < 0) sTesto = "Decrease volume by " + Math.abs(index) ;
|
|
414
|
+
if (index > 0) sTesto = "Increase volume by " + index;
|
|
415
|
+
oAdjustVolume.append($("<option></option>")
|
|
416
|
+
.attr("value", index)
|
|
417
|
+
.text(sTesto)
|
|
418
|
+
)
|
|
419
|
+
}
|
|
420
|
+
oAdjustVolume.val(_currentVolume);
|
|
421
|
+
}
|
|
406
422
|
function resizeRule(rule) { }
|
|
423
|
+
|
|
407
424
|
$("#node-input-rule-container").css('min-height', '150px').css('min-width', '450px').editableList({
|
|
408
425
|
addItem: function (container, i, opt) { // row, index, data
|
|
409
|
-
// opt.r is: { topic: rowRuleTopic, devicename: rowRuleDeviceName, dpt:rowRuleDPT, send: rowRuleSend}
|
|
410
426
|
|
|
411
427
|
if (!opt.hasOwnProperty('r')) {
|
|
412
428
|
opt.r = {};
|
|
413
429
|
}
|
|
414
|
-
|
|
430
|
+
let rule = opt.r;
|
|
415
431
|
if (!opt.hasOwnProperty('i')) {
|
|
416
432
|
opt._i = Math.floor((0x99999 - 0x10000) * Math.random()).toString();
|
|
417
433
|
}
|
|
@@ -422,8 +438,7 @@
|
|
|
422
438
|
|
|
423
439
|
|
|
424
440
|
var row = $('<div class="form-row"/>').appendTo(container);
|
|
425
|
-
var oPlayer = $('<label>Discovering.... wait...</label>', { class: "rowRulePlayerHost", type: "text", style: "width:
|
|
426
|
-
|
|
441
|
+
var oPlayer = $('<label>Discovering.... wait...</label>', { class: "rowRulePlayerHost", type: "text", style: "width:200px; margin-left: 5px; text-align: left;" }).appendTo(row);
|
|
427
442
|
oPlayer.on("change", function () {
|
|
428
443
|
resizeRule(container);
|
|
429
444
|
});
|
|
@@ -432,16 +447,18 @@
|
|
|
432
447
|
if (typeof data === "string" && data == "ERRORDISCOVERY") { // 10/04/2020 if error in discovery, fallback to manual IP input
|
|
433
448
|
// Transform the dropdown to a simple input
|
|
434
449
|
oPlayer.remove();
|
|
435
|
-
oPlayer = $('<input/>', { class: "rowRulePlayerHost", type: "text", style: "width:
|
|
450
|
+
oPlayer = $('<input/>', { class: "rowRulePlayerHost", type: "text", style: "width:200px; margin-left: 5px; text-align: left;" }).appendTo(row);
|
|
451
|
+
addAdditionalPlayerVolumeUI(row, rule.hostVolumeAdjust);
|
|
436
452
|
} else {
|
|
437
453
|
oPlayer.remove();
|
|
438
|
-
oPlayer = $('<select/>', { class: "rowRulePlayerHost", type: "text", style: "width:
|
|
454
|
+
oPlayer = $('<select/>', { class: "rowRulePlayerHost", type: "text", style: "width:200px; margin-left: 5px; text-align: left;" }).appendTo(row);
|
|
439
455
|
data.sort().forEach(oGroup => {
|
|
440
456
|
oPlayer.append($("<option></option>")
|
|
441
457
|
.attr("value", oGroup.host)
|
|
442
458
|
.text(oGroup.name + " (" + oGroup.host + ")")
|
|
443
459
|
)
|
|
444
460
|
});
|
|
461
|
+
addAdditionalPlayerVolumeUI(row, rule.hostVolumeAdjust);
|
|
445
462
|
}
|
|
446
463
|
oPlayer.val(rule.host);
|
|
447
464
|
});
|
|
@@ -460,7 +477,7 @@
|
|
|
460
477
|
|
|
461
478
|
// 20/03/2020 For each rule, create a row
|
|
462
479
|
for (var i = 0; i < this.rules.length; i++) {
|
|
463
|
-
|
|
480
|
+
let rule = this.rules[i];
|
|
464
481
|
$("#node-input-rule-container").editableList('addItem', { r: rule, i: i });
|
|
465
482
|
}
|
|
466
483
|
// ##########################################################
|
|
@@ -469,14 +486,14 @@
|
|
|
469
486
|
node.refreshHailingList();
|
|
470
487
|
|
|
471
488
|
}, oneditsave: function () {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
var rules = $("#node-input-rule-container").editableList('items');
|
|
489
|
+
let node = this;
|
|
490
|
+
let rules = $("#node-input-rule-container").editableList('items');
|
|
475
491
|
node.rules = [];
|
|
476
492
|
rules.each(function (i) {
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
493
|
+
let rule = $(this);
|
|
494
|
+
let rowRulePlayerHost = rule.find(".rowRulePlayerHost").val();
|
|
495
|
+
let rowRulePlayerHostAdjustVolume = rule.find(".rowRulePlayerHostAdjustVolume").val();
|
|
496
|
+
node.rules.push({ host: rowRulePlayerHost, hostVolumeAdjust: rowRulePlayerHostAdjustVolume });
|
|
480
497
|
});
|
|
481
498
|
this.propertyType = $("#node-input-property").typedInput('type');
|
|
482
499
|
},
|
|
@@ -95,12 +95,12 @@ module.exports = function (RED) {
|
|
|
95
95
|
|
|
96
96
|
//#region ASYNC DECLARATIONS
|
|
97
97
|
// 30/12/2020 we are at the end of this crazy 2020
|
|
98
|
-
function getMusicQueue() {
|
|
98
|
+
function getMusicQueue(_oPlayer = node.SonosClient) {
|
|
99
99
|
return new Promise(function (resolve, reject) {
|
|
100
100
|
var oRet = null;
|
|
101
|
-
|
|
101
|
+
_oPlayer.currentTrack().then(track => {
|
|
102
102
|
oRet = track;// .queuePosition || 1; // Get the current track in the queue.
|
|
103
|
-
|
|
103
|
+
_oPlayer.getCurrentState().then(state => {
|
|
104
104
|
// A music queue is playing and no TTS is speaking?
|
|
105
105
|
oRet.state = state;
|
|
106
106
|
resolve(oRet);
|
|
@@ -115,11 +115,12 @@ module.exports = function (RED) {
|
|
|
115
115
|
});
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
+
|
|
118
119
|
let iWaitAfterSync = 500;
|
|
119
120
|
// 24/08/2021 Sync wrapper
|
|
120
|
-
function PLAYSync(_toPlay) {
|
|
121
|
+
function PLAYSync(_toPlay, _oPlayer = node.SonosClient) {
|
|
121
122
|
return new Promise((resolve, reject) => {
|
|
122
|
-
|
|
123
|
+
_oPlayer.play(_toPlay).then(result => {
|
|
123
124
|
if (iWaitAfterSync > 2000) console.log("PLAYSYNC")
|
|
124
125
|
let t = setTimeout(() => {
|
|
125
126
|
resolve(true);
|
|
@@ -132,9 +133,9 @@ module.exports = function (RED) {
|
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
// 24/08/2021 Sync wrapper
|
|
135
|
-
function SEEKSync(_Position) {
|
|
136
|
+
function SEEKSync(_Position, _oPlayer = node.SonosClient) {
|
|
136
137
|
return new Promise((resolve, reject) => {
|
|
137
|
-
|
|
138
|
+
_oPlayer.seek(_Position).then(result => {
|
|
138
139
|
if (iWaitAfterSync > 2000) console.log("SEEKSync", _Position)
|
|
139
140
|
let t = setTimeout(() => {
|
|
140
141
|
resolve(true);
|
|
@@ -147,9 +148,9 @@ module.exports = function (RED) {
|
|
|
147
148
|
}
|
|
148
149
|
|
|
149
150
|
// 24/08/2021 Sync wrapper
|
|
150
|
-
function SELECTQUEUESync() {
|
|
151
|
+
function SELECTQUEUESync(_oPlayer = node.SonosClient) {
|
|
151
152
|
return new Promise((resolve, reject) => {
|
|
152
|
-
|
|
153
|
+
_oPlayer.selectQueue().then(result => {
|
|
153
154
|
if (iWaitAfterSync > 2000) console.log("SELECTQUEUESync")
|
|
154
155
|
try {
|
|
155
156
|
STOPSync(); // The SetQueue automatically starts playing, so i need to stop it now!
|
|
@@ -166,10 +167,10 @@ module.exports = function (RED) {
|
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
// 24/08/2021 Sync wrapper
|
|
169
|
-
function SELECTTRACKSync(
|
|
170
|
+
function SELECTTRACKSync(_queuePosition, _oPlayer = node.SonosClient) {
|
|
170
171
|
return new Promise((resolve, reject) => {
|
|
171
|
-
|
|
172
|
-
if (iWaitAfterSync > 2000) console.log("SELECTTRACKSync",
|
|
172
|
+
_oPlayer.selectTrack(_queuePosition).then(result => {
|
|
173
|
+
if (iWaitAfterSync > 2000) console.log("SELECTTRACKSync", _queuePosition)
|
|
173
174
|
let t = setTimeout(() => {
|
|
174
175
|
resolve(true);
|
|
175
176
|
}, iWaitAfterSync);
|
|
@@ -181,9 +182,9 @@ module.exports = function (RED) {
|
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
// 24/08/2021 Sync wrapper
|
|
184
|
-
function STOPSync() {
|
|
185
|
+
function STOPSync(_oPlayer = node.SonosClient) {
|
|
185
186
|
return new Promise((resolve, reject) => {
|
|
186
|
-
|
|
187
|
+
_oPlayer.stop().then(result => {
|
|
187
188
|
if (iWaitAfterSync > 2000) console.log("STOPSync")
|
|
188
189
|
let t = setTimeout(() => {
|
|
189
190
|
resolve(true);
|
|
@@ -196,9 +197,9 @@ module.exports = function (RED) {
|
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
// 24/08/2021 Sync wrapper
|
|
199
|
-
function GETVOLUMESync() {
|
|
200
|
+
function GETVOLUMESync(_oPlayer = node.SonosClient) {
|
|
200
201
|
return new Promise((resolve, reject) => {
|
|
201
|
-
|
|
202
|
+
_oPlayer.getVolume().then(volume => {
|
|
202
203
|
if (iWaitAfterSync > 2000) console.log("GETVOLUMESync", volume)
|
|
203
204
|
resolve(volume);
|
|
204
205
|
}).catch(err => {
|
|
@@ -209,9 +210,9 @@ module.exports = function (RED) {
|
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
// 24/08/2021 Sync wrapper
|
|
212
|
-
function SETVOLUMESync(_volume) {
|
|
213
|
+
function SETVOLUMESync(_volume, _oPlayer = node.SonosClient) {
|
|
213
214
|
return new Promise((resolve, reject) => {
|
|
214
|
-
|
|
215
|
+
_oPlayer.setVolume(_volume).then(result => {
|
|
215
216
|
if (iWaitAfterSync > 2000) console.log("SETVOLUMESync", _volume)
|
|
216
217
|
resolve(true);
|
|
217
218
|
}).catch(err => {
|
|
@@ -222,9 +223,9 @@ module.exports = function (RED) {
|
|
|
222
223
|
}
|
|
223
224
|
|
|
224
225
|
// 24/08/2021 Sync wrapper
|
|
225
|
-
function setAVTransportURISync(_Uri) {
|
|
226
|
+
function setAVTransportURISync(_Uri, _oPlayer = node.SonosClient) {
|
|
226
227
|
return new Promise((resolve, reject) => {
|
|
227
|
-
|
|
228
|
+
_oPlayer.setAVTransportURI(_Uri).then(volume => {
|
|
228
229
|
if (iWaitAfterSync > 2000) console.log("setAVTransportURISync", _Uri)
|
|
229
230
|
resolve(true);
|
|
230
231
|
}).catch(err => {
|
|
@@ -235,9 +236,9 @@ module.exports = function (RED) {
|
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
// 24/08/2021 Sync wrapper
|
|
238
|
-
function getCurrentStateSync() {
|
|
239
|
+
function getCurrentStateSync(_oPlayer = node.SonosClient) {
|
|
239
240
|
return new Promise((resolve, reject) => {
|
|
240
|
-
|
|
241
|
+
_oPlayer.getCurrentState().then(state => {
|
|
241
242
|
resolve(state);
|
|
242
243
|
}).catch(err => {
|
|
243
244
|
RED.log.error("ttsultimate: Error getCurrentStateSync: " + err.message);
|
|
@@ -247,9 +248,9 @@ module.exports = function (RED) {
|
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
// 21/10/2021 Sync wrapper
|
|
250
|
-
function GETMutedSync() {
|
|
251
|
+
function GETMutedSync(_oPlayer = node.SonosClient) {
|
|
251
252
|
return new Promise((resolve, reject) => {
|
|
252
|
-
|
|
253
|
+
_oPlayer.getMuted().then(state => {
|
|
253
254
|
resolve(state);
|
|
254
255
|
}).catch(err => {
|
|
255
256
|
RED.log.error("ttsultimate: Error GETMutedSync: " + err.message);
|
|
@@ -259,9 +260,9 @@ module.exports = function (RED) {
|
|
|
259
260
|
}
|
|
260
261
|
|
|
261
262
|
// 21/10/2021 Sync wrapper
|
|
262
|
-
function SETMutedSync(_muted) {
|
|
263
|
+
function SETMutedSync(_muted, _oPlayer = node.SonosClient) {
|
|
263
264
|
return new Promise((resolve, reject) => {
|
|
264
|
-
|
|
265
|
+
_oPlayer.setMuted(_muted).then(state => {
|
|
265
266
|
resolve(state);
|
|
266
267
|
}).catch(err => {
|
|
267
268
|
RED.log.error("ttsultimate: Error SETMutedSync: " + err.message);
|
|
@@ -283,15 +284,12 @@ module.exports = function (RED) {
|
|
|
283
284
|
}
|
|
284
285
|
// 30/03/2020 in the middle of coronavirus emergency. Group Speakers
|
|
285
286
|
for (let index = 0; index < node.oAdditionalSonosPlayers.length; index++) {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
} catch (error) {
|
|
290
|
-
RED.log.warn("ttsultimate: Error joining device " + error.message);
|
|
291
|
-
}
|
|
292
|
-
// 02/07/2021 Get the player's volume set by app, to be set again in ungroupspealers
|
|
287
|
+
let element = node.oAdditionalSonosPlayers[index].oPlayer;
|
|
288
|
+
|
|
289
|
+
// 02/07/2021 Get the additional's player's volume set by app and the current track, to be set again in ungroupspealers
|
|
293
290
|
try {
|
|
294
291
|
element.additionalPlayerPreviousVolumeSetByApp = await element.getVolume();
|
|
292
|
+
element.additionalPlayerCurrentTrack = await getMusicQueue(element);
|
|
295
293
|
} catch (error) {
|
|
296
294
|
RED.log.warn("ttsultimate: Error setting volume of joined device " + error.message);
|
|
297
295
|
}
|
|
@@ -301,6 +299,12 @@ module.exports = function (RED) {
|
|
|
301
299
|
} catch (error) {
|
|
302
300
|
RED.log.warn("ttsultimate: Error getMuted of joined device " + error.message);
|
|
303
301
|
}
|
|
302
|
+
|
|
303
|
+
try {
|
|
304
|
+
await element.joinGroup(node.sonosCoordinatorGroupName);
|
|
305
|
+
} catch (error) {
|
|
306
|
+
RED.log.warn("ttsultimate: Error joining device " + error.message);
|
|
307
|
+
}
|
|
304
308
|
};
|
|
305
309
|
}
|
|
306
310
|
|
|
@@ -322,7 +326,7 @@ module.exports = function (RED) {
|
|
|
322
326
|
}
|
|
323
327
|
|
|
324
328
|
for (let index = 0; index < node.oAdditionalSonosPlayers.length; index++) {
|
|
325
|
-
|
|
329
|
+
let element = node.oAdditionalSonosPlayers[index].oPlayer;
|
|
326
330
|
try {
|
|
327
331
|
await element.leaveGroup();
|
|
328
332
|
} catch (error) {
|
|
@@ -401,9 +405,10 @@ module.exports = function (RED) {
|
|
|
401
405
|
});
|
|
402
406
|
// Fill the node.oAdditionalSonosPlayers with all sonos object in the rules
|
|
403
407
|
for (let index = 0; index < node.rules.length; index++) {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
408
|
+
let element = node.rules[index]; // Rule row is {host:"192.168.1.12,hostVolumeAdjust:0}
|
|
409
|
+
// 12/04/2022 Create an object containing the addidtional player and the adapted volume
|
|
410
|
+
node.oAdditionalSonosPlayers.push({ oPlayer: new sonos.Sonos(element.host), hostVolumeAdjust: Number(element.hostVolumeAdjust) });
|
|
411
|
+
RED.log.info("ttsultimate: FOUND ADDITIONAL PLAYER " + element.host + " Adjusted volume: " + element.hostVolumeAdjust);
|
|
407
412
|
}
|
|
408
413
|
|
|
409
414
|
|
|
@@ -432,7 +437,7 @@ module.exports = function (RED) {
|
|
|
432
437
|
|
|
433
438
|
|
|
434
439
|
// 30/12/2020 Supergiovane resume queue for radio, queue music, TV in , line in etc.
|
|
435
|
-
async function resumeMusicQueue(_oTrack) {
|
|
440
|
+
async function resumeMusicQueue(_oTrack, _oPlayer = node.SonosClient) {
|
|
436
441
|
|
|
437
442
|
if (_oTrack !== null) {
|
|
438
443
|
// Do some checks on the track.
|
|
@@ -457,12 +462,13 @@ module.exports = function (RED) {
|
|
|
457
462
|
if (_oTrack.state === "playing") {
|
|
458
463
|
// 03/09/2021 Play if it was playing
|
|
459
464
|
try {
|
|
460
|
-
await PLAYSync(_oTrack.uri);
|
|
465
|
+
await PLAYSync(_oTrack.uri, _oPlayer);
|
|
461
466
|
} catch (error) {
|
|
462
467
|
return error;
|
|
463
468
|
}
|
|
464
469
|
try {
|
|
465
|
-
await
|
|
470
|
+
await delay(1000);
|
|
471
|
+
await SEEKSync(_oTrack.position, _oPlayer);
|
|
466
472
|
} catch (error) {
|
|
467
473
|
// Don't care
|
|
468
474
|
}
|
|
@@ -470,31 +476,33 @@ module.exports = function (RED) {
|
|
|
470
476
|
} else {
|
|
471
477
|
if (_oTrack.trackType === "musicqueue") { // This indicates that is an audio file or stream station
|
|
472
478
|
try {
|
|
473
|
-
await SELECTQUEUESync();
|
|
479
|
+
await SELECTQUEUESync(_oPlayer);
|
|
474
480
|
} catch (error) {
|
|
475
481
|
return error;
|
|
476
482
|
}
|
|
477
483
|
try {
|
|
478
|
-
await
|
|
484
|
+
await delay(1000);
|
|
485
|
+
await SELECTTRACKSync(_oTrack.queuePosition, _oPlayer);
|
|
479
486
|
} catch (error) {
|
|
480
487
|
return error;
|
|
481
488
|
}
|
|
482
489
|
try {
|
|
483
|
-
await
|
|
490
|
+
await delay(1000);
|
|
491
|
+
await SEEKSync(_oTrack.position, _oPlayer);
|
|
484
492
|
} catch (error) {
|
|
485
493
|
// Don't care
|
|
486
494
|
}
|
|
487
495
|
if (_oTrack.state === "playing") {
|
|
488
496
|
// 24/08/2021 Play if it was playing
|
|
489
497
|
try {
|
|
490
|
-
await PLAYSync();
|
|
498
|
+
await PLAYSync(_oPlayer);
|
|
491
499
|
} catch (error) {
|
|
492
500
|
return error;
|
|
493
501
|
}
|
|
494
502
|
} else {
|
|
495
503
|
/// 03/09/2021
|
|
496
504
|
try {
|
|
497
|
-
await STOPSync();
|
|
505
|
+
await STOPSync(_oPlayer);
|
|
498
506
|
} catch (error) {
|
|
499
507
|
return error;
|
|
500
508
|
}
|
|
@@ -503,7 +511,7 @@ module.exports = function (RED) {
|
|
|
503
511
|
// Line in, TV in, etc...
|
|
504
512
|
if (_oTrack.state === "playing") {
|
|
505
513
|
try {
|
|
506
|
-
await setAVTransportURISync(_oTrack.uri);
|
|
514
|
+
await setAVTransportURISync(_oTrack.uri, _oPlayer);
|
|
507
515
|
} catch (error) {
|
|
508
516
|
return error;
|
|
509
517
|
}
|
|
@@ -513,6 +521,7 @@ module.exports = function (RED) {
|
|
|
513
521
|
let t = setTimeout(() => { return true; }, 5000); // Wait some seconds
|
|
514
522
|
};
|
|
515
523
|
|
|
524
|
+
|
|
516
525
|
// Handle the queue
|
|
517
526
|
async function HandleQueue() {
|
|
518
527
|
node.bBusyPlayingQueue = true;
|
|
@@ -523,6 +532,7 @@ module.exports = function (RED) {
|
|
|
523
532
|
var oCurTrack = null;
|
|
524
533
|
try {
|
|
525
534
|
oCurTrack = await getMusicQueue();
|
|
535
|
+
// 19/04/2022 The current track of additional players is read in the groupSpeakerySync function
|
|
526
536
|
} catch (error) {
|
|
527
537
|
oCurTrack = null;
|
|
528
538
|
}
|
|
@@ -530,7 +540,7 @@ module.exports = function (RED) {
|
|
|
530
540
|
// 05/12/2020 Set "completed" to false and send it
|
|
531
541
|
node.msg.completed = false;
|
|
532
542
|
try {
|
|
533
|
-
await groupSpeakersSync(); // 20/03/2020 Group Speakers toghether
|
|
543
|
+
await groupSpeakersSync(); // 20/03/2020 Group Speakers toghether and reads each current track
|
|
534
544
|
} catch (error) {
|
|
535
545
|
// Don't care.
|
|
536
546
|
node.setNodeStatus({ fill: "red", shape: "ring", text: "Error grouping speakers: " + error.message });
|
|
@@ -655,21 +665,26 @@ module.exports = function (RED) {
|
|
|
655
665
|
|
|
656
666
|
// Set Volume
|
|
657
667
|
try {
|
|
658
|
-
let volTemp = 0
|
|
668
|
+
let volTemp = 0;
|
|
659
669
|
if (node.currentMSGbeingSpoken.hasOwnProperty("volume")) {
|
|
660
|
-
volTemp = node.currentMSGbeingSpoken.volume;
|
|
670
|
+
volTemp = Number(node.currentMSGbeingSpoken.volume);
|
|
661
671
|
} else {
|
|
662
|
-
volTemp = node.sSonosVolume;
|
|
672
|
+
volTemp = Number(node.sSonosVolume);
|
|
663
673
|
}
|
|
664
674
|
await SETVOLUMESync(volTemp);
|
|
665
675
|
if (node.unmuteIfMuted) await SETMutedSync(false); // 21/10/2021 Unmute
|
|
666
676
|
|
|
667
677
|
if (node.oAdditionalSonosPlayers.length > 0) {
|
|
668
|
-
// 05/07/2021 set the volume of additional
|
|
678
|
+
// 05/07/2021 set the volume of additional coordinators
|
|
669
679
|
for (let index = 0; index < node.oAdditionalSonosPlayers.length; index++) {
|
|
670
|
-
|
|
680
|
+
let element = node.oAdditionalSonosPlayers[index].oPlayer;
|
|
681
|
+
//node.oAdditionalSonosPlayers.push({ oPlayer: new sonos.Sonos(element.host), hostVolumeAdjust: element.hostVolumeAdjust });
|
|
671
682
|
try {
|
|
672
|
-
|
|
683
|
+
// 12/04/20222 Set the adjusted volume, based on the main player volume + the adjusted volume in %
|
|
684
|
+
let iAdjustedVol = Number(volTemp) + Number((node.oAdditionalSonosPlayers[index].hostVolumeAdjust || 0));
|
|
685
|
+
if (iAdjustedVol < 0) iAdjustedVol = 0;
|
|
686
|
+
if (iAdjustedVol > 100) iAdjustedVol = 100;
|
|
687
|
+
await element.setVolume(iAdjustedVol);
|
|
673
688
|
if (node.unmuteIfMuted) await element.setMuted(false); // 21/10/2021 Unmute
|
|
674
689
|
} catch (error) {
|
|
675
690
|
RED.log.error("ttsultimate: Handlequeue: Unable to set the volume on additional player " + error.message);
|
|
@@ -760,7 +775,7 @@ module.exports = function (RED) {
|
|
|
760
775
|
|
|
761
776
|
// Ungroup speaker
|
|
762
777
|
try {
|
|
763
|
-
await ungroupSpeakersSync();
|
|
778
|
+
await ungroupSpeakersSync(); // Ungroup speakers
|
|
764
779
|
} catch (error) {
|
|
765
780
|
// Don't care.
|
|
766
781
|
node.setNodeStatus({ fill: "red", shape: "ring", text: "Error ungrouping speakers: " + error.message });
|
|
@@ -782,6 +797,24 @@ module.exports = function (RED) {
|
|
|
782
797
|
node.setNodeStatus({ fill: 'red', shape: 'ring', text: "Error resuming queue: " + error.message });
|
|
783
798
|
}
|
|
784
799
|
|
|
800
|
+
|
|
801
|
+
// 19/04/2022 Resume music queue of additional players
|
|
802
|
+
for (let index = 0; index < node.oAdditionalSonosPlayers.length; index++) {
|
|
803
|
+
let addPlayer = node.oAdditionalSonosPlayers[index].oPlayer;
|
|
804
|
+
let trackAddPlayer = addPlayer.additionalPlayerCurrentTrack;
|
|
805
|
+
if (trackAddPlayer !== null) {
|
|
806
|
+
try {
|
|
807
|
+
await resumeMusicQueue(trackAddPlayer, addPlayer);
|
|
808
|
+
node.setNodeStatus({ fill: 'green', shape: 'ring', text: "Done resuming queue additional player " + addPlayer.host || "" });
|
|
809
|
+
} catch (error) {
|
|
810
|
+
// Dont care
|
|
811
|
+
RED.log.warn("ttsultimate: Error resuming music queue of additional player " + error.message + " " + addPlayer.host || "");
|
|
812
|
+
}
|
|
813
|
+
} else {
|
|
814
|
+
node.setNodeStatus({ fill: 'green', shape: 'ring', text: "No queue to resume for " + addPlayer.host || "" });
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
785
818
|
// Signal end playing
|
|
786
819
|
let t = setTimeout(() => {
|
|
787
820
|
node.msg.completed = true;
|
|
@@ -843,9 +876,18 @@ module.exports = function (RED) {
|
|
|
843
876
|
// Fill the node.oAdditionalSonosPlayers with all sonos IPs in the setPlayerGroupArray
|
|
844
877
|
node.oAdditionalSonosPlayers = [];
|
|
845
878
|
for (let index = 0; index < msg.setConfig.setPlayerGroupArray.length; index++) {
|
|
846
|
-
const
|
|
847
|
-
|
|
848
|
-
|
|
879
|
+
const sRow = msg.setConfig.setPlayerGroupArray[index];
|
|
880
|
+
let host = "";
|
|
881
|
+
let hostVolumeAdjust = 0;
|
|
882
|
+
if (sRow.includes("#")) {
|
|
883
|
+
host = sRow.split("#")[0];
|
|
884
|
+
hostVolumeAdjust = sRow.split("#")[1];
|
|
885
|
+
} else {
|
|
886
|
+
host = sRow;
|
|
887
|
+
}
|
|
888
|
+
//node.oAdditionalSonosPlayers.push({ oPlayer: new sonos.Sonos(element.host), hostVolumeAdjust: element.hostVolumeAdjust });
|
|
889
|
+
node.oAdditionalSonosPlayers.push({ oPlayer: new sonos.Sonos(host), hostVolumeAdjust: Number(hostVolumeAdjust) });
|
|
890
|
+
RED.log.info("ttsultimate: new group player set by msg: " + host + " adjusted volume: " + Number(hostVolumeAdjust));
|
|
849
891
|
}
|
|
850
892
|
};
|
|
851
893
|
};
|