loupedeck-commander 1.2.3 → 1.2.4

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.
@@ -1,326 +1,333 @@
1
- import {discover, HAPTIC,LoupedeckDevice } from 'loupedeck'
2
- import { ApplicationConfig } from './ApplicationConfig.mjs'
3
- import { ButtonField, StopInterfaces, InitializeInterfaces,opcuainterface,profileEmitter} from './touchbuttons.mjs'
4
-
5
- export class BaseLoupeDeckHandler {
6
- device = undefined
7
- appConfig = undefined
8
- profileConfigs = []
9
- currentProfile = 0
10
- screens = {}
11
- buttons = {}
12
- screenUpdate = {}
13
- stopping = false
14
-
15
- constructor (config) {
16
- console.log(`INIT with config ${config}`)
17
- this.loadConfig(config)
18
- }
19
-
20
- /**
21
- * event handler - start
22
- */
23
- async start () {
24
- console.info('Start')
25
- while (!this.device && !this.stopping) {
26
- try {
27
- var list = await LoupedeckDevice.list()
28
- if (list.length>0){
29
- var element = list[0]
30
- console.log("Connecting to device")
31
- console.log("Path: ", element.path)
32
- console.log("vendorId: ", element.vendorId, element.productId)
33
- console.log("serialNumber: ", element.serialNumber)
34
- }
35
-
36
- this.device = await discover()
37
-
38
-
39
-
40
- } catch (e) {
41
- console.error(`${e}. Reattempting in 3 seconds...`)
42
- await new Promise(resolve => setTimeout(resolve, 3000))
43
- }
44
-
45
- if (this.stopping){
46
- return
47
- }
48
- }
49
- console.info(`✅ Discovered Device ${this.device.type}`)
50
-
51
- const self = this
52
-
53
- this.device.on('connect', (address) => { self.onConnected(address) })
54
- this.device.on('down', (event) => { self.onButtonDown(event) })
55
- this.device.on('up', (event) => { self.onButtonUp(event) })
56
- this.device.on('rotate', (event) => { self.onRotate(event) })
57
- this.device.on('touchstart', (event) => { self.onTouchStart(event) })
58
- this.device.on('touchmove', (event) => { self.onTouchMove(event) })
59
- this.device.on('touchend', (event) => { self.onTouchEnd(event) })
60
- this.device.on('disconnect', (event) => { self.disconnectDevice(event) })
61
-
62
- console.info(`✅ Registered callbacks`)
63
- }
64
-
65
- /**
66
- * event handler - loupedeck device disconnected
67
- */
68
- async disconnectDevice (event) {
69
- console.info("Device Disconnected")
70
- this.device=undefined
71
- }
72
-
73
- /**
74
- * stop handler - close the dipslay-connection and also stop all interface handlers
75
- */
76
- async stop () {
77
- console.info('Stopping Handler')
78
-
79
- try {
80
- console.info(`Closing Device`)
81
- this.stopping = true
82
- if (this.device){
83
- this.device.vibrate(HAPTIC.DESCEND_MED)
84
- await new Promise(resolve => setTimeout(resolve, 250))
85
- }
86
- if (this.device){
87
- this.device.setBrightness(0)
88
- await new Promise(resolve => setTimeout(resolve, 250))
89
- }
90
- if (this.device){
91
- this.device.reconnectInterval = 0
92
- await this.device.close()
93
- await new Promise(resolve => setTimeout(resolve, 2000))
94
- console.info(`Device Closed`)
95
- }
96
-
97
- console.info(`Stopping interfaces`)
98
- await StopInterfaces()
99
- await new Promise(resolve => setTimeout(resolve, 500))
100
- } catch (e) {}
101
-
102
- process.exit()
103
-
104
- }
105
-
106
- /**
107
- * load Application config file from JSON
108
- * @param filename
109
- */
110
- loadConfig (fileName) {
111
- console.info(`Loading Config File ${fileName}`)
112
- this.appConfig = new ApplicationConfig()
113
- this.appConfig.loadFromFile(fileName)
114
- }
115
-
116
- /**
117
- * activate the profile with the givven ID
118
- */
119
- async activateProfile (id) {
120
- // todo Profile-change implementation
121
- id = Number(id)
122
- var oldProfile = this.currentProfile
123
- if (this.appConfig.profiles.length > id) {
124
- this.currentProfile = id
125
- }else{
126
- return
127
- }
128
- const profile = this.getCurrentProfile()
129
- console.info("ACTIVATE PROFILE",id,profile.name)
130
- const dLeft = this.device.displays.left
131
- const dRight = this.device.displays.right
132
- const dCenter = this.device.displays.center
133
- const dKnob = this.device.displays.knob
134
-
135
- this.screens.center = new ButtonField('center', this.device.rows, this.device.columns, dCenter.width, dCenter.height, profile.touch.center,profile)
136
- this.screens.left = new ButtonField('left', 1, 1, dLeft.width, dLeft.height, profile.touch.left,profile)
137
- this.screens.right = new ButtonField('right', 1, 1, dRight.width, dRight.height, profile.touch.right,profile)
138
- // knob Display is only available in the CT-version - not with live:
139
- if (dKnob) {
140
- this.screens.knob = new ButtonField('knob', 1, 1, dKnob.width, dKnob.height, profile.touch.knob,profile)
141
- }
142
-
143
- this.buttons = new ButtonField('buttons', 1, 1, 0, 0, profile.buttons,profile)
144
-
145
- await this.screens.center.load()
146
- await this.screens.right.load()
147
- await this.screens.left.load()
148
- if (dKnob) {
149
- await this.screens.knob.load()
150
- }
151
- await this.buttons.load()
152
-
153
- await this.screens.center.draw(this.device)
154
- if (dKnob) {
155
- await this.screens.knob.draw(this.device)
156
- }
157
-
158
- this.buttons.setState(this.currentProfile+1,1)
159
- this.buttons.setState(oldProfile+1,1)
160
-
161
- await this.buttons.draw(this.device)
162
-
163
- }
164
-
165
- /**
166
- * get the dictionary iwth the current profile settings
167
- */
168
- getCurrentProfile () {
169
- return this.appConfig.profiles[this.currentProfile]
170
- }
171
-
172
- /**
173
- * Triggered, when LoupeDeck Device is connected
174
- * - Initialize the profile from config-file and
175
- * - start the interface handlers accordingly
176
- */
177
- async onConnected (address) {
178
- console.info(`✅ Connected to ${this.device.type}, ${address}`)
179
-
180
- await this.activateProfile(0)
181
-
182
- var profile = this.getCurrentProfile()
183
- await InitializeInterfaces(profile,this.buttons.setState)
184
-
185
- const self = this
186
-
187
- // Register callback on monitored item change:
188
- opcuainterface.on("monitored item changed",(buttonID,nodeid,val) => { self.buttonStateChanged(buttonID,nodeid,val) })
189
- profileEmitter.on("profileChanged",(profileID) => { self.activateProfile(profileID) })
190
-
191
-
192
- this.device.setBrightness(1)
193
- this.device.vibrate(HAPTIC.ASCEND_MED)
194
-
195
- // Fore update of all screens
196
- console.info('✅ Force Screen update')
197
- this.screenUpdate["center"] = true
198
- this.screenUpdate["left"] = true
199
- this.screenUpdate["right"] = true
200
- await this.updateScreens()
201
-
202
- console.info('✅ Done initializing')
203
- }
204
-
205
- /**
206
- * Fore an update of all screens
207
- */
208
- async updateScreens () {
209
- const keys = Object.keys(this.screenUpdate)
210
- for (let i = 0; i < keys.length; i++) {
211
- const screen = keys[i]
212
- await this.screens[screen].draw(this.device)
213
- }
214
- this.screenUpdate = {}
215
- }
216
-
217
- /**
218
- * Button Down Handler - triggered through Event Button Down - connected to LoupeDeck Event
219
- */
220
- async onButtonDown (event) {
221
- let ok = false
222
- const id = event.id
223
- ok = await this.buttons.pressed(id)
224
- await this.buttons.draw(this.device)
225
- return ok
226
- }
227
-
228
- /**
229
- * Button Up Handler - triggered through Event Button Up - connected to LoupeDeck Event
230
- */
231
- async onButtonUp (event) {
232
- let ok = false
233
- const id = event.id
234
- ok = await this.buttons.released(id)
235
- await this.buttons.draw(this.device)
236
-
237
- /*if (this.currentProfile != id){
238
- this.activateProfile(id-1)
239
- }*/
240
- return ok
241
- }
242
-
243
- /**
244
- * Button Rotate Handler - triggered through Event Rotate available with knob-Buttons - connected to LoupeDeck Event
245
- */
246
- async onRotate (event) {
247
- const id = event.id
248
- const delta = event.delta
249
- return await this.buttons.rotated(id, delta)
250
- }
251
-
252
- /**
253
- * TouchStart Handler - triggered through Event touch available on all touchbuttons on the loupedeck display - connected to LoupeDeck Event
254
- */
255
- async onTouchStart (event) {
256
- let ok = false
257
- const changedTouches = event.changedTouches
258
- for (let i = 0; i < changedTouches.length; i++) {
259
- const screen = changedTouches[i].target.screen
260
- let id = changedTouches[i].target.key
261
- this.screenUpdate[screen] = true
262
- if (id === undefined) {
263
- id = 0
264
- }
265
- ok = await this.screens[screen].pressed(id)
266
- }
267
- await this.updateScreens()
268
- return ok
269
- }
270
-
271
- /**
272
- * TouchMove Handler - triggered through Event touch available on all touchbuttons on the loupedeck display - connected to LoupeDeck Event
273
- */
274
- async onTouchMove (event) {
275
- let ok = false
276
- const changedTouches = event.changedTouches
277
- for (let i = 0; i < changedTouches.length; i++) {
278
- const x = changedTouches[i].x
279
- const y = changedTouches[i].y
280
- const screen = changedTouches[i].target.screen
281
- let id = changedTouches[i].target.key
282
- if (id === undefined) {
283
- id = 0 // for left/right
284
- }
285
- ok = await this.screens[screen].touchmove(id, x, y)
286
- }
287
- return ok
288
- }
289
-
290
- /**
291
- * TouchEnd Handler - triggered through Event touch available on all touchbuttons on the loupedeck display - connected to LoupeDeck Event
292
- */
293
- async onTouchEnd (event) {
294
- let ok = false
295
- const changedTouches = event.changedTouches
296
- for (let i = 0; i < changedTouches.length; i++) {
297
- const elem = changedTouches[i].target
298
- let id = changedTouches[i].target.key
299
- if (id === undefined) {
300
- id = 0
301
- }
302
- this.screenUpdate[elem.screen] = true
303
-
304
- ok = await this.screens[elem.screen].released(id)
305
- }
306
- await this.updateScreens()
307
- return ok
308
- }
309
-
310
- /**
311
- * Handler for StateChanged through OPC/UA Interface - only connected with touch-buttons on center field (yet)
312
- */
313
- async buttonStateChanged(buttonID,nodeid,val) {
314
- let ok = false
315
- this.screenUpdate["center"] = true
316
- this.screenUpdate["left"] = true
317
- this.screenUpdate["right"] = true
318
-
319
- ok = await this.screens.center.changed(buttonID,nodeid,val)
320
-
321
- await this.updateScreens()
322
- return ok
323
- }
324
-
325
-
326
- }
1
+ import {discover, HAPTIC,LoupedeckDevice } from 'loupedeck'
2
+ import { ApplicationConfig } from './ApplicationConfig.mjs'
3
+ import { ButtonField, StopInterfaces, InitializeInterfaces,opcuainterface,profileEmitter} from './touchbuttons.mjs'
4
+
5
+ export class BaseLoupeDeckHandler {
6
+ device = undefined
7
+ appConfig = undefined
8
+ profileConfigs = []
9
+ currentProfile = 0
10
+ screens = {}
11
+ buttons = {}
12
+ knobs = {}
13
+ screenUpdate = {}
14
+ stopping = false
15
+
16
+ constructor (config) {
17
+ console.log(`INIT with config ${config}`)
18
+ let result = this.loadConfig(config)
19
+ if (!result){
20
+ process.exit(-1)
21
+ }
22
+ }
23
+
24
+ /**
25
+ * event handler - start
26
+ */
27
+ async start () {
28
+ console.info('Start')
29
+ while (!this.device && !this.stopping) {
30
+ try {
31
+ var list = await LoupedeckDevice.list()
32
+ if (list.length>0){
33
+ var element = list[0]
34
+ console.log("Connecting to device")
35
+ console.log("Path: ", element.path)
36
+ console.log("vendorId: ", element.vendorId, element.productId)
37
+ console.log("serialNumber: ", element.serialNumber)
38
+ }
39
+
40
+ this.device = await discover()
41
+
42
+
43
+
44
+ } catch (e) {
45
+ console.error(`${e}. Reattempting in 3 seconds...`)
46
+ await new Promise(resolve => setTimeout(resolve, 3000))
47
+ }
48
+
49
+ if (this.stopping){
50
+ return
51
+ }
52
+ }
53
+ console.info(`✅ Discovered Device ${this.device.type}`)
54
+
55
+ const self = this
56
+
57
+ this.device.on('connect', (address) => { self.onConnected(address) })
58
+ this.device.on('down', (event) => { self.onButtonDown(event) })
59
+ this.device.on('up', (event) => { self.onButtonUp(event) })
60
+ this.device.on('rotate', (event) => { self.onRotate(event) })
61
+ this.device.on('touchstart', (event) => { self.onTouchStart(event) })
62
+ this.device.on('touchmove', (event) => { self.onTouchMove(event) })
63
+ this.device.on('touchend', (event) => { self.onTouchEnd(event) })
64
+ this.device.on('disconnect', (event) => { self.disconnectDevice(event) })
65
+
66
+ console.info(`✅ Registered callbacks`)
67
+ }
68
+
69
+ /**
70
+ * event handler - loupedeck device disconnected
71
+ */
72
+ async disconnectDevice (event) {
73
+ console.info("Device Disconnected")
74
+ this.device=undefined
75
+ }
76
+
77
+ /**
78
+ * stop handler - close the dipslay-connection and also stop all interface handlers
79
+ */
80
+ async stop () {
81
+ console.info('Stopping Handler')
82
+
83
+ try {
84
+ console.info(`Closing Device`)
85
+ this.stopping = true
86
+ if (this.device){
87
+ this.device.vibrate(HAPTIC.DESCEND_MED)
88
+ await new Promise(resolve => setTimeout(resolve, 250))
89
+ }
90
+ if (this.device){
91
+ this.device.setBrightness(0)
92
+ await new Promise(resolve => setTimeout(resolve, 250))
93
+ }
94
+ if (this.device){
95
+ this.device.reconnectInterval = 0
96
+ await this.device.close()
97
+ await new Promise(resolve => setTimeout(resolve, 2000))
98
+ console.info(`Device Closed`)
99
+ }
100
+
101
+ console.info(`Stopping interfaces`)
102
+ await StopInterfaces()
103
+ await new Promise(resolve => setTimeout(resolve, 500))
104
+ } catch (e) {}
105
+
106
+ process.exit()
107
+
108
+ }
109
+
110
+ /**
111
+ * load Application config file from JSON
112
+ * @param filename
113
+ */
114
+ loadConfig (fileName) {
115
+ console.info(`Loading Config File ${fileName}`)
116
+ this.appConfig = new ApplicationConfig()
117
+ return this.appConfig.loadFromFile(fileName)
118
+ }
119
+
120
+ /**
121
+ * activate the profile with the givven ID
122
+ */
123
+ async activateProfile (id) {
124
+ // todo Profile-change implementation
125
+ id = Number(id)
126
+ var oldProfile = this.currentProfile
127
+ if (this.appConfig.profiles.length > id) {
128
+ this.currentProfile = id
129
+ }else{
130
+ return
131
+ }
132
+ const profile = this.getCurrentProfile()
133
+ console.info("ACTIVATE PROFILE",id,profile.name)
134
+ const dLeft = this.device.displays.left
135
+ const dRight = this.device.displays.right
136
+ const dCenter = this.device.displays.center
137
+
138
+ this.screens.center = new ButtonField('center', this.device.rows, this.device.columns, dCenter.width, dCenter.height, profile.touch.center,profile)
139
+ this.screens.left = new ButtonField('left', 1, 1, dLeft.width, dLeft.height, profile.touch.left,profile)
140
+ this.screens.right = new ButtonField('right', 1, 1, dRight.width, dRight.height, profile.touch.right,profile)
141
+ // knobs are only available in the CT-version:
142
+ if (this.device.knobs) {
143
+ this.knobs = new ButtonField('knob', 1, 1, 0, 0, profile.knobs,profile)
144
+ }
145
+ if (this.device.buttons) {
146
+ this.buttons = new ButtonField('buttons', 1, 1, 0, 0, profile.buttons,profile)
147
+ }
148
+ await this.screens.center.load()
149
+ await this.screens.right.load()
150
+ await this.screens.left.load()
151
+ await this.buttons.load()
152
+ await this.knobs.load()
153
+
154
+ await this.screens.center.draw(this.device)
155
+
156
+ //this.buttons.setState(this.currentProfile+1,1)
157
+ //this.buttons.setState(oldProfile+1,1)
158
+
159
+ await this.buttons.draw(this.device)
160
+
161
+ }
162
+
163
+ /**
164
+ * get the dictionary iwth the current profile settings
165
+ */
166
+ getCurrentProfile () {
167
+ return this.appConfig.profiles[this.currentProfile]
168
+ }
169
+
170
+ /**
171
+ * Triggered, when LoupeDeck Device is connected
172
+ * - Initialize the profile from config-file and
173
+ * - start the interface handlers accordingly
174
+ */
175
+ async onConnected (address) {
176
+ console.info(`✅ Connected to ${this.device.type}, ${address}`)
177
+
178
+ await this.activateProfile(0)
179
+
180
+ var profile = this.getCurrentProfile()
181
+ await InitializeInterfaces(profile,this.buttons.setState)
182
+
183
+ const self = this
184
+
185
+ // Register callback on monitored item change:
186
+ opcuainterface.on("monitored item changed",(buttonID,nodeid,val) => { self.buttonStateChanged(buttonID,nodeid,val) })
187
+ profileEmitter.on("profileChanged",(profileID) => { self.activateProfile(profileID) })
188
+
189
+
190
+ this.device.setBrightness(1)
191
+ this.device.vibrate(HAPTIC.ASCEND_MED)
192
+
193
+ // Fore update of all screens
194
+ console.info('✅ Force Screen update')
195
+ this.screenUpdate["center"] = true
196
+ this.screenUpdate["left"] = true
197
+ this.screenUpdate["right"] = true
198
+ await this.updateScreens()
199
+
200
+ console.info('✅ Done initializing')
201
+ }
202
+
203
+ /**
204
+ * Fore an update of all screens
205
+ */
206
+ async updateScreens () {
207
+ const keys = Object.keys(this.screenUpdate)
208
+ for (let i = 0; i < keys.length; i++) {
209
+ const screen = keys[i]
210
+ await this.screens[screen].draw(this.device)
211
+ }
212
+ this.screenUpdate = {}
213
+ }
214
+
215
+ /**
216
+ * Button Down Handler - triggered through Event Button Down - connected to LoupeDeck Event
217
+ */
218
+ async onButtonDown (event) {
219
+ let ok = false
220
+ const id = event.id
221
+ if (Number.isInteger(id)){
222
+ ok = await this.buttons.pressed(id)
223
+ await this.buttons.draw(this.device)
224
+ }else{
225
+ ok = await this.knobs.pressed(id)
226
+ }
227
+ return ok
228
+ }
229
+
230
+ /**
231
+ * Button Up Handler - triggered through Event Button Up - connected to LoupeDeck Event
232
+ */
233
+ async onButtonUp (event) {
234
+ let ok = false
235
+ const id = event.id
236
+ if (Number.isInteger(id) && this.buttons){
237
+ ok = await this.buttons.released(id)
238
+ await this.buttons.draw(this.device)
239
+ }else{
240
+ if(this.knobs)
241
+ ok = await this.knobs.released(id)
242
+ }
243
+ return ok
244
+ }
245
+
246
+ /**
247
+ * Button Rotate Handler - triggered through Event Rotate available with knob-Buttons - connected to LoupeDeck Event
248
+ */
249
+ async onRotate (event) {
250
+ const id = event.id
251
+ const delta = event.delta
252
+ if (this.knobs)
253
+ return await this.knobs.rotated(id, delta)
254
+ }
255
+
256
+ /**
257
+ * TouchStart Handler - triggered through Event touch available on all touchbuttons on the loupedeck display - connected to LoupeDeck Event
258
+ */
259
+ async onTouchStart (event) {
260
+ let ok = false
261
+ const changedTouches = event.changedTouches
262
+ for (let i = 0; i < changedTouches.length; i++) {
263
+ const screen = changedTouches[i].target.screen
264
+ let id = changedTouches[i].target.key
265
+ this.screenUpdate[screen] = true
266
+ if (id === undefined) {
267
+ id = 0
268
+ }
269
+ if (this.screens[screen])
270
+ ok = await this.screens[screen].pressed(id)
271
+ }
272
+ await this.updateScreens()
273
+ return ok
274
+ }
275
+
276
+ /**
277
+ * TouchMove Handler - triggered through Event touch available on all touchbuttons on the loupedeck display - connected to LoupeDeck Event
278
+ */
279
+ async onTouchMove (event) {
280
+ let ok = false
281
+ const changedTouches = event.changedTouches
282
+ for (let i = 0; i < changedTouches.length; i++) {
283
+ const x = changedTouches[i].x
284
+ const y = changedTouches[i].y
285
+ const screen = changedTouches[i].target.screen
286
+ let id = changedTouches[i].target.key
287
+ if (id === undefined) {
288
+ id = 0 // for left/right
289
+ }
290
+ if (this.screens[screen])
291
+ ok = await this.screens[screen].touchmove(id, x, y)
292
+ }
293
+ return ok
294
+ }
295
+
296
+ /**
297
+ * TouchEnd Handler - triggered through Event touch available on all touchbuttons on the loupedeck display - connected to LoupeDeck Event
298
+ */
299
+ async onTouchEnd (event) {
300
+ let ok = false
301
+ const changedTouches = event.changedTouches
302
+ for (let i = 0; i < changedTouches.length; i++) {
303
+ const elem = changedTouches[i].target
304
+ let id = changedTouches[i].target.key
305
+ if (id === undefined) {
306
+ id = 0
307
+ }
308
+ this.screenUpdate[elem.screen] = true
309
+
310
+ if (this.screens[elem.screen])
311
+ ok = await this.screens[elem.screen].released(id)
312
+ }
313
+ await this.updateScreens()
314
+ return ok
315
+ }
316
+
317
+ /**
318
+ * Handler for StateChanged through OPC/UA Interface - only connected with touch-buttons on center field (yet)
319
+ */
320
+ async buttonStateChanged(buttonID,nodeid,val) {
321
+ let ok = false
322
+ this.screenUpdate["center"] = true
323
+ this.screenUpdate["left"] = true
324
+ this.screenUpdate["right"] = true
325
+
326
+ ok = await this.screens.center.changed(buttonID,nodeid,val)
327
+
328
+ await this.updateScreens()
329
+ return ok
330
+ }
331
+
332
+
333
+ }