Canvas2DMX is backend-agnostic. It doesnβt depend on any specific DMX library (ENTTEC, DMX4Artists, Art-Net, sACN, OLA, etc.).
Instead, it exposes a tiny callback so you can adapt any sender with one line.
@FunctionalInterface
public interface DmxSender {
void send(int channel, int value);
}
Canvas2DMX emits channel/value pairs using your current mapping + channel pattern:
c2d.sendToDmx((ch, val) -> {
// bridge to your backend here
dmxController.sendValue(ch, val);
});
Why this approach?
c2d.sendToDmx((ch, val) -> dmx.sendValue(ch, val));
int[] frame = c2d.buildDmxFrame(512); // 1-based DMX mapped into 0-based array
artnet.writeUniverse(0, frame); // hypothetical bulk API
DMX4Artists (ENTTEC / serial)
import com.jaysonh.dmx4artists.*;
DMXControl dmx = new DMXControl(0, 512);
c2d.sendToDmx((ch, val) -> dmx.sendValue(ch, val));
Mock sender (testing / no hardware)
c2d.sendToDmx((ch, val) -> {
if (ch <= 16 && frameCount % 30 == 0) println("ch " + ch + " = " + val);
});
Art-Net / sACN style (batch)
int[] frame = c2d.buildDmxFrame(512);
// e.g., convert to byte[] and send in one call (pseudo-code)
// byte[] bytes = new byte[frame.length];
// for (int i = 0; i < frame.length; i++) bytes[i] = (byte) (frame[i] & 0xFF);
// artnet.writeUniverse(0, bytes);
BiConsumer<Integer,Integer>
?We considered an overload that accepted BiConsumer<Integer,Integer>
.
However, having both sendToDmx(DmxSender)
and sendToDmx(BiConsumer<β¦>)
made lambdas ambiguous for the Java compiler.
To keep the API simple and reliable, we kept only the DmxSender
version.
You still get one-line lambda calls, and the library stays backend-agnostic.
MIT License Β© 2025 Studio Jordan Shaw