cabbage-react 1.0.14 → 1.0.16
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,25 +1,94 @@
|
|
|
1
1
|
export class Cabbage {
|
|
2
2
|
/**
|
|
3
|
-
* Main entry point for sending
|
|
3
|
+
* Main entry point for sending widget value changes to the Cabbage backend.
|
|
4
|
+
*
|
|
4
5
|
* This function automatically routes messages to the appropriate backend function
|
|
5
6
|
* based on the automatable flag:
|
|
6
7
|
*
|
|
7
|
-
* - automatable=true
|
|
8
|
-
*
|
|
8
|
+
* - `automatable=true`: Routes to `sendParameterUpdate()` for DAW-automatable parameters.
|
|
9
|
+
* The value is sent to the DAW for automation recording and also forwarded to Csound.
|
|
10
|
+
*
|
|
11
|
+
* - `automatable=false`: Routes to `sendChannelData()` for non-automatable data.
|
|
12
|
+
* The value is sent directly to Csound without DAW parameter involvement.
|
|
13
|
+
*
|
|
14
|
+
* **When to use**: Call this from widget event handlers (e.g., pointer events, input changes)
|
|
15
|
+
* when the user interacts with a widget.
|
|
16
|
+
*
|
|
17
|
+
* **When NOT to use**: Do not call this when handling incoming `parameterChange` messages
|
|
18
|
+
* from the backend. Those messages are for display updates only.
|
|
19
|
+
*
|
|
20
|
+
* @param {Object} message - The message object containing widget data
|
|
21
|
+
* @param {string} message.channel - The channel name
|
|
22
|
+
* @param {number} message.paramIdx - Parameter index (required if automatable)
|
|
23
|
+
* @param {number|string} message.value - The value to send
|
|
24
|
+
* @param {Object|null} vscode - VS Code API object (null for plugin mode)
|
|
25
|
+
* @param {boolean} automatable - Whether this widget is DAW-automatable
|
|
26
|
+
*/
|
|
27
|
+
static sendChannelUpdate(message: {
|
|
28
|
+
channel: string;
|
|
29
|
+
paramIdx: number;
|
|
30
|
+
value: number | string;
|
|
31
|
+
}, vscode?: Object | null, automatable?: boolean): void;
|
|
32
|
+
/**
|
|
33
|
+
* Internal: Send a parameter update to the DAW for automation recording.
|
|
34
|
+
* Use `sendChannelUpdate()` instead - it will route here automatically for automatable widgets.
|
|
35
|
+
*
|
|
36
|
+
* This function sends the parameter value to the DAW's automation system.
|
|
37
|
+
* The DAW will then send the value back via a `parameterChange` message,
|
|
38
|
+
* which updates both the UI and Csound.
|
|
9
39
|
*
|
|
10
|
-
*
|
|
40
|
+
* **Important**: This creates a round-trip through the DAW:
|
|
41
|
+
* 1. UI calls `sendParameterUpdate()` with value
|
|
42
|
+
* 2. DAW receives and records/processes the value
|
|
43
|
+
* 3. DAW sends `parameterChange` back to the plugin
|
|
44
|
+
* 4. Plugin updates Csound and sends `parameterChange` to UI
|
|
45
|
+
* 5. UI updates its display (but does NOT call sendParameterUpdate again!)
|
|
11
46
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
47
|
+
* @param {Object} message - The parameter message
|
|
48
|
+
* @param {number} message.paramIdx - The parameter index (must be >= 0)
|
|
49
|
+
* @param {string} message.channel - The channel name
|
|
50
|
+
* @param {number} message.value - The parameter value (full range, not normalized)
|
|
51
|
+
* @param {string} [message.channelType="number"] - The channel type
|
|
52
|
+
* @param {Object|null} vscode - VS Code API object (null for plugin mode)
|
|
14
53
|
*/
|
|
15
|
-
static
|
|
16
|
-
|
|
54
|
+
static sendParameterUpdate(message: {
|
|
55
|
+
paramIdx: number;
|
|
56
|
+
channel: string;
|
|
57
|
+
value: number;
|
|
58
|
+
channelType?: string | undefined;
|
|
59
|
+
}, vscode?: Object | null): void;
|
|
17
60
|
static sendCustomCommand(command: any, vscode?: null, additionalData?: {}): void;
|
|
18
61
|
static sendWidgetUpdate(widget: any, vscode?: null): void;
|
|
19
62
|
static sendMidiMessageFromUI(statusByte: any, dataByte1: any, dataByte2: any, vscode?: null): void;
|
|
20
|
-
|
|
63
|
+
/**
|
|
64
|
+
* @private
|
|
65
|
+
* Internal: Send channel data directly to Csound without DAW automation involvement.
|
|
66
|
+
* Use `sendChannelUpdate()` instead - it will route here automatically for non-automatable widgets.
|
|
67
|
+
*
|
|
68
|
+
* Used for non-automatable widgets like buttons, file selectors, or
|
|
69
|
+
* any widget that sends string data. The value is sent directly to Csound's
|
|
70
|
+
* channel system and is not recorded by DAW automation.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} channel - The Csound channel name
|
|
73
|
+
* @param {number|string} data - The data to send (number or string)
|
|
74
|
+
* @param {Object|null} vscode - VS Code API object (null for plugin mode)
|
|
75
|
+
*/
|
|
76
|
+
private static sendChannelData;
|
|
21
77
|
static MidiMessageFromHost(statusByte: any, dataByte1: any, dataByte2: any): void;
|
|
22
78
|
static triggerFileOpenDialog(vscode: any, channel: any, options?: {}): void;
|
|
23
79
|
static openUrl(vscode: any, url: any, file: any): void;
|
|
80
|
+
/**
|
|
81
|
+
* Request a resize of the plugin GUI window.
|
|
82
|
+
* This is only supported in plugin mode (CLAP/VST3/AUv2).
|
|
83
|
+
* The host may accept or reject the resize request.
|
|
84
|
+
*
|
|
85
|
+
* @param {number} width - The requested width in pixels
|
|
86
|
+
* @param {number} height - The requested height in pixels
|
|
87
|
+
* @param {object} vscode - The vscode API object (null for plugin mode)
|
|
88
|
+
*
|
|
89
|
+
* The response will be sent via hostMessageCallback with:
|
|
90
|
+
* {command: "resizeResponse", accepted: boolean, width: number, height: number}
|
|
91
|
+
*/
|
|
92
|
+
static requestResize(width: number, height: number, vscode?: object): void;
|
|
24
93
|
}
|
|
25
94
|
//# sourceMappingURL=cabbage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cabbage.d.ts","sourceRoot":"","sources":["../../src/cabbage/cabbage.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cabbage.d.ts","sourceRoot":"","sources":["../../src/cabbage/cabbage.js"],"names":[],"mappings":"AAqFA;IACC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,kCANG;QAAwB,OAAO,EAAvB,MAAM;QACU,QAAQ,EAAxB,MAAM;QACiB,KAAK,EAA5B,MAAM,GAAC,MAAM;KACrB,WAAQ,MAAM,GAAC,IAAI,gBACX,OAAO,QAcjB;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,oCANG;QAAwB,QAAQ,EAAxB,MAAM;QACU,OAAO,EAAvB,MAAM;QACU,KAAK,EAArB,MAAM;QACW,WAAW;KACpC,WAAQ,MAAM,GAAC,IAAI,QAwCrB;IAED,iFAiCC;IAED,0DAiBC;IAED,mGA6BC;IAED;;;;;;;;;;;;OAYG;IACH,+BAoCC;IAED,kFASC;IAED,4EA2BC;IAED,uDAsBC;IAED;;;;;;;;;;;OAWG;IACH,4BAPW,MAAM,UACN,MAAM,WACN,MAAM,QA4BhB;CACD"}
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* This hook listens for updates to a parameter value from Cabbage and
|
|
4
4
|
* sends updates to Cabbage when the parameter value changes locally (e.g., through a UI slider).
|
|
5
5
|
*/
|
|
6
|
-
export declare const useCabbageState: <T>(channelId: string) => {
|
|
6
|
+
export declare const useCabbageState: <T>(channelId: string, isDragging?: boolean) => {
|
|
7
7
|
value: T | undefined;
|
|
8
8
|
setValue: (value: T) => void;
|
|
9
|
+
parameterIndex: number | undefined;
|
|
9
10
|
};
|
|
10
11
|
//# sourceMappingURL=useCabbageState.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCabbageState.d.ts","sourceRoot":"","sources":["../../src/hooks/useCabbageState.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,aAAa,MAAM;;
|
|
1
|
+
{"version":3,"file":"useCabbageState.d.ts","sourceRoot":"","sources":["../../src/hooks/useCabbageState.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,aAAa,MAAM,eAAe,OAAO;;sBAMvC,CAAC;;CA+GnC,CAAC"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react");console.log("Cabbage: loading cabbage.js");class f{static sendChannelUpdate(e,
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react");console.log("Cabbage: loading cabbage.js");class f{static sendChannelUpdate(e,a=null,n=!1){if(n===!0||n===1)f.sendParameterUpdate(e,a);else{const s=e.value!==void 0?e.value:e.stringData||e.floatData;f.sendChannelData(e.channel,s,a)}}static sendParameterUpdate(e,a=null){if(e.paramIdx===void 0||e.paramIdx===null){console.error("Cabbage.sendParameterUpdate: message missing paramIdx!",e);return}if(e.paramIdx<0){console.warn("Cabbage.sendParameterUpdate: paramIdx is -1, skipping (non-automatable widget)",e);return}const n={command:"parameterChange",paramIdx:e.paramIdx,channel:e.channel,value:e.value,channelType:e.channelType||"number"};a!==null?a.postMessage(n):typeof window.sendMessageFromUI=="function"?window.sendMessageFromUI(n):console.error("Cabbage: window.sendMessageFromUI is not available. Message:",n)}static sendCustomCommand(e,a=null,n={}){const s={command:e,text:JSON.stringify(n)};if(a!==null)a.postMessage(s);else if(typeof window.sendMessageFromUI=="function"){console.log("Cabbage: Calling window.sendMessageFromUI with:",s);try{const o=window.sendMessageFromUI(s);console.log("Cabbage: sendMessageFromUI returned:",o)}catch(o){console.error("Cabbage: sendMessageFromUI threw error:",o),console.error("Cabbage: Error stack:",o.stack)}}else console.error("Cabbage: window.sendMessageFromUI is not available yet. Message:",s),console.error("Cabbage: typeof window.sendMessageFromUI:",typeof window.sendMessageFromUI),console.error("Cabbage: window.sendMessageFromUI value:",window.sendMessageFromUI)}static sendWidgetUpdate(e,a=null){const n={command:"widgetStateUpdate",obj:JSON.stringify(CabbageUtils.sanitizeForEditor(e))};a!==null?a.postMessage(n):typeof window.sendMessageFromUI=="function"?window.sendMessageFromUI(n):console.error("Cabbage: window.sendMessageFromUI is not available. Message:",n)}static sendMidiMessageFromUI(e,a,n,s=null){var o={statusByte:e,dataByte1:a,dataByte2:n};const l={command:"midiMessage",obj:JSON.stringify(o)};s!==null?s.postMessage(l):typeof window.sendMessageFromUI=="function"?window.sendMessageFromUI(l):console.error("Cabbage: window.sendMessageFromUI is not available. Message:",l)}static sendChannelData(e,a,n=null){var s={channel:e};if(typeof a=="string")s.stringData=a;else if(typeof a=="number")s.floatData=a;else{console.warn("Cabbage: sendChannelData received unsupported data type:",typeof a);return}const o={command:"channelData",obj:JSON.stringify(s)};console.log("Cabbage: sending channel data from UI",s),n!==null?n.postMessage(o):typeof window.sendMessageFromUI=="function"?window.sendMessageFromUI(o):console.error("Cabbage: window.sendMessageFromUI is not available. Message:",o)}static MidiMessageFromHost(e,a,n){console.log("Cabbage: Got MIDI Message"+e+":"+a+":"+n)}static triggerFileOpenDialog(e,a,n={}){var s={channel:a,directory:n.directory||"",filters:n.filters||"*",openAtLastKnownLocation:n.openAtLastKnownLocation!==void 0?n.openAtLastKnownLocation:!0};const o={command:"fileOpen",obj:JSON.stringify(s)};e!==null?e.postMessage(o):typeof window.sendMessageFromUI=="function"?window.sendMessageFromUI(o):console.error("Cabbage: window.sendMessageFromUI is not available. Message:",o)}static openUrl(e,a,n){var s={url:a,file:n};const o={command:"openUrl",obj:JSON.stringify(s)};e!==null?e.postMessage(o):typeof window.sendMessageFromUI=="function"?window.sendMessageFromUI(o):console.error("Cabbage: window.sendMessageFromUI is not available. Message:",o)}static requestResize(e,a,n=null){const s={command:"requestResize",width:e,height:a};if(n!==null){console.warn("Cabbage: requestResize is not supported in VS Code extension mode");return}else typeof window.sendMessageFromUI=="function"?window.sendMessageFromUI(s):console.error("Cabbage: window.sendMessageFromUI is not available. Message:",s)}}const I=i=>{const[e,a]=u.useState();return u.useEffect(()=>{const n=s=>{const{id:o,widgetJson:l,command:b}=s.data;if(o===i&&l&&b==="widgetUpdate"){const t=JSON.parse(l);console.log(`[Cabbage-React] Received properties for channelId ${o}`,t),a(t)}};return window.addEventListener("message",n),()=>{window.removeEventListener("message",n)}},[]),{properties:e}},C=(i,e)=>{const{properties:a}=I(i),[n,s]=u.useState(),[o,l]=u.useState(),b=t=>{if(o===void 0){console.warn(`[Cabbage-React] parameterIndex not ready for "${i}"`);return}s(t);const d={paramIdx:o,channel:i,value:t,channelType:"number"};f.sendParameterUpdate(d,null)};return u.useEffect(()=>{var r;const t=a==null?void 0:a.channels.find(g=>g.id===i);if(!t)return;const d=t==null?void 0:t.parameterIndex;o===void 0&&d!==void 0&&(console.log(`[Cabbage-React] Received parameterIndex for channelId "${t.id}"`,d),l(d));const c=a==null?void 0:a.value;c!=null&&(console.log(`[Cabbage-React] Received initial value for channelId "${i}"`,c),s(c));const m=(r=t.range)==null?void 0:r.defaultValue;n===void 0&&m!==void 0&&(console.log(`[Cabbage-React] Received default value for channelId "${t.id}"`,m),s(m))},[a]),u.useEffect(()=>{const t=d=>{var m;const{command:c}=d.data;if(c==="parameterChange"){if(e)return;const{value:r,paramIdx:g}=d.data.data;if(g!==o||r===null)return;console.log(`[Cabbage-React] Received parameterChange for parameterIndex ${g}`,r),s(r)}else if(c==="batchWidgetUpdate"){const r=d.data.widgets,g=r==null?void 0:r.find(p=>p.id===i);if(!g)return;const w=JSON.parse(g.widgetJson).channels.find(p=>p.id===i),M=(m=w==null?void 0:w.range)==null?void 0:m.value;console.log(`[Cabbage-React] Received batch widget update for channelId ${g.id}`,M),s(M)}};return window.addEventListener("message",t),()=>{window.removeEventListener("message",t)}},[o]),{value:n,setValue:b,parameterIndex:o}};exports.Cabbage=f;exports.useCabbageProperties=I;exports.useCabbageState=C;
|
package/dist/index.mjs
CHANGED
|
@@ -1,28 +1,62 @@
|
|
|
1
|
-
import { useState as
|
|
1
|
+
import { useState as p, useEffect as M } from "react";
|
|
2
2
|
console.log("Cabbage: loading cabbage.js");
|
|
3
3
|
class f {
|
|
4
4
|
/**
|
|
5
|
-
* Main entry point for sending
|
|
5
|
+
* Main entry point for sending widget value changes to the Cabbage backend.
|
|
6
|
+
*
|
|
6
7
|
* This function automatically routes messages to the appropriate backend function
|
|
7
8
|
* based on the automatable flag:
|
|
8
9
|
*
|
|
9
|
-
* - automatable=true
|
|
10
|
-
*
|
|
10
|
+
* - `automatable=true`: Routes to `sendParameterUpdate()` for DAW-automatable parameters.
|
|
11
|
+
* The value is sent to the DAW for automation recording and also forwarded to Csound.
|
|
12
|
+
*
|
|
13
|
+
* - `automatable=false`: Routes to `sendChannelData()` for non-automatable data.
|
|
14
|
+
* The value is sent directly to Csound without DAW parameter involvement.
|
|
11
15
|
*
|
|
12
|
-
*
|
|
16
|
+
* **When to use**: Call this from widget event handlers (e.g., pointer events, input changes)
|
|
17
|
+
* when the user interacts with a widget.
|
|
13
18
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
19
|
+
* **When NOT to use**: Do not call this when handling incoming `parameterChange` messages
|
|
20
|
+
* from the backend. Those messages are for display updates only.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} message - The message object containing widget data
|
|
23
|
+
* @param {string} message.channel - The channel name
|
|
24
|
+
* @param {number} message.paramIdx - Parameter index (required if automatable)
|
|
25
|
+
* @param {number|string} message.value - The value to send
|
|
26
|
+
* @param {Object|null} vscode - VS Code API object (null for plugin mode)
|
|
27
|
+
* @param {boolean} automatable - Whether this widget is DAW-automatable
|
|
16
28
|
*/
|
|
17
|
-
static sendChannelUpdate(e,
|
|
18
|
-
if (
|
|
19
|
-
f.sendParameterUpdate(e,
|
|
29
|
+
static sendChannelUpdate(e, a = null, n = !1) {
|
|
30
|
+
if (n === !0 || n === 1)
|
|
31
|
+
f.sendParameterUpdate(e, a);
|
|
20
32
|
else {
|
|
21
33
|
const s = e.value !== void 0 ? e.value : e.stringData || e.floatData;
|
|
22
|
-
f.sendChannelData(e.channel, s,
|
|
34
|
+
f.sendChannelData(e.channel, s, a);
|
|
23
35
|
}
|
|
24
36
|
}
|
|
25
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Internal: Send a parameter update to the DAW for automation recording.
|
|
39
|
+
* Use `sendChannelUpdate()` instead - it will route here automatically for automatable widgets.
|
|
40
|
+
*
|
|
41
|
+
* This function sends the parameter value to the DAW's automation system.
|
|
42
|
+
* The DAW will then send the value back via a `parameterChange` message,
|
|
43
|
+
* which updates both the UI and Csound.
|
|
44
|
+
*
|
|
45
|
+
* **Important**: This creates a round-trip through the DAW:
|
|
46
|
+
* 1. UI calls `sendParameterUpdate()` with value
|
|
47
|
+
* 2. DAW receives and records/processes the value
|
|
48
|
+
* 3. DAW sends `parameterChange` back to the plugin
|
|
49
|
+
* 4. Plugin updates Csound and sends `parameterChange` to UI
|
|
50
|
+
* 5. UI updates its display (but does NOT call sendParameterUpdate again!)
|
|
51
|
+
*
|
|
52
|
+
* @param {Object} message - The parameter message
|
|
53
|
+
* @param {number} message.paramIdx - The parameter index (must be >= 0)
|
|
54
|
+
* @param {string} message.channel - The channel name
|
|
55
|
+
* @param {number} message.value - The parameter value (full range, not normalized)
|
|
56
|
+
* @param {string} [message.channelType="number"] - The channel type
|
|
57
|
+
* @param {Object|null} vscode - VS Code API object (null for plugin mode)
|
|
58
|
+
*/
|
|
59
|
+
static sendParameterUpdate(e, a = null) {
|
|
26
60
|
if (e.paramIdx === void 0 || e.paramIdx === null) {
|
|
27
61
|
console.error(
|
|
28
62
|
"Cabbage.sendParameterUpdate: message missing paramIdx!",
|
|
@@ -37,25 +71,25 @@ class f {
|
|
|
37
71
|
);
|
|
38
72
|
return;
|
|
39
73
|
}
|
|
40
|
-
const
|
|
74
|
+
const n = {
|
|
41
75
|
command: "parameterChange",
|
|
42
76
|
paramIdx: e.paramIdx,
|
|
43
77
|
channel: e.channel,
|
|
44
78
|
value: e.value,
|
|
45
79
|
channelType: e.channelType || "number"
|
|
46
80
|
};
|
|
47
|
-
|
|
81
|
+
a !== null ? a.postMessage(n) : typeof window.sendMessageFromUI == "function" ? window.sendMessageFromUI(n) : console.error(
|
|
48
82
|
"Cabbage: window.sendMessageFromUI is not available. Message:",
|
|
49
|
-
|
|
83
|
+
n
|
|
50
84
|
);
|
|
51
85
|
}
|
|
52
|
-
static sendCustomCommand(e,
|
|
86
|
+
static sendCustomCommand(e, a = null, n = {}) {
|
|
53
87
|
const s = {
|
|
54
88
|
command: e,
|
|
55
|
-
text: JSON.stringify(
|
|
89
|
+
text: JSON.stringify(n)
|
|
56
90
|
};
|
|
57
|
-
if (
|
|
58
|
-
|
|
91
|
+
if (a !== null)
|
|
92
|
+
a.postMessage(s);
|
|
59
93
|
else if (typeof window.sendMessageFromUI == "function") {
|
|
60
94
|
console.log("Cabbage: Calling window.sendMessageFromUI with:", s);
|
|
61
95
|
try {
|
|
@@ -76,21 +110,21 @@ class f {
|
|
|
76
110
|
window.sendMessageFromUI
|
|
77
111
|
);
|
|
78
112
|
}
|
|
79
|
-
static sendWidgetUpdate(e,
|
|
80
|
-
const
|
|
113
|
+
static sendWidgetUpdate(e, a = null) {
|
|
114
|
+
const n = {
|
|
81
115
|
command: "widgetStateUpdate",
|
|
82
116
|
obj: JSON.stringify(CabbageUtils.sanitizeForEditor(e))
|
|
83
117
|
};
|
|
84
|
-
|
|
118
|
+
a !== null ? a.postMessage(n) : typeof window.sendMessageFromUI == "function" ? window.sendMessageFromUI(n) : console.error(
|
|
85
119
|
"Cabbage: window.sendMessageFromUI is not available. Message:",
|
|
86
|
-
|
|
120
|
+
n
|
|
87
121
|
);
|
|
88
122
|
}
|
|
89
|
-
static sendMidiMessageFromUI(e,
|
|
123
|
+
static sendMidiMessageFromUI(e, a, n, s = null) {
|
|
90
124
|
var o = {
|
|
91
125
|
statusByte: e,
|
|
92
|
-
dataByte1:
|
|
93
|
-
dataByte2:
|
|
126
|
+
dataByte1: a,
|
|
127
|
+
dataByte2: n
|
|
94
128
|
};
|
|
95
129
|
const l = {
|
|
96
130
|
command: "midiMessage",
|
|
@@ -101,18 +135,31 @@ class f {
|
|
|
101
135
|
l
|
|
102
136
|
);
|
|
103
137
|
}
|
|
104
|
-
|
|
138
|
+
/**
|
|
139
|
+
* @private
|
|
140
|
+
* Internal: Send channel data directly to Csound without DAW automation involvement.
|
|
141
|
+
* Use `sendChannelUpdate()` instead - it will route here automatically for non-automatable widgets.
|
|
142
|
+
*
|
|
143
|
+
* Used for non-automatable widgets like buttons, file selectors, or
|
|
144
|
+
* any widget that sends string data. The value is sent directly to Csound's
|
|
145
|
+
* channel system and is not recorded by DAW automation.
|
|
146
|
+
*
|
|
147
|
+
* @param {string} channel - The Csound channel name
|
|
148
|
+
* @param {number|string} data - The data to send (number or string)
|
|
149
|
+
* @param {Object|null} vscode - VS Code API object (null for plugin mode)
|
|
150
|
+
*/
|
|
151
|
+
static sendChannelData(e, a, n = null) {
|
|
105
152
|
var s = {
|
|
106
153
|
channel: e
|
|
107
154
|
};
|
|
108
|
-
if (typeof
|
|
109
|
-
s.stringData =
|
|
110
|
-
else if (typeof
|
|
111
|
-
s.floatData =
|
|
155
|
+
if (typeof a == "string")
|
|
156
|
+
s.stringData = a;
|
|
157
|
+
else if (typeof a == "number")
|
|
158
|
+
s.floatData = a;
|
|
112
159
|
else {
|
|
113
160
|
console.warn(
|
|
114
161
|
"Cabbage: sendChannelData received unsupported data type:",
|
|
115
|
-
typeof
|
|
162
|
+
typeof a
|
|
116
163
|
);
|
|
117
164
|
return;
|
|
118
165
|
}
|
|
@@ -120,22 +167,22 @@ class f {
|
|
|
120
167
|
command: "channelData",
|
|
121
168
|
obj: JSON.stringify(s)
|
|
122
169
|
};
|
|
123
|
-
console.log("Cabbage: sending channel data from UI", s),
|
|
170
|
+
console.log("Cabbage: sending channel data from UI", s), n !== null ? n.postMessage(o) : typeof window.sendMessageFromUI == "function" ? window.sendMessageFromUI(o) : console.error(
|
|
124
171
|
"Cabbage: window.sendMessageFromUI is not available. Message:",
|
|
125
172
|
o
|
|
126
173
|
);
|
|
127
174
|
}
|
|
128
|
-
static MidiMessageFromHost(e,
|
|
175
|
+
static MidiMessageFromHost(e, a, n) {
|
|
129
176
|
console.log(
|
|
130
|
-
"Cabbage: Got MIDI Message" + e + ":" +
|
|
177
|
+
"Cabbage: Got MIDI Message" + e + ":" + a + ":" + n
|
|
131
178
|
);
|
|
132
179
|
}
|
|
133
|
-
static triggerFileOpenDialog(e,
|
|
180
|
+
static triggerFileOpenDialog(e, a, n = {}) {
|
|
134
181
|
var s = {
|
|
135
|
-
channel:
|
|
136
|
-
directory:
|
|
137
|
-
filters:
|
|
138
|
-
openAtLastKnownLocation:
|
|
182
|
+
channel: a,
|
|
183
|
+
directory: n.directory || "",
|
|
184
|
+
filters: n.filters || "*",
|
|
185
|
+
openAtLastKnownLocation: n.openAtLastKnownLocation !== void 0 ? n.openAtLastKnownLocation : !0
|
|
139
186
|
};
|
|
140
187
|
const o = {
|
|
141
188
|
command: "fileOpen",
|
|
@@ -146,10 +193,10 @@ class f {
|
|
|
146
193
|
o
|
|
147
194
|
);
|
|
148
195
|
}
|
|
149
|
-
static openUrl(e,
|
|
196
|
+
static openUrl(e, a, n) {
|
|
150
197
|
var s = {
|
|
151
|
-
url:
|
|
152
|
-
file:
|
|
198
|
+
url: a,
|
|
199
|
+
file: n
|
|
153
200
|
};
|
|
154
201
|
const o = {
|
|
155
202
|
command: "openUrl",
|
|
@@ -160,90 +207,128 @@ class f {
|
|
|
160
207
|
o
|
|
161
208
|
);
|
|
162
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Request a resize of the plugin GUI window.
|
|
212
|
+
* This is only supported in plugin mode (CLAP/VST3/AUv2).
|
|
213
|
+
* The host may accept or reject the resize request.
|
|
214
|
+
*
|
|
215
|
+
* @param {number} width - The requested width in pixels
|
|
216
|
+
* @param {number} height - The requested height in pixels
|
|
217
|
+
* @param {object} vscode - The vscode API object (null for plugin mode)
|
|
218
|
+
*
|
|
219
|
+
* The response will be sent via hostMessageCallback with:
|
|
220
|
+
* {command: "resizeResponse", accepted: boolean, width: number, height: number}
|
|
221
|
+
*/
|
|
222
|
+
static requestResize(e, a, n = null) {
|
|
223
|
+
const s = {
|
|
224
|
+
command: "requestResize",
|
|
225
|
+
width: e,
|
|
226
|
+
height: a
|
|
227
|
+
};
|
|
228
|
+
if (n !== null) {
|
|
229
|
+
console.warn(
|
|
230
|
+
"Cabbage: requestResize is not supported in VS Code extension mode"
|
|
231
|
+
);
|
|
232
|
+
return;
|
|
233
|
+
} else
|
|
234
|
+
typeof window.sendMessageFromUI == "function" ? window.sendMessageFromUI(s) : console.error(
|
|
235
|
+
"Cabbage: window.sendMessageFromUI is not available. Message:",
|
|
236
|
+
s
|
|
237
|
+
);
|
|
238
|
+
}
|
|
163
239
|
}
|
|
164
|
-
const
|
|
165
|
-
const [e,
|
|
166
|
-
return
|
|
167
|
-
const
|
|
168
|
-
const { id: o, widgetJson: l, command:
|
|
169
|
-
if (o ===
|
|
170
|
-
const
|
|
240
|
+
const U = (i) => {
|
|
241
|
+
const [e, a] = p();
|
|
242
|
+
return M(() => {
|
|
243
|
+
const n = (s) => {
|
|
244
|
+
const { id: o, widgetJson: l, command: u } = s.data;
|
|
245
|
+
if (o === i && l && u === "widgetUpdate") {
|
|
246
|
+
const t = JSON.parse(l);
|
|
171
247
|
console.log(
|
|
172
248
|
`[Cabbage-React] Received properties for channelId ${o}`,
|
|
173
|
-
|
|
174
|
-
),
|
|
249
|
+
t
|
|
250
|
+
), a(t);
|
|
175
251
|
}
|
|
176
252
|
};
|
|
177
|
-
return window.addEventListener("message",
|
|
178
|
-
window.removeEventListener("message",
|
|
253
|
+
return window.addEventListener("message", n), () => {
|
|
254
|
+
window.removeEventListener("message", n);
|
|
179
255
|
};
|
|
180
256
|
}, []), {
|
|
181
257
|
properties: e
|
|
182
258
|
};
|
|
183
|
-
},
|
|
184
|
-
const { properties:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
259
|
+
}, h = (i, e) => {
|
|
260
|
+
const { properties: a } = U(i), [n, s] = p(), [o, l] = p(), u = (t) => {
|
|
261
|
+
if (o === void 0) {
|
|
262
|
+
console.warn(
|
|
263
|
+
`[Cabbage-React] parameterIndex not ready for "${i}"`
|
|
264
|
+
);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
s(t);
|
|
268
|
+
const d = {
|
|
269
|
+
paramIdx: o,
|
|
270
|
+
channel: i,
|
|
271
|
+
value: t,
|
|
272
|
+
channelType: "number"
|
|
273
|
+
};
|
|
274
|
+
f.sendParameterUpdate(d, null);
|
|
192
275
|
};
|
|
193
|
-
return
|
|
194
|
-
var
|
|
195
|
-
const t =
|
|
196
|
-
(g) => g.id ===
|
|
276
|
+
return M(() => {
|
|
277
|
+
var r;
|
|
278
|
+
const t = a == null ? void 0 : a.channels.find(
|
|
279
|
+
(g) => g.id === i
|
|
197
280
|
);
|
|
198
281
|
if (!t) return;
|
|
199
|
-
const
|
|
200
|
-
|
|
282
|
+
const d = t == null ? void 0 : t.parameterIndex;
|
|
283
|
+
o === void 0 && d !== void 0 && (console.log(
|
|
201
284
|
`[Cabbage-React] Received parameterIndex for channelId "${t.id}"`,
|
|
202
|
-
|
|
203
|
-
),
|
|
204
|
-
const c =
|
|
285
|
+
d
|
|
286
|
+
), l(d));
|
|
287
|
+
const c = a == null ? void 0 : a.value;
|
|
205
288
|
c != null && (console.log(
|
|
206
|
-
`[Cabbage-React] Received initial value for channelId "${
|
|
289
|
+
`[Cabbage-React] Received initial value for channelId "${i}"`,
|
|
207
290
|
c
|
|
208
|
-
),
|
|
209
|
-
const m = (
|
|
291
|
+
), s(c));
|
|
292
|
+
const m = (r = t.range) == null ? void 0 : r.defaultValue;
|
|
210
293
|
n === void 0 && m !== void 0 && (console.log(
|
|
211
294
|
`[Cabbage-React] Received default value for channelId "${t.id}"`,
|
|
212
295
|
m
|
|
213
|
-
),
|
|
214
|
-
}, [
|
|
215
|
-
const t = (
|
|
296
|
+
), s(m));
|
|
297
|
+
}, [a]), M(() => {
|
|
298
|
+
const t = (d) => {
|
|
216
299
|
var m;
|
|
217
|
-
const { command: c } =
|
|
300
|
+
const { command: c } = d.data;
|
|
218
301
|
if (c === "parameterChange") {
|
|
219
|
-
|
|
220
|
-
|
|
302
|
+
if (e) return;
|
|
303
|
+
const { value: r, paramIdx: g } = d.data.data;
|
|
304
|
+
if (g !== o || r === null) return;
|
|
221
305
|
console.log(
|
|
222
306
|
`[Cabbage-React] Received parameterChange for parameterIndex ${g}`,
|
|
223
|
-
|
|
224
|
-
),
|
|
307
|
+
r
|
|
308
|
+
), s(r);
|
|
225
309
|
} else if (c === "batchWidgetUpdate") {
|
|
226
|
-
const
|
|
310
|
+
const r = d.data.widgets, g = r == null ? void 0 : r.find((b) => b.id === i);
|
|
227
311
|
if (!g) return;
|
|
228
|
-
const
|
|
229
|
-
(
|
|
230
|
-
),
|
|
312
|
+
const w = JSON.parse(g.widgetJson).channels.find(
|
|
313
|
+
(b) => b.id === i
|
|
314
|
+
), I = (m = w == null ? void 0 : w.range) == null ? void 0 : m.value;
|
|
231
315
|
console.log(
|
|
232
316
|
`[Cabbage-React] Received batch widget update for channelId ${g.id}`,
|
|
233
|
-
|
|
234
|
-
),
|
|
317
|
+
I
|
|
318
|
+
), s(I);
|
|
235
319
|
}
|
|
236
320
|
};
|
|
237
321
|
return window.addEventListener("message", t), () => {
|
|
238
322
|
window.removeEventListener("message", t);
|
|
239
323
|
};
|
|
240
|
-
}, [
|
|
324
|
+
}, [o]), {
|
|
241
325
|
value: n,
|
|
242
|
-
setValue:
|
|
326
|
+
setValue: u,
|
|
327
|
+
parameterIndex: o
|
|
243
328
|
};
|
|
244
329
|
};
|
|
245
330
|
export {
|
|
246
331
|
f as Cabbage,
|
|
247
|
-
|
|
248
|
-
|
|
332
|
+
U as useCabbageProperties,
|
|
333
|
+
h as useCabbageState
|
|
249
334
|
};
|