Unofficial Node.js API for Loupedeck Live, Loupedeck Live S, Loupedeck CT and Razer Stream controllers.

Supports:
This library has been tested with firmware versions 0.1.3, 0.1.79, 0.2.5, 0.2.8 and 0.2.23. Other versions may work.
Note: Firmware version 0.2.26 does not seem to work on Linux. Recommendation is to downgrade to 0.2.23 (see #30)
npm install loupedeck
By default, Loupdeck devices uses RGB565 (16-bit) buffers for drawing (with small exceptions, see below), so the canvas module is used to enable a more pleasant API that allows for drawing using Canvas API callbacks.
Note: Ensure Loupedeck software is not running as it may conflict with this library
import { discover } from 'loupedeck'
// Detects and opens first connected device
const device = await discover()
// Observe connect events
device.on('connect', () => {
console.info('Connection successful!')
})
// React to button presses
device.on('down', ({ id }) => {
console.info(`Button pressed: ${id}`)
})
// React to knob turns
device.on('rotate', ({ id, delta }) => {
console.info(`Knob ${id} rotated: ${delta}`)
})
import { LoupedeckLiveS } from 'loupedeck'
const device = new LoupedeckLiveS({ path: '/dev/tty.usbmodem101', autoConnect: false })
await device.connect()
console.info('Connection successful!')
device.on('down', ({ id }) => {
console.info(`Button pressed: ${id}`)
})
For all examples, see the examples folder. Running some examples requires canvas to be installed (see above).
discover() : Promise<LoupedeckDevice>Find the first connected Loupedeck device and return it.
Returns an instance of LoupedeckLive, LoupedeckLiveS, LoupedeckCT, RazerStreamController, RazerStreamControllerX, or throws an Error in case none or unsupported devices are found.
LoupedeckLiveImplements and supports all methods from the LoupedeckDevice interface.
new LoupedeckLive({ path : String?, host : String?, autoConnect : Boolean? })Create a new Loupedeck Live device interface.
Most use-cases should omit the host/path parameter, unless you're using multiple devices or know specifically which IP or device path you want to connect to. Either use path OR host, never both.
path: (Firmware 0.2.X only) Serial device path (example: /dev/cu.ttymodem-1332 or COM2) (default: autodiscover)host: (Firmware 0.1.X only) Host or IP address to connect to (example: 127.100.1.1) (default: autodiscover)autoConnect: Automatically connect during construction. (default: true) Set to false if you'd prefer to call connect(). yourself.reconnectInterval: How many milliseconds to wait before attempting a reconnect after a failed connection (default: 3000) Set to false to turn off automatic reconnects.LoupedeckCTSame interface as LoupedeckLive.
LoupedeckLiveSSame interface as LoupedeckLive.
RazerStreamControllerSame interface as LoupedeckLive.
RazerStreamControllerXSame interface as LoupedeckLive.
Does not implement vibration or button colors.
LoupedeckDeviceShared device interface. Do not instantiate this manually, use one of the above classes instead or the discover() function.
All incoming messages are emitted as action events and can be subscribed to via device.on().
LoupedeckDevice.list({ ignoreSerial : Boolean?, ignoreWebsocket : Boolean?} = {}) : Promise<Array>Static method to scan for and return a list of all detected devices. This includes ones which are already opened.
ignoreSerial: Ignore devices which operate over serial (Firmware 0.2.X) (default: false)ignoreWebsocket: Ignore devices which operate over websocket (Firmware 0.1.X) (default: false)Device info can be directly passed on to the constructor below.
'connect'Emitted when connection to the device succeeds. Includes an info object containing:
address: Connection address (E.G. serial path or websocket address)'disconnect'Emitted when a device disconnects for any reason. First argument for the event is an Error object in case of an abnormal disconnect (otherwise undefined).
'down'Emitted when a button or knob is pressed down.
Arguments:
id: Button ID (see constants.js for possible IDs)'rotate'Emitted when a knob is rotated.
Arguments:
id: Button ID (see constants.js for possible IDs)delta: Rotation direction, -1 for counter-clockwise, 1 for clockwise.'touchstart'Emitted when any part of the screen is touched for the first time.
Arguments:
changedTouches: Array of new touches created during this eventtouches: Array of all currently held touches on screen'touchmove'Emitted when a touch moves across the screen.
Arguments:
changedTouches: Array of touches changed during this eventtouches: Array of all currently held touches on screen'touchend'Emitted when a touch is no longer detected.
Arguments:
changedTouches: Array of touches removed during this eventtouches: Array of all currently held touches on screen (if any)'up'Emitted when a button or knob is released.
Arguments:
id: Button ID (see constants.js for possible IDs)device.close() : PromiseClose device connection.
Returns Promise which resolves once the device has been closed.
device.connect() : PromiseManually connect. Resolves on success.
device.drawBuffer({ id : String, width : Number, height : Number, x? : Number, y? : Number, autoRefresh? : Boolean }, buffer : Buffer) : PromiseDraw graphics to a particular area using a RGB16-565 pixel buffer.
Lower-level method if drawKey() or drawScreen() don't meet your needs.
id: Screen to write to [left, center, right, knob] (left and right available on Loupedeck Live / RSC only) (knob available on Loupedeck CT only)width: Width of area to drawheight: Height of area to drawx: Starting X offset (default: 0)y: Starting Y offset (default: 0)autoRefresh: Whether to refresh the screen after drawing (default: true)buffer: RGB16-565 Buffer. Should be width * height * 2 bytes long, with each pixel represented by 2 bytes (5 bits red, 6 bits green, 5 bits blue) in little-endian (LE). Note: Loupedeck CT knob screen is the only exception, it uses big-endian (BE)Returns a Promise which resolves once the command has been acknowledged by the device.
device.drawCanvas({ id : String, width : Number, height : Number, x? : Number, y? : Number, autoRefresh? : Boolean }, callback : Function) : PromiseDraw graphics to a particular area using the Canvas API.
Lower-level method if drawKey() or drawScreen() don't meet your needs.
id: Screen to write to [left, center, right, knob] (left and right available on Loupedeck Live / RSC only) (knob available on Loupedeck CT only)width: Width of area to drawheight: Height of area to drawx: Starting X offset (default: 0)y: Starting Y offset (default: 0)autoRefresh: Whether to refresh the screen after drawing (default: true)callback: Function to handle draw calls. Receives the following arguments:
context: 2d canvas graphics contextwidth: Width of drawing areaheight: Height of drawing areaReturns a Promise which resolves once the command has been acknowledged by the device.
device.drawKey(key : Number, buffer/callback : Buffer/Function) : PromiseDraw graphics to a specific key.
Second argument can be either a RGB16-565 buffer or a callback. Width and height of callback will typically be 90, as keys are mostly 90x90px (RSCX being the exception - those keys are 96x96px).
key: Key index to write to ([0-11] on Loupedeck Live/Loupedeck CT/RSC, [0-14] on Loupedeck Live S and RSCX)buffer: RGB16-565 Buffercallback: Function to handle draw calls. Receives the following arguments:
context: 2d canvas graphics contextwidth: Width of drawing areaheight: Height of drawing areaReturns a Promise which resolves once the command has been acknowledged by the device.
device.drawScreen(screenID : String, buffer/callback : Buffer/Function) : PromiseDraw graphics to a specific screen. Screen sizes are as follows:
Loupedeck CT:
left: 60x270pxcenter: 360x270pxright: 60x270pxknob: 240x240px (Note: uses big-endian byte order!)Loupedeck Live / Razer Stream Controller:
left: 60x270pxcenter: 360x270pxright: 60x270pxLoupedeck Live S:
center: 480x270pxRazer Stream Controller X:
center: 480x288pxSecond argument can be either a RGB16-565 buffer or a callback.
screenID: Screen to write to [left, center, right, knob] (left and right available on Loupedeck Live and Razer Stream Controller only) (knob available on Loupedeck CT only)buffer: RGB16-565 Buffer (BE for knob, LE otherwise)callback: Function to handle draw calls. Receives the following arguments:
context: 2d canvas graphics contextwidth: Width of drawing areaheight: Height of drawing areaReturns a Promise which resolves once the command has been acknowledged by the device.
device.getInfo() : PromiseRequest device information. Returns a promise resolving to object containing:
serial: Device serial numberversion: Firmware versionIf the device is not connected, the promise will reject.
device.setBrightness(brightness : Number) : PromiseSet screen brightness.
brightness: Float between (0, 1) (0 would turn the screen off, 1 for full brightness)Returns a Promise which resolves once the command has been acknowledged by the device.
device.setButtonColor({ id : String, color : String }) : PromiseSet a button LED to a particular color. (Unavailable on RSCX)
id: Button ID (possible choices: 0-7 on Loupedeck Live/CT/RSC, 0-4 on Loupedeck Live S, see BUTTONS for Loupedeck CT square buttons)color: Any valid CSS color stringReturns a Promise which resolves once the command has been acknowledged by the device.
device.vibrate(pattern? : byte) : PromiseMake device vibrate. (Unavailable on RSCX)
pattern: A valid vibration pattern (see HAPTIC for valid patterns) (default: HAPTIC.SHORT)Returns a Promise which resolves once the command has been acknowledged by the device.
Touch objects are emitted in the touchstart, touchmove, and touchend events and have the following properties:
id: Unique touch identifierx: Screen X-coordinate ([0, 480])y: Screen Y-coordinate ([0, 270])target:
screen: Identifier of screen this touch was detected on ([left, center, right, knob]) (center only on Loupedeck Live S, knob only on Loupedeck CT)key: Index of key touched ([0-11] on Loupedeck Live/CT/RSC, [0-14] on Loupedeck Live S/RSCX)npm installnpm testBig thanks go out to Max Maischein's earlier work in Perl on this topic.
MIT
JavaScript
100.0%
Unofficial Node.js API for Loupedeck Live, Loupedeck Live S, Loupedeck CT and Razer Stream controllers.

Supports:
This library has been tested with firmware versions 0.1.3, 0.1.79, 0.2.5, 0.2.8 and 0.2.23. Other versions may work.
Note: Firmware version 0.2.26 does not seem to work on Linux. Recommendation is to downgrade to 0.2.23 (see #30)
npm install loupedeck
By default, Loupdeck devices uses RGB565 (16-bit) buffers for drawing (with small exceptions, see below), so the canvas module is used to enable a more pleasant API that allows for drawing using Canvas API callbacks.
Note: Ensure Loupedeck software is not running as it may conflict with this library
import { discover } from 'loupedeck'
// Detects and opens first connected device
const device = await discover()
// Observe connect events
device.on('connect', () => {
console.info('Connection successful!')
})
// React to button presses
device.on('down', ({ id }) => {
console.info(`Button pressed: ${id}`)
})
// React to knob turns
device.on('rotate', ({ id, delta }) => {
console.info(`Knob ${id} rotated: ${delta}`)
})
import { LoupedeckLiveS } from 'loupedeck'
const device = new LoupedeckLiveS({ path: '/dev/tty.usbmodem101', autoConnect: false })
await device.connect()
console.info('Connection successful!')
device.on('down', ({ id }) => {
console.info(`Button pressed: ${id}`)
})
For all examples, see the examples folder. Running some examples requires canvas to be installed (see above).
discover() : Promise<LoupedeckDevice>Find the first connected Loupedeck device and return it.
Returns an instance of LoupedeckLive, LoupedeckLiveS, LoupedeckCT, RazerStreamController, RazerStreamControllerX, or throws an Error in case none or unsupported devices are found.
LoupedeckLiveImplements and supports all methods from the LoupedeckDevice interface.
new LoupedeckLive({ path : String?, host : String?, autoConnect : Boolean? })Create a new Loupedeck Live device interface.
Most use-cases should omit the host/path parameter, unless you're using multiple devices or know specifically which IP or device path you want to connect to. Either use path OR host, never both.
path: (Firmware 0.2.X only) Serial device path (example: /dev/cu.ttymodem-1332 or COM2) (default: autodiscover)host: (Firmware 0.1.X only) Host or IP address to connect to (example: 127.100.1.1) (default: autodiscover)autoConnect: Automatically connect during construction. (default: true) Set to false if you'd prefer to call connect(). yourself.reconnectInterval: How many milliseconds to wait before attempting a reconnect after a failed connection (default: 3000) Set to false to turn off automatic reconnects.LoupedeckCTSame interface as LoupedeckLive.
LoupedeckLiveSSame interface as LoupedeckLive.
RazerStreamControllerSame interface as LoupedeckLive.
RazerStreamControllerXSame interface as LoupedeckLive.
Does not implement vibration or button colors.
LoupedeckDeviceShared device interface. Do not instantiate this manually, use one of the above classes instead or the discover() function.
All incoming messages are emitted as action events and can be subscribed to via device.on().
LoupedeckDevice.list({ ignoreSerial : Boolean?, ignoreWebsocket : Boolean?} = {}) : Promise<Array>Static method to scan for and return a list of all detected devices. This includes ones which are already opened.
ignoreSerial: Ignore devices which operate over serial (Firmware 0.2.X) (default: false)ignoreWebsocket: Ignore devices which operate over websocket (Firmware 0.1.X) (default: false)Device info can be directly passed on to the constructor below.
'connect'Emitted when connection to the device succeeds. Includes an info object containing:
address: Connection address (E.G. serial path or websocket address)'disconnect'Emitted when a device disconnects for any reason. First argument for the event is an Error object in case of an abnormal disconnect (otherwise undefined).
'down'Emitted when a button or knob is pressed down.
Arguments:
id: Button ID (see constants.js for possible IDs)'rotate'Emitted when a knob is rotated.
Arguments:
id: Button ID (see constants.js for possible IDs)delta: Rotation direction, -1 for counter-clockwise, 1 for clockwise.'touchstart'Emitted when any part of the screen is touched for the first time.
Arguments:
changedTouches: Array of new touches created during this eventtouches: Array of all currently held touches on screen'touchmove'Emitted when a touch moves across the screen.
Arguments:
changedTouches: Array of touches changed during this eventtouches: Array of all currently held touches on screen'touchend'Emitted when a touch is no longer detected.
Arguments:
changedTouches: Array of touches removed during this eventtouches: Array of all currently held touches on screen (if any)'up'Emitted when a button or knob is released.
Arguments:
id: Button ID (see constants.js for possible IDs)device.close() : PromiseClose device connection.
Returns Promise which resolves once the device has been closed.
device.connect() : PromiseManually connect. Resolves on success.
device.drawBuffer({ id : String, width : Number, height : Number, x? : Number, y? : Number, autoRefresh? : Boolean }, buffer : Buffer) : PromiseDraw graphics to a particular area using a RGB16-565 pixel buffer.
Lower-level method if drawKey() or drawScreen() don't meet your needs.
id: Screen to write to [left, center, right, knob] (left and right available on Loupedeck Live / RSC only) (knob available on Loupedeck CT only)width: Width of area to drawheight: Height of area to drawx: Starting X offset (default: 0)y: Starting Y offset (default: 0)autoRefresh: Whether to refresh the screen after drawing (default: true)buffer: RGB16-565 Buffer. Should be width * height * 2 bytes long, with each pixel represented by 2 bytes (5 bits red, 6 bits green, 5 bits blue) in little-endian (LE). Note: Loupedeck CT knob screen is the only exception, it uses big-endian (BE)Returns a Promise which resolves once the command has been acknowledged by the device.
device.drawCanvas({ id : String, width : Number, height : Number, x? : Number, y? : Number, autoRefresh? : Boolean }, callback : Function) : PromiseDraw graphics to a particular area using the Canvas API.
Lower-level method if drawKey() or drawScreen() don't meet your needs.
id: Screen to write to [left, center, right, knob] (left and right available on Loupedeck Live / RSC only) (knob available on Loupedeck CT only)width: Width of area to drawheight: Height of area to drawx: Starting X offset (default: 0)y: Starting Y offset (default: 0)autoRefresh: Whether to refresh the screen after drawing (default: true)callback: Function to handle draw calls. Receives the following arguments:
context: 2d canvas graphics contextwidth: Width of drawing areaheight: Height of drawing areaReturns a Promise which resolves once the command has been acknowledged by the device.
device.drawKey(key : Number, buffer/callback : Buffer/Function) : PromiseDraw graphics to a specific key.
Second argument can be either a RGB16-565 buffer or a callback. Width and height of callback will typically be 90, as keys are mostly 90x90px (RSCX being the exception - those keys are 96x96px).
key: Key index to write to ([0-11] on Loupedeck Live/Loupedeck CT/RSC, [0-14] on Loupedeck Live S and RSCX)buffer: RGB16-565 Buffercallback: Function to handle draw calls. Receives the following arguments:
context: 2d canvas graphics contextwidth: Width of drawing areaheight: Height of drawing areaReturns a Promise which resolves once the command has been acknowledged by the device.
device.drawScreen(screenID : String, buffer/callback : Buffer/Function) : PromiseDraw graphics to a specific screen. Screen sizes are as follows:
Loupedeck CT:
left: 60x270pxcenter: 360x270pxright: 60x270pxknob: 240x240px (Note: uses big-endian byte order!)Loupedeck Live / Razer Stream Controller:
left: 60x270pxcenter: 360x270pxright: 60x270pxLoupedeck Live S:
center: 480x270pxRazer Stream Controller X:
center: 480x288pxSecond argument can be either a RGB16-565 buffer or a callback.
screenID: Screen to write to [left, center, right, knob] (left and right available on Loupedeck Live and Razer Stream Controller only) (knob available on Loupedeck CT only)buffer: RGB16-565 Buffer (BE for knob, LE otherwise)callback: Function to handle draw calls. Receives the following arguments:
context: 2d canvas graphics contextwidth: Width of drawing areaheight: Height of drawing areaReturns a Promise which resolves once the command has been acknowledged by the device.
device.getInfo() : PromiseRequest device information. Returns a promise resolving to object containing:
serial: Device serial numberversion: Firmware versionIf the device is not connected, the promise will reject.
device.setBrightness(brightness : Number) : PromiseSet screen brightness.
brightness: Float between (0, 1) (0 would turn the screen off, 1 for full brightness)Returns a Promise which resolves once the command has been acknowledged by the device.
device.setButtonColor({ id : String, color : String }) : PromiseSet a button LED to a particular color. (Unavailable on RSCX)
id: Button ID (possible choices: 0-7 on Loupedeck Live/CT/RSC, 0-4 on Loupedeck Live S, see BUTTONS for Loupedeck CT square buttons)color: Any valid CSS color stringReturns a Promise which resolves once the command has been acknowledged by the device.
device.vibrate(pattern? : byte) : PromiseMake device vibrate. (Unavailable on RSCX)
pattern: A valid vibration pattern (see HAPTIC for valid patterns) (default: HAPTIC.SHORT)Returns a Promise which resolves once the command has been acknowledged by the device.
Touch objects are emitted in the touchstart, touchmove, and touchend events and have the following properties:
id: Unique touch identifierx: Screen X-coordinate ([0, 480])y: Screen Y-coordinate ([0, 270])target:
screen: Identifier of screen this touch was detected on ([left, center, right, knob]) (center only on Loupedeck Live S, knob only on Loupedeck CT)key: Index of key touched ([0-11] on Loupedeck Live/CT/RSC, [0-14] on Loupedeck Live S/RSCX)npm installnpm testBig thanks go out to Max Maischein's earlier work in Perl on this topic.
MIT
JavaScript
100.0%