Skip to content

Commit 98e24ff

Browse files
committed
Updating docs, getting DoricoRemote with latest websocket client changes
1 parent 5c03b5b commit 98e24ff

File tree

7 files changed

+165
-39
lines changed

7 files changed

+165
-39
lines changed

DoricoRemote.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ class DoricoRemote extends WebSocketClient {
99
this.handshakeDone = false;
1010
}
1111

12-
onOpen() {
12+
onOpen(resolve) {
13+
let savedMessageQueue = this.messageQueue;
14+
this.messageQueue = [];
15+
1316
this._sendHandshake();
1417

15-
super.onOpen();
18+
// this.messageQueue = savedMessageQueue;
19+
// savedMessageQueue = []
20+
21+
super.onOpen(resolve);
1622
}
1723

1824
_sendHandshake() {
@@ -26,10 +32,11 @@ class DoricoRemote extends WebSocketClient {
2632
message.sessionToken = this.sessionToken;
2733
}
2834

29-
this.send(message);
35+
super.send(message);
3036
}
3137

3238
_processHandshake(data) {
39+
console.log(data);
3340
if (data.message === 'sessiontoken' && data.sessionToken) {
3441
this.sessionToken = data.sessionToken;
3542
console.log(`Received sessiontoken: ${this.sessionToken} - completing handshake`);
@@ -39,7 +46,7 @@ class DoricoRemote extends WebSocketClient {
3946
sessionToken: this.sessionToken
4047
}
4148

42-
this.send(message);
49+
super.send(message);
4350
}
4451
else if (data.message === 'response' && data.code === 'kConnected') {
4552
console.log(`Handshake complete for ${this.appName}`);
@@ -48,17 +55,32 @@ class DoricoRemote extends WebSocketClient {
4855
}
4956
}
5057

51-
onMessage(data) {
58+
onMessage(event) {
59+
const data = JSON.parse(event.data);
60+
5261
if (!this.handshakeDone && data.message === 'sessiontoken') {
5362
this._processHandshake(data);
5463
}
5564

56-
super.onMessage(data);
65+
super.onMessage(event);
5766

5867
if (this.callbackAddress && this.callbackAddress.length > 0) {
5968
receive(this.callbackAddress, data)
6069
}
6170
}
71+
72+
async send(message) {
73+
if (!this.socket) {
74+
this.connect();
75+
}
76+
77+
try {
78+
await super.send(message);
79+
}
80+
catch (e) {
81+
console.error('caught error', e)
82+
}
83+
}
6284
}
6385

6486
module.exports = DoricoRemote;

README.md

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,78 @@ Once the session is running, pressing any of the buttons will initiate the hands
1818

1919
Enjoy!
2020

21-
## Adding Custom Buttons
21+
## Adding Custom Buttons (Sibelius)
2222

2323
1. Enable the `Editor` by selecting the 3 dots menu > Editor > Enabled (checked) OR by pressing Cmd/Ctrl + E
2424
2. Add a button by right clicking on the canvas > Add Widget > Basics > add button
25-
3. Set the following properties for the button:
26-
- `button`
27-
- `on`: enter one of:
28-
- (Sibelius) a comma-separated list of Command IDs
29-
- (Sibelius) a plugin name (executing the plugin's default Run() method) **
30-
- (Sibelius) a plugin JSON object to execute arbitrary plugin methods **
31-
- (Dorico) a Dorico JSON message or an array of Dorico JSON messages
32-
- `osc`
33-
- `address`: enter one of:
34-
- `/SibeliusConnect/command` if sending Command IDs
35-
- `/SibeliusConnect/plugin` if invoking a plugin **
36-
- `/SibeliusConnect` if sending a raw Sibelius Connect JSON message (per the [Sibelius Manuscript Reference Documentation](https://resources.avid.com/SupportFiles/Sibelius/2024.10/ManuScript_Language_Guide.pdf])) ***
37-
- `/DoricoRemote` if sending a request to Dorico
38-
- `send`: `localhost:8080`
39-
40-
_** NOTE: if executing Sibelius plugins, the plugin name **MUST** be added to the SibeliusConnect websocket instance in `customModule.js` BEFORE starting OpenStageControl, i.e.:_
25+
3. There are a variety of methods for sending commands to Sibelius (assuming `localhost` with default port `8080`):
4126

27+
| Method | `button > on` | `osc > address` | `osc > target` |
28+
| :-------------: | :---------------------------------- | :-------------: | :------------: |
29+
| Command(s) (explicit) | comma-separated list of Command IDs | `/sibelius/command` | `localhost:8080` |
30+
| Command(s) (implicit) | `command:Command1,Command2,etc...` | `/sibelius` | `localhost:8080` |
31+
| Plugin (explicit - simple)** | PluginName (executes default Run() method) | `/sibelius/plugin` | `localhost:8080` |
32+
| Plugin (explicit - advanced)** | PluginName,MethodName,arg1,"arg2",... | `/sibelius/plugin` | `localhost:8080` |
33+
| Plugin (implicit)** | `plugin:PluginName,MethodName,arg1,"Arg 2",...` | `/sibelius` | `localhost:8080` |
34+
| Plugin (JSON)** | An `InvokePlugin` JSON object (without `message` key) | `/sibelius` | `localhost:8080` |
35+
| Command or Plugin (raw JSON) | A raw SibeliusConnect JSON object | `/sibelius` | `localhost:8080` |
36+
37+
>_** NOTE: if executing Sibelius plugins, the plugin name **MUST** be added to the SibeliusConnect websocket instance in `customModule.js` BEFORE starting OpenStageControl, i.e.:_
4238
```javascript
43-
global.SibeliusConnect = new SibeliusConnect({ plugins: ['PositionRehearsalMarks'] })
39+
global.SibeliusConnect = new SibeliusConnect({ plugins: ['cmdutils'] })
4440
```
4541

42+
## Macros
43+
Macros can be sent via a variety of methods:
44+
- Commands/plugins can be combined into an array or semicolon-separated string. For example, [Bob Zawalich's **Add Wildcards Title Subtitle Composer Lyricist** macro](https://bobzawalich.com/wp-content/uploads/2021/08/Some-Current-Sibelius-Command-Macros.pdf)
45+
- Also set `osc > address: /sibelius` and `osc > target: localhost:8080`
46+
47+
`button > on` (as an array - can mix implicit command/plugin strings and raw SibeliusConnect JSON objects):
48+
49+
[
50+
"plugin:cmdutils,GoToFirstBar_cu",
51+
"plugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.title\"",
52+
"plugin:cmdutils,Add_Text_cu,\"\\$Title\\\"",
53+
"plugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.subtitle\"",
54+
"plugin:cmdutils,Add_Text_cu,\"\\$Subtitle\\\"",
55+
"plugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.composer\"",
56+
"plugin:cmdutils,Add_Text_cu,\"\\$Composer\\\"",
57+
"plugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.lyricist\"",
58+
"plugin:cmdutils,Add_Text_cu,\"\\$Lyricist\\\"",
59+
"command:goto_selection_start",
60+
"plugin:cmdutils,MessageBox_cu,\"Please fill in the Score Info fields for the title, subtitle, composer, and lyricist, then click the Ribbon Home tab.\"",
61+
"command:score_info"
62+
]
63+
64+
_NOTE: Some characters need to be escaped due to javascript syntax. Backslashes always need to be escaped (i.e. `\\` will result in `\` when the message is actually sent). Single quoted strings will automatically be converted to double quoted strings (with proper double quote escaping, as above)_
65+
66+
`button > on` (as a semicolon-separated string):
67+
68+
plugin:cmdutils,GoToFirstBar_cu;
69+
plugin:cmdutils,TextStyleDefaultForCommands_cu,"text.system.page_aligned.title";
70+
plugin:cmdutils,Add_Text_cu,"\$Title\";
71+
plugin:cmdutils,TextStyleDefaultForCommands_cu,"text.system.page_aligned.subtitle";
72+
plugin:cmdutils,Add_Text_cu,"\$Subtitle\";
73+
plugin:cmdutils,TextStyleDefaultForCommands_cu,"text.system.page_aligned.composer";
74+
plugin:cmdutils,Add_Text_cu,"\$Composer\";
75+
plugin:cmdutils,TextStyleDefaultForCommands_cu,"text.system.page_aligned.lyricist";
76+
plugin:cmdutils,Add_Text_cu,"\$Lyricist\";
77+
command:goto_selection_start;
78+
plugin:cmdutils,MessageBox_cu,"Please fill in the Score Info fields for the title, subtitle, composer, and lyricist, then click the Ribbon Home tab.";
79+
command:score_info
80+
81+
- Implicit AND Explicit commands/plugins can also be sent as a macro using the built-in `/SibeliusConnect` macro builder. This is done by setting the widget's:
82+
83+
`value > linkId: >>sibelius`
84+
85+
It has the following benefits:
86+
- Negates the need to set the widget's `osc > address` or `osc > target`
87+
- Ability to reference other widget's addresses that also send Sibelius Connect command/plugin mesages (i.e. `command:voice3;/filterRests`, where the `filterRests` widget sends its own command/plugin message)
88+
4689
## Additional Notes
4790
The `ws` NPM package is bundled with this custom module to negate the need for having NPM installed.
91+
92+
## Roadmap
93+
- [ ] Cleanup interface
94+
- [ ] Fix reconnect websocket issues
95+
- [ ] Allow other OSC apps to send websocket messages via the custom module

SibeliusConnect.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ class SibeliusConnect extends WebSocketClient {
5555
}
5656

5757
_processHandshake(data) {
58-
console.log(data)
5958
if (data.sessionToken) {
6059
this.sessionToken = data.sessionToken;
6160
console.log('Received sessionToken:', this.sessionToken);
@@ -116,7 +115,7 @@ class SibeliusConnect extends WebSocketClient {
116115
}
117116

118117
try {
119-
super.send(message);
118+
await super.send(message);
120119
}
121120
catch (e) {
122121
console.error('caught error', e)

WebSocketClient.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,22 +168,26 @@ class WebSocketClient extends EventEmitter {
168168

169169
if (id) {
170170
const responseEvent = `response:${id}`;
171-
const response = await new Promise((resolve, reject) => {
171+
const response = await new Promise((res, rej) => {
172172
const timeout = setTimeout(() => {
173-
this.off(responseEvent, resolve);
174-
reject(new Error(`Timeout waiting for response to message id: ${id}`));
173+
this.off(responseEvent, res);
174+
rej(new Error(`Timeout waiting for response to message id: ${id}`));
175175
}, this.responseTimeout);
176176

177177
this.once(responseEvent, (message) => {
178178
clearTimeout(timeout);
179-
resolve(message)
179+
res(message)
180180
});
181181
})
182182
resolve(response)
183183
}
184184
else {
185-
await new Promise((response) => this.once("message", response));
186-
resolve()
185+
try {
186+
await new Promise((response) => this.once("message", response));
187+
resolve()
188+
} catch(e) {
189+
console.error(e);
190+
}
187191
}
188192
}
189193
catch (error) {

customModule.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ module.exports = {
2424
}
2525

2626
if (address === '/sibelius' || path.dirname(address) === '/sibelius') {
27-
args.forEach(arg => {
27+
let newArgs = args
28+
if (args.length === 1 && args[0].value.indexOf(';') > -1) {
29+
newArgs = args[0].value.split(';').map(v => { return { type: 's', value: v.replace(/^\n|\n$/g, '').trim() } })
30+
}
31+
32+
newArgs.forEach(arg => {
2833
let addr = address
2934
arg = arg.value
3035

@@ -55,6 +60,7 @@ module.exports = {
5560

5661
global.SibeliusConnect.send(msg)
5762
})
63+
return;
5864
}
5965
else if (address === '/dorico') {
6066
args.forEach(arg => {

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
2-
"name": "osc-sibelius-connect",
3-
"version": "1.0.0",
2+
"name": "osc-websocket",
3+
"version": "0.1.0",
44
"description": "",
5-
"main": "sibelius-connect.js",
5+
"main": "customModule.js",
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1"
88
},

session.json

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,7 @@
13101310
},
13111311
{
13121312
"type": "button",
1313-
"top": 470,
1313+
"top": 550,
13141314
"left": 410,
13151315
"lock": false,
13161316
"id": "button_8",
@@ -1356,7 +1356,7 @@
13561356
},
13571357
{
13581358
"type": "button",
1359-
"top": 390,
1359+
"top": 470,
13601360
"left": 410,
13611361
"lock": false,
13621362
"id": "addWildcardsArr",
@@ -1392,6 +1392,7 @@
13921392
"plugin:cmdutils,Add_Text_cu,\"\\$Composer\\\"",
13931393
"plugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.lyricist\"",
13941394
"plugin:cmdutils,Add_Text_cu,\"\\$Lyricist\\\"",
1395+
"plugin:cmdutils,Add_Text_cu,\"$Lyricist\"",
13951396
"command:goto_selection_start",
13961397
"plugin:cmdutils,MessageBox_cu,\"Please fill in the Score Info fields for the title, subtitle, composer, and lyricist, then click the Ribbon Home tab.\"",
13971398
"command:score_info"
@@ -1415,7 +1416,7 @@
14151416
},
14161417
{
14171418
"type": "button",
1418-
"top": 530,
1419+
"top": 610,
14191420
"left": 410,
14201421
"lock": false,
14211422
"id": "button_7",
@@ -1458,6 +1459,52 @@
14581459
"bypass": false,
14591460
"onCreate": "",
14601461
"onValue": ""
1462+
},
1463+
{
1464+
"type": "button",
1465+
"top": 390,
1466+
"left": 410,
1467+
"lock": false,
1468+
"id": "addWildcardsServer",
1469+
"visible": true,
1470+
"interaction": true,
1471+
"comments": "",
1472+
"width": 130,
1473+
"height": 80,
1474+
"expand": "false",
1475+
"colorText": "auto",
1476+
"colorWidget": "auto",
1477+
"colorStroke": "auto",
1478+
"colorFill": "auto",
1479+
"alphaStroke": "auto",
1480+
"alphaFillOff": "auto",
1481+
"alphaFillOn": "auto",
1482+
"lineWidth": "auto",
1483+
"borderRadius": "auto",
1484+
"padding": "auto",
1485+
"html": "",
1486+
"css": "",
1487+
"colorTextOn": "auto",
1488+
"label": "Add Wildcards\nTitle, SubTitle\nComposer, Lyricist\n(macro - server)",
1489+
"vertical": false,
1490+
"wrap": false,
1491+
"on": "plugin:cmdutils,GoToFirstBar_cu;\nplugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.title\";\nplugin:cmdutils,Add_Text_cu,\"\\$Title\\\";\nplugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.subtitle\";\nplugin:cmdutils,Add_Text_cu,\"\\$Subtitle\\\";\nplugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.composer\";\nplugin:cmdutils,Add_Text_cu,\"\\$Composer\\\";\nplugin:cmdutils,TextStyleDefaultForCommands_cu,\"text.system.page_aligned.lyricist\";\nplugin:cmdutils,Add_Text_cu,\"\\$Lyricist\\\";\ncommand:goto_selection_start;\nplugin:cmdutils,MessageBox_cu,\"Please fill in the Score Info fields for the title, subtitle, composer, and lyricist, then click the Ribbon Home tab.\";\ncommand:score_info",
1492+
"off": 0,
1493+
"mode": "tap",
1494+
"doubleTap": false,
1495+
"decoupled": false,
1496+
"value": "",
1497+
"default": "",
1498+
"linkId": "",
1499+
"address": "/sibelius",
1500+
"preArgs": "",
1501+
"typeTags": "",
1502+
"decimals": 2,
1503+
"target": "localhost:8080",
1504+
"ignoreDefaults": false,
1505+
"bypass": false,
1506+
"onCreate": "",
1507+
"onValue": ""
14611508
}
14621509
],
14631510
"tabs": []

0 commit comments

Comments
 (0)