loupedeck-commander 1.4.0 → 1.4.2

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,166 +1,168 @@
1
- import {Button} from './button.mjs'
2
-
3
- export class ButtonField {
4
- #buttons = {}
5
- #screen
6
- width = 0
7
- height = 0
8
- #keys = []
9
- #type
10
- #name
11
- #profile
12
-
13
- constructor (name, rows, columns, width, height, data, profile) {
14
- console.info(`ButtonField ${name.padEnd(10, ' ')} Buttons: ${rows} x ${columns} , Pixels ${width} x ${height}`)
15
- this.#name = name
16
- this.width = width
17
- this.height = height
18
- // this.#rows = rows
19
- // this.#columns = columns
20
- this.#screen = this.width > 0 && this.height > 0
21
- this.#type = 'button'
22
- this.#profile = profile
23
- if (this.#screen) { this.#type = 'touch' }
24
-
25
- const keys = Object.keys(data)
26
- for (let i = 0; i < keys.length; i++) {
27
- const key = keys[i]
28
- const tb = new Button(`${this.#type}-${key}`, width / columns, height / rows, data[key],key,this.#profile)
29
- this.#buttons[key] = tb
30
- }
31
-
32
- this.#keys = keys
33
- }
34
-
35
-
36
- async draw (device) {
37
- if (!this.#screen) {
38
- // physical buttons:
39
- for (let i = 0; i < this.#keys.length; i++) {
40
- const key = this.#keys[i]
41
- this.#buttons[key].drawPhysical(device, key)
42
- }
43
- } else {
44
- // screen:
45
- device.drawScreen(this.#name, ctx => {
46
- ctx.globalCompositeOperation = 'source-atop'
47
- for (let i = 0; i < this.#keys.length; i++) {
48
- const key = this.#keys[i]
49
- const iValue = parseInt(key, 10)
50
- const row = Math.floor(iValue / device.columns)
51
- const column = iValue % device.columns
52
-
53
- this.#buttons[key].draw(row, column, ctx)
54
- }
55
- })
56
- }
57
- }
58
-
59
- setState (id, val) {
60
- this.#buttons[id].setState(val)
61
- }
62
-
63
- /*setIntState (id, val) {
64
- this.#buttons[id].setIntState(val)
65
- }*/
66
-
67
- async load () {
68
- for (let i = 0; i < this.#keys.length; i++) {
69
- const key = this.#keys[i]
70
- if (isNaN(key)) {
71
- await this.#buttons[key].load(this.#profile)
72
- } else {
73
- const iVal = parseInt(key, 10)
74
- await this.#buttons[iVal].load(this.#profile)
75
- }
76
- }
77
- }
78
-
79
- async pressed (id) {
80
- this.checkAndCreateButton(id)
81
- const result = await this.#buttons[id].pressed()
82
- if (!result) {
83
- console.info(`pressed ${this.#type} ${id}`)
84
- }
85
- return result
86
- }
87
-
88
- /**
89
- * Button released event handler
90
- * @param {*} id
91
- * @returns
92
- */
93
- async released (id) {
94
- const result = await this.#buttons[id].released()
95
- if (result) {
96
- // disable all other buttons of the group, if this one had been activated:
97
- for (let i = 0; i < this.#keys.length; i++) {
98
- let key = this.#keys[i]
99
- if (!isNaN(key)) { key = parseInt(key, 10) }
100
- // Ignore for myself (active element of the group)
101
- if (id === key) { continue }
102
- let toggleGroup = this.#buttons[id].getGroup()
103
- // Ignore empty groups
104
- if (toggleGroup === undefined || toggleGroup == "" ) { continue }
105
- // Switch all other elements of the same group off:
106
- if (this.#buttons[key].getGroup() === toggleGroup) {
107
- this.#buttons[key].setState(0)
108
- }
109
- }
110
- }
111
- if (!result) {
112
- console.info(`released ${this.#type} ${id}`)
113
- }
114
- return result
115
- }
116
-
117
- /**
118
- * Button changed event handler (after opcua value change)
119
- * @param {*} buttonID
120
- * @param {*} nodeid
121
- * @param {*} val
122
- */
123
- async buttonStateChanged(changedButtonID,attribute,nodeid,val){
124
- // todo: filter for buttonID
125
- for (let i = 0; i < this.#keys.length; i++) {
126
- let buttonID = this.#keys[i]
127
- if (changedButtonID == buttonID)
128
- await this.#buttons[buttonID].buttonStateChanged(i,attribute,nodeid,val)
129
- }
130
- }
131
-
132
- /**
133
- * Handle a rotation event for a knob
134
- * @param {*} id : Knob ID (e.g. 'knobTL, 'knobTR', 'knobBL', 'knobBR')
135
- * @param {*} delta
136
- * @returns
137
- */
138
- async rotated (id, delta) {
139
- this.checkAndCreateButton(id)
140
- const result = await this.#buttons[id].rotated(delta)
141
- if (!result) { console.info(`rotated ${this.#type} ${id} ${delta}`) }
142
- return result
143
- }
144
-
145
- /**
146
- * Handle a touchmove event for a touchbutton (available in left, center and right button fields)
147
- * @param {*} id
148
- * @param {*} x
149
- * @param {*} y
150
- * @returns
151
- */
152
- async touchmove (id, x, y) {
153
- this.checkAndCreateButton(id)
154
- const result = await this.#buttons[id].touchmove(x, y)
155
- if (!result) { console.info(`touchmove ${id} ${x} ${y}`) }
156
- return result
157
- }
158
-
159
- checkAndCreateButton (id) {
160
- if (!(id in this.#buttons)) {
161
- const tb = new Button(id, 1, 1, id)
162
- this.#buttons[id] = tb
163
- }
164
- }
165
- }
166
-
1
+ import {Button} from './button.mjs'
2
+
3
+ export class ButtonField {
4
+ #buttons = {}
5
+ #screen
6
+ width = 0
7
+ height = 0
8
+ #rows = 0
9
+ #columns = 0
10
+ #keys = []
11
+ #type
12
+ #name
13
+ #profile
14
+
15
+ constructor (name, rows, columns, width, height, data, profile) {
16
+ console.info(`ButtonField ${name.padEnd(10, ' ')} Buttons: ${rows} x ${columns} , Pixels ${width} x ${height}`)
17
+ this.#name = name
18
+ this.width = width
19
+ this.height = height
20
+ this.#rows = rows
21
+ this.#columns = columns
22
+ this.#screen = this.width > 0 && this.height > 0
23
+ this.#type = 'button'
24
+ this.#profile = profile
25
+ if (this.#screen) { this.#type = 'touch' }
26
+
27
+ const keys = Object.keys(data)
28
+ for (let i = 0; i < keys.length; i++) {
29
+ const key = keys[i]
30
+ const tb = new Button(`${this.#type}-${key}`, width / columns, height / rows, data[key],key,this.#profile)
31
+ this.#buttons[key] = tb
32
+ }
33
+
34
+ this.#keys = keys
35
+ }
36
+
37
+
38
+ async draw (device) {
39
+ if (!this.#screen) {
40
+ // physical buttons:
41
+ for (let i = 0; i < this.#keys.length; i++) {
42
+ const key = this.#keys[i]
43
+ this.#buttons[key].drawPhysical(device, key)
44
+ }
45
+ } else {
46
+ // screen:
47
+ device.drawScreen(this.#name, ctx => {
48
+ ctx.globalCompositeOperation = 'source-atop'
49
+ for (let i = 0; i < this.#keys.length; i++) {
50
+ const key = this.#keys[i]
51
+ const iValue = parseInt(key, 10)
52
+ const row = Math.floor(iValue / device.columns)
53
+ const column = iValue % device.columns
54
+
55
+ this.#buttons[key].draw(row, column, ctx)
56
+ }
57
+ })
58
+ }
59
+ }
60
+
61
+ setState (id, val) {
62
+ this.#buttons[id].setState(val)
63
+ }
64
+
65
+ /*setIntState (id, val) {
66
+ this.#buttons[id].setIntState(val)
67
+ }*/
68
+
69
+ async load () {
70
+ for (let i = 0; i < this.#keys.length; i++) {
71
+ const key = this.#keys[i]
72
+ if (isNaN(key)) {
73
+ await this.#buttons[key].load(this.#profile)
74
+ } else {
75
+ const iVal = parseInt(key, 10)
76
+ await this.#buttons[iVal].load(this.#profile)
77
+ }
78
+ }
79
+ }
80
+
81
+ async pressed (id) {
82
+ this.checkAndCreateButton(id)
83
+ const result = await this.#buttons[id].pressed()
84
+ if (!result) {
85
+ console.info(`pressed ${this.#type} ${id}`)
86
+ }
87
+ return result
88
+ }
89
+
90
+ /**
91
+ * Button released event handler
92
+ * @param {*} id
93
+ * @returns
94
+ */
95
+ async released (id) {
96
+ const result = await this.#buttons[id].released()
97
+ if (result) {
98
+ // disable all other buttons of the group, if this one had been activated:
99
+ for (let i = 0; i < this.#keys.length; i++) {
100
+ let key = this.#keys[i]
101
+ if (!isNaN(key)) { key = parseInt(key, 10) }
102
+ // Ignore for myself (active element of the group)
103
+ if (id === key) { continue }
104
+ let toggleGroup = this.#buttons[id].getGroup()
105
+ // Ignore empty groups
106
+ if (toggleGroup === undefined || toggleGroup == "" ) { continue }
107
+ // Switch all other elements of the same group off:
108
+ if (this.#buttons[key].getGroup() === toggleGroup) {
109
+ this.#buttons[key].setState(0)
110
+ }
111
+ }
112
+ }
113
+ if (!result) {
114
+ console.info(`released ${this.#type} ${id}`)
115
+ }
116
+ return result
117
+ }
118
+
119
+ /**
120
+ * Button changed event handler (after opcua value change)
121
+ * @param {*} buttonID
122
+ * @param {*} nodeid
123
+ * @param {*} val
124
+ */
125
+ async buttonStateChanged(changedButtonID,attribute,nodeid,val){
126
+ // todo: filter for buttonID
127
+ for (let i = 0; i < this.#keys.length; i++) {
128
+ let buttonID = this.#keys[i]
129
+ if (changedButtonID == buttonID)
130
+ await this.#buttons[buttonID].buttonStateChanged(i,attribute,nodeid,val)
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Handle a rotation event for a knob
136
+ * @param {*} id : Knob ID (e.g. 'knobTL, 'knobTR', 'knobBL', 'knobBR')
137
+ * @param {*} delta
138
+ * @returns
139
+ */
140
+ async rotated (id, delta) {
141
+ this.checkAndCreateButton(id)
142
+ const result = await this.#buttons[id].rotated(delta)
143
+ if (!result) { console.info(`rotated ${this.#type} ${id} ${delta}`) }
144
+ return result
145
+ }
146
+
147
+ /**
148
+ * Handle a touchmove event for a touchbutton (available in left, center and right button fields)
149
+ * @param {*} id
150
+ * @param {*} x
151
+ * @param {*} y
152
+ * @returns
153
+ */
154
+ async touchmove (id, x, y) {
155
+ this.checkAndCreateButton(id)
156
+ const result = await this.#buttons[id].touchmove(x, y)
157
+ if (!result) { console.info(`touchmove ${id} ${x} ${y}`) }
158
+ return result
159
+ }
160
+
161
+ checkAndCreateButton (id) {
162
+ if (!(id in this.#buttons)) {
163
+ const tb = new Button(id, 1, 1, id)
164
+ this.#buttons[id] = tb
165
+ }
166
+ }
167
+ }
168
+