Skip to content

Commit 5edb064

Browse files
Indicated per-part mode by accent in Cambiare.
1 parent ad98a7d commit 5edb064

File tree

4 files changed

+153
-26
lines changed

4 files changed

+153
-26
lines changed

src/basic/index.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ let RootDisplay = class extends CustomEventSource {
537537
(upThis.#metaRun[e.meta] || console.debug).call(upThis, e.meta, e.data);
538538
});
539539
});
540+
// This is asking for trouble
540541
eventPassThru(upThis.device, upThis, "mode");
541542
eventPassThru(upThis.device, upThis, "mastervolume");
542543
eventPassThru(upThis.device, upThis, "channelactive");
@@ -561,6 +562,7 @@ let RootDisplay = class extends CustomEventSource {
561562
eventPassThru(upThis.device, upThis, "efxinsert2");
562563
eventPassThru(upThis.device, upThis, "efxinsert3");
563564
eventPassThru(upThis.device, upThis, "partefxtoggle");
565+
eventPassThru(upThis.device, upThis, "chmode");
564566
upThis.addEventListener("note", function ({data}) {
565567
upThis.#noteEvents.push(data);
566568
//console.debug(data);

src/cambiare/index.mjs

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ const modeColourPool = {
112112
"sd": ["ffe1a5", "804e00"],
113113
"sg": ["ffdddd", "990022"]
114114
};
115+
/*const modeGlobalClasses = [];
116+
for (let mode in modeNames) {
117+
modeGlobalClasses.push(`cambiare-mode-${mode}`);
118+
};*/
115119

116120
piMulti.forEach((e, i, a) => {
117121
a[i] = Math.PI * i / 12;
@@ -239,6 +243,8 @@ let Cambiare = class extends RootDisplay {
239243
#canvas;
240244
#pixelProfile;
241245
#accent = "fcdaff";
246+
#chAccent = new Array(allocated.ch);
247+
#chMode = new Array(allocated.ch);
242248
#foreground = "ffffff";
243249
#mode = "?";
244250
#sectInfo = {};
@@ -253,7 +259,7 @@ let Cambiare = class extends RootDisplay {
253259
#style = "comb";
254260
glyphs = new MxFont40();
255261
panStyle = 11; // Block, Pin, Arc, Dash
256-
#drawNote(context, note, velo, state = 0, pitch = 0) {
262+
#drawNote(context, note, velo, state = 0, pitch = 0, part) {
257263
// Param calculation
258264
let upThis = this;
259265
let {width, height} = context.canvas;
@@ -290,7 +296,7 @@ let Cambiare = class extends RootDisplay {
290296
};
291297
};
292298
// Colours
293-
context.fillStyle = `#${isBlackKey ? (upThis.#accent) : (upThis.#foreground)}${((velo << 1) | (velo >> 6)).toString(16).padStart(2, "0")}`;
299+
context.fillStyle = `#${isBlackKey ? (upThis.getChAccent(part)) : (upThis.#foreground)}${((velo << 1) | (velo >> 6)).toString(16).padStart(2, "0")}`;
294300
context.strokeStyle = context.fillStyle;
295301
context.lineWidth = range == 1 ? 4 : 2;
296302
context.lineDashOffset = 0;
@@ -360,7 +366,7 @@ let Cambiare = class extends RootDisplay {
360366
let context = upThis.#sectPart[part >> 4][part & 15].cxt;
361367
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
362368
sum.chKeyPr[part].forEach(({v, s}, note) => {
363-
upThis.#drawNote(context, note, v, s, upThis.device.getPitchShift(part));
369+
upThis.#drawNote(context, note, v, s, upThis.device.getPitchShift(part), part);
364370
});
365371
};
366372
});
@@ -429,13 +435,13 @@ let Cambiare = class extends RootDisplay {
429435
chOff = part * allocated.cc,
430436
aceOff = part * allocated.ace,
431437
e = upThis.#sectPart[port][part & 15];
432-
if (sum.chInUse[part] && port >= upThis.#renderPort && port < renderPortMax) {
438+
if (visualizer.device.getActive()[part] && port >= upThis.#renderPort && port < renderPortMax) {
433439
// Render CC draw calls
434440
ccCandidates[8] = sum.ace[aceOff + 0] || 256;
435441
ccCandidates[9] = sum.ace[aceOff + 1] || 256;
436442
e.ccVis.clearRect(0, 0, 109, 25);
437-
e.ccVis.fillStyle = `#${upThis.#accent}`;
438-
e.ccVis.strokeStyle = `#${upThis.#accent}`;
443+
e.ccVis.fillStyle = `#${upThis.getChAccent(part)}`;
444+
e.ccVis.strokeStyle = `#${upThis.getChAccent(part)}`;
439445
e.ccVis.lineWidth = 2;
440446
for (let cci = 0; cci < ccCandidates.length; cci ++) {
441447
let cce = ccCandidates[cci];
@@ -601,7 +607,7 @@ let Cambiare = class extends RootDisplay {
601607
e.extVis.lineTo(7 + velocity, 12);
602608
e.extVis.lineTo(0, 12 + mouth + 3);
603609
e.extVis.fill();
604-
e.extVis.fillStyle = `#${upThis.#accent}`;
610+
e.extVis.fillStyle = `#${upThis.getChAccent(part)}`;
605611
e.extVis.beginPath();
606612
e.extVis.ellipse(43, 12, 4, 4 + breathNoise, 0, 0, fullRotation);
607613
e.extVis.fill();
@@ -612,7 +618,7 @@ let Cambiare = class extends RootDisplay {
612618
let dxView = sum.chContr.subarray(chOff + ccToPos[142], chOff + ccToPos[157] + 1);
613619
dxView.forEach((v, i) => {
614620
if (i >= 8) {
615-
e.extVis.fillStyle = `#${upThis.#accent}`;
621+
e.extVis.fillStyle = `#${upThis.getChAccent(part)}`;
616622
};
617623
let x = i * 3;
618624
let size = (v - 64) / 5.82;
@@ -650,7 +656,7 @@ let Cambiare = class extends RootDisplay {
650656
sum.extraNotes.forEach((ev) => {
651657
let {part, note, velo, state} = ev;
652658
let context = upThis.#sectPart[part >> 4][part & 15].cxt;
653-
upThis.#drawNote(context, note, velo, state, upThis.device.getPitchShift(part));
659+
upThis.#drawNote(context, note, velo, state, upThis.device.getPitchShift(part), part);
654660
//console.debug(part, note);
655661
});
656662
// Write to the new pixel display buffers
@@ -775,6 +781,24 @@ let Cambiare = class extends RootDisplay {
775781
classOff(upThis.#canvas, [`cambiare-style-block`, `cambiare-style-comb`, `cambiare-style-piano`, `cambiare-style-line`]);
776782
classOn(upThis.#canvas, [`cambiare-style-${value}`]);
777783
};
784+
getChMode(part = 0, disableFallback) {
785+
if (part >= allocated.ch) {
786+
throw(new RangeError("Invalid part number"));
787+
};
788+
let upThis = this;
789+
if (disableFallback) {
790+
return upThis.#chMode[part];
791+
} else {
792+
return upThis.#chMode[part] ?? upThis.#mode;
793+
};
794+
};
795+
getChAccent(part = 0) {
796+
if (part >= allocated.ch) {
797+
throw(new RangeError("Invalid part number"));
798+
};
799+
let upThis = this;
800+
return upThis.#chAccent[part] ?? upThis.#accent;
801+
};
778802
setClockSource(clockSource) {
779803
this.#clockSource = clockSource;
780804
};
@@ -797,19 +821,48 @@ let Cambiare = class extends RootDisplay {
797821
};
798822
setMode(mode) {
799823
let upThis = this;
800-
classOff(upThis.#canvas, [`cambiare-mode-gm`, `cambiare-mode-xg`, `cambiare-mode-gs`, `cambiare-mode-sc`, `cambiare-mode-ns5r`, `cambiare-mode-05rw`, `cambiare-mode-x5d`, `cambiare-mode-k11`, `cambiare-mode-sg`, `cambiare-mode-g2`, `cambiare-mode-mt32`, `cambiare-mode-doc`, `cambiare-mode-qy10`, `cambiare-mode-qy20`, `cambiare-mode-sd`, `cambiare-mode-krs`, `cambiare-mode-s90es`, `cambiare-mode-motif`]);
801-
if (mode != "?") {
802-
classOn(upThis.#canvas, [`cambiare-mode-${mode}`]);
803-
};
804824
upThis.#mode = mode;
805825
upThis.#accent = (modeColourPool[mode] || ["fcdaff", "742b81"])[upThis.#scheme];
826+
//classOff(upThis.#canvas, modeGlobalClasses);
827+
for (let className of upThis.#canvas.classList) {
828+
if (className.substring(0, 14) === "cambiare-mode-") {
829+
upThis.#canvas.classList.remove(className);
830+
};
831+
};
832+
if (mode != "?") {
833+
upThis.#canvas.classList.add(`cambiare-mode-${mode}`);
834+
};
835+
};
836+
setChMode(part, mode) {
837+
let upThis = this;
838+
upThis.#chMode[part] = mode;
839+
let partViewer = upThis.#sectPart[part >> 4][part & 15];
840+
for (let className of partViewer.root.classList) {
841+
if (className.substring(0, 10) == "part-mode-") {
842+
partViewer.root.classList.remove(className);
843+
};
844+
};
845+
if (mode != "?") {
846+
partViewer.root.classList.add(`part-mode-${mode}`);
847+
};
806848
};
807849
setScheme(scheme = 0) {
808850
let upThis = this;
809851
upThis.#scheme = scheme ? 1 : 0;
810852
upThis.#foreground = ["ffffff", "000000"][upThis.#scheme];
811853
[classOff, classOn][upThis.#scheme](upThis.#canvas, [`cambiare-scheme-light`]);
812854
upThis.#accent = (modeColourPool[upThis.#mode] || ["fcdaff", "742b81"])[upThis.#scheme];
855+
for (let part = 0; part < allocated.ch; part ++) {
856+
if (upThis.device.getChActive(part) === 0) {
857+
continue;
858+
};
859+
if (upThis.#chAccent[part]) {
860+
let targetColour = modeColourPool[upThis.#chMode[part]];
861+
if (targetColour) {
862+
upThis.#chAccent[part] = targetColour[upThis.#scheme];
863+
};
864+
};
865+
};
813866
};
814867
#setPortView(canvasUpdate) {
815868
let upThis = this;
@@ -1270,6 +1323,8 @@ let Cambiare = class extends RootDisplay {
12701323
let upThis = this;
12711324
upThis.#resizer = upThis.#resizerSrc.bind(this);
12721325
upThis.#renderer = upThis.#rendererSrc.bind(this);
1326+
upThis.#chAccent.fill(null);
1327+
upThis.#chMode.fill(null);
12731328
if (attachElement) {
12741329
upThis.attach(attachElement);
12751330
};
@@ -1284,6 +1339,8 @@ let Cambiare = class extends RootDisplay {
12841339
upThis.#metaType = "";
12851340
upThis.#metaLastLine = null;
12861341
upThis.#underlinedCh = allocated.invalidCh;
1342+
upThis.#chAccent.fill(null);
1343+
upThis.#chMode.fill(null);
12871344
try {
12881345
// Remove all meta
12891346
let list = upThis.#sectMeta.view.children;
@@ -1315,6 +1372,18 @@ let Cambiare = class extends RootDisplay {
13151372
upThis.#noteEvents.push(data);
13161373
//console.debug(data);
13171374
});*/
1375+
upThis.addEventListener("chmode", ({data}) => {
1376+
let {part, mode} = data;
1377+
/* classOn(upThis.#sectPart[part >> 4][part & 15]?.root, [
1378+
`part-mode-${mode}`
1379+
]); */
1380+
upThis.setChMode(part, mode);
1381+
let resultColour = modeColourPool[mode];
1382+
if (resultColour) {
1383+
upThis.#chAccent[part] = resultColour[upThis.#scheme];
1384+
};
1385+
console.debug(part, mode);
1386+
});
13181387
upThis.addEventListener("pitch", ({data}) => {
13191388
upThis.#pitchEvents.push(data);
13201389
});

src/state/index.mjs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,11 +1313,18 @@ let OctaviaDevice = class extends CustomEventSource {
13131313
//};
13141314
return result;
13151315
};
1316+
getChActive(part) {
1317+
return this.#chActive[part];
1318+
};
13161319
getCc(part) {
13171320
// Return channel CC registers
13181321
// Potential bug exists here
1322+
if (typeof part !== "number" || part < 0 || part >= allocated.ch) {
1323+
throw(new RangeError(`Invalid part number: CH${part + 1}`));
1324+
return;
1325+
};
13191326
let upThis = this;
1320-
let start = ccOffTable[channel];
1327+
let start = ccOffTable[part];
13211328
let arr = upThis.#cc.subarray(start, start + allocated.cc);
13221329
/* arr[ccToPos[0]] = arr[ccToPos[0]] || upThis.#subDb[upThis.getChModeId(channel)][0];
13231330
arr[ccToPos[32]] = arr[ccToPos[32]] || upThis.#subDb[upThis.getChModeId(channel)][1];
@@ -1359,6 +1366,9 @@ let OctaviaDevice = class extends CustomEventSource {
13591366
let posCache = ccOffTable[part] + ccToPos[cc];
13601367
upThis.#cc[posCache] = data;
13611368
upThis.#cc[posCache + allocated.chcc] = 1;
1369+
if (part == 9) {
1370+
console.debug(part, cc, value);
1371+
};
13621372
upThis.dispatchEvent("cc", {
13631373
part,
13641374
cc,
@@ -1567,8 +1577,8 @@ let OctaviaDevice = class extends CustomEventSource {
15671577
throw(new RangeError(`Invalid voice primitive component "${component}"`));
15681578
return;
15691579
};
1570-
if (part >= allocated.ch) {
1571-
throw(new RangeError(`Invalid part "CH${part + 1}"`));
1580+
if (typeof part !== "number" || part < 0 || part >= allocated.ch) {
1581+
throw(new RangeError(`Invalid part number: CH${part + 1}`));
15721582
return;
15731583
};
15741584
let upThis = this;
@@ -1993,15 +2003,20 @@ let OctaviaDevice = class extends CustomEventSource {
19932003
setChMode(part, modeId) {
19942004
// Per-channel mode
19952005
let upThis = this;
1996-
if (part < 0 || part >= allocated.ch) {
1997-
throw(new RangeError(`Invalid CH${part + 1}`));
2006+
if (typeof part !== "number" || part < 0 || part >= allocated.ch) {
2007+
throw(new RangeError(`Invalid part number: CH${part + 1}`));
19982008
return;
19992009
};
20002010
if (port < 0 || modeId >= modeIdx.length) {
20012011
throw(new RangeError(`Invalid mode ID ${modeId}`));
20022012
return;
20032013
};
20042014
upThis.#chMode[part] = modeId;
2015+
upThis.dispatchEvent("chmode", {
2016+
part,
2017+
id: modeId,
2018+
mode: modeIdx[modeId]
2019+
});
20052020
upThis.dispatchEvent("voice", {
20062021
part
20072022
});
@@ -2037,6 +2052,11 @@ let OctaviaDevice = class extends CustomEventSource {
20372052
for (let sect = port; sect < port + range; sect ++) {
20382053
upThis.#portMode[sect] = modeId;
20392054
for (let part = sect << 4; part < ((sect + 1) << 4); part ++) {
2055+
upThis.dispatchEvent("chmode", {
2056+
part,
2057+
id: modeId,
2058+
mode: modeIdx[modeId]
2059+
});
20402060
upThis.dispatchEvent("voice", {
20412061
part
20422062
});

test/css/cambiare.css

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,39 @@ div.cambiare-canvas.cambiare-mode-x5d,
3939
div.cambiare-canvas.cambiare-mode-05rw,
4040
div.cambiare-canvas.cambiare-mode-k11,
4141
div.cambiare-canvas.cambiare-mode-s90es,
42-
div.cambiare-canvas.cambiare-mode-motif {
42+
div.cambiare-canvas.cambiare-mode-motif,
43+
div.cambiare-canvas div.part-channel.part-mode-xg,
44+
div.cambiare-canvas div.part-channel.part-mode-doc,
45+
div.cambiare-canvas div.part-channel.part-mode-qy10,
46+
div.cambiare-canvas div.part-channel.part-mode-qy20,
47+
div.cambiare-canvas div.part-channel.part-mode-ns5r,
48+
div.cambiare-canvas div.part-channel.part-mode-x5d,
49+
div.cambiare-canvas div.part-channel.part-mode-05rw,
50+
div.cambiare-canvas div.part-channel.part-mode-k11,
51+
div.cambiare-canvas div.part-channel.part-mode-s90es,
52+
div.cambiare-canvas div.part-channel.part-mode-motif {
4353
--accent-color: #9efaa0;
4454
}
4555
div.cambiare-canvas.cambiare-mode-gm,
4656
div.cambiare-canvas.cambiare-mode-g2,
47-
div.cambiare-canvas.cambiare-mode-krs {
57+
div.cambiare-canvas.cambiare-mode-krs,
58+
div.cambiare-canvas div.part-channel.part-mode-gm,
59+
div.cambiare-canvas div.part-channel.part-mode-g2,
60+
div.cambiare-canvas div.part-channel.part-mode-krs {
4861
--accent-color: #a1f3ff;
4962
}
5063
div.cambiare-canvas.cambiare-mode-gs,
5164
div.cambiare-canvas.cambiare-mode-sc,
5265
div.cambiare-canvas.cambiare-mode-mt32,
53-
div.cambiare-canvas.cambiare-mode-sd {
66+
div.cambiare-canvas.cambiare-mode-sd,
67+
div.cambiare-canvas div.part-channel.part-mode-gs,
68+
div.cambiare-canvas div.part-channel.part-mode-sc,
69+
div.cambiare-canvas div.part-channel.part-mode-mt32,
70+
div.cambiare-canvas div.part-channel.part-mode-sd {
5471
--accent-color: #ffe1a5;
5572
}
56-
div.cambiare-canvas.cambiare-mode-sg {
73+
div.cambiare-canvas.cambiare-mode-sg,
74+
div.cambiare-canvas div.part-channel.part-mode-sg {
5775
--accent-color: #fdd;
5876
}
5977
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-xg,
@@ -65,21 +83,39 @@ div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-x5d,
6583
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-05rw,
6684
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-k11,
6785
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-s90es,
68-
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-motif {
86+
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-motif,
87+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-xg,
88+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-doc,
89+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-qy10,
90+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-qy20,
91+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-ns5r,
92+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-x5d,
93+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-05rw,
94+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-k11,
95+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-s90es,
96+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-motif {
6997
--accent-color: #006415;
7098
}
7199
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-gm,
72100
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-g2,
73-
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-krs {
101+
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-krs,
102+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-gm,
103+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-g2,
104+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-krs {
74105
--accent-color: #005e88;
75106
}
76107
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-gs,
77108
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-sc,
78109
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-mt32,
79-
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-sd {
110+
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-sd,
111+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-gs,
112+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-sc,
113+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-mt32,
114+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-sd {
80115
--accent-color: #804e00;
81116
}
82-
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-sg {
117+
div.cambiare-canvas.cambiare-scheme-light.cambiare-mode-sg,
118+
div.cambiare-canvas.cambiare-scheme-light div.part-channel.part-mode-sg {
83119
--accent-color: #902;
84120
}
85121

0 commit comments

Comments
 (0)