Documentation ¶
Overview ¶
Package loupedeck provides a Go interface for talking to a Loupedeck Live control surface.
The Loupedeck Live with firmware 1.x appeared as a USB network device that we talked to via HTTP+websockets, but newer firmware looks like a serial device that talks a mutant version of the Websocket protocol.
See https://github.com/foxxyz/loupedeck for Javascript code for talking to the Loupedeck Live; it supports more of the Loupedeck's functionality.
Example ¶
package main import ( "fmt" "github.com/scottlaird/loupedeck" ) func main() { l, err := loupedeck.ConnectAuto() if err != nil { panic(err) } light1 := loupedeck.NewWatchedInt(0) light1.AddWatcher(func(i int) { fmt.Printf("DMX 1->%d\n", i) }) light2 := loupedeck.NewWatchedInt(0) light2.AddWatcher(func(i int) { fmt.Printf("DMX 3->%d\n", i) }) light3 := loupedeck.NewWatchedInt(0) light3.AddWatcher(func(i int) { fmt.Printf("DMX 5->%d\n", i) }) l.NewTouchDial(l.GetDisplay("left"), light1, light2, light3, 0, 100) // Define the 'Circle' button (bottom left) to function as an "off" button. l.BindButton(loupedeck.Circle, func(b loupedeck.Button, s loupedeck.ButtonStatus) { light1.Set(0) light2.Set(0) light3.Set(0) }) l.Listen() }
Output:
Index ¶
- Constants
- type Button
- type ButtonFunc
- type ButtonStatus
- type Display
- type IntKnob
- type Knob
- type KnobFunc
- type Loupedeck
- func (l *Loupedeck) BindButton(b Button, f ButtonFunc)
- func (l *Loupedeck) BindButtonUp(b Button, f ButtonFunc)
- func (l *Loupedeck) BindKnob(k Knob, f KnobFunc)
- func (l *Loupedeck) BindTouch(b TouchButton, f TouchFunc)
- func (l *Loupedeck) BindTouchUp(b TouchButton, f TouchFunc)
- func (l *Loupedeck) Close()
- func (l *Loupedeck) Face() font.Face
- func (l *Loupedeck) FontDrawer() font.Drawer
- func (l *Loupedeck) GetDisplay(name string) *Display
- func (l *Loupedeck) IntKnob(k Knob, min int, max int, watchedint *WatchedInt) *IntKnob
- func (l *Loupedeck) Listen()
- func (l *Loupedeck) NewMessage(messageType MessageType, data []byte) *Message
- func (l *Loupedeck) NewMultiButton(watchedint *WatchedInt, b TouchButton, im image.Image, val int) *MultiButton
- func (l *Loupedeck) NewTouchDial(display *Display, w1, w2, w3 *WatchedInt, min, max int) *TouchDial
- func (l *Loupedeck) ParseMessage(b []byte) (*Message, error)
- func (l *Loupedeck) Send(m *Message) error
- func (l *Loupedeck) SendAndWait(m *Message, timeout time.Duration) (*Message, error)
- func (l *Loupedeck) SendWithCallback(m *Message, c transactionCallback) error
- func (l *Loupedeck) SetBrightness(b int) error
- func (l *Loupedeck) SetButtonColor(b Button, c color.RGBA) error
- func (l *Loupedeck) SetDefaultFont() error
- func (l *Loupedeck) SetDisplays()
- func (l *Loupedeck) TextInBox(x, y int, s string, fg, bg color.Color) (image.Image, error)
- type Message
- type MessageType
- type MultiButton
- type SerialWebSockConn
- func (l *SerialWebSockConn) Close() error
- func (l *SerialWebSockConn) LocalAddr() net.Addr
- func (l *SerialWebSockConn) Read(b []byte) (n int, err error)
- func (l *SerialWebSockConn) RemoteAddr() net.Addr
- func (l *SerialWebSockConn) SetDeadline(t time.Time) error
- func (l *SerialWebSockConn) SetReadDeadline(t time.Time) error
- func (l *SerialWebSockConn) SetWriteDeadline(t time.Time) error
- func (l *SerialWebSockConn) Write(b []byte) (n int, err error)
- type TouchButton
- type TouchDial
- type TouchFunc
- type WatchFunc
- type WatchedInt
Examples ¶
Constants ¶
const ( // CTKnob is the large knob in the center of the Loupedeck CT CTKnob Knob = 0 // Knob1 is the upper left knob. Knob1 = 1 // Knob2 is the middle left knob. Knob2 = 2 // Knob3 is the bottom left knob. Knob3 = 3 // Knob4 is the upper right knob. Knob4 = 4 // Knob5 is the middle right knob. Knob5 = 5 // Knob6 is the bottom right knob. Knob6 = 6 )
const ( // TouchLeft indicates that the left touchscreen area, near the leftmost knobs has been touched. TouchLeft TouchButton = 1 // TouchRight indicates that hte right touchscreen area, near the rightmost knobs has been touched. TouchRight = 2 Touch1 = 3 Touch2 = 4 Touch3 = 5 Touch4 = 6 Touch5 = 7 Touch6 = 8 Touch7 = 9 Touch8 = 10 Touch9 = 11 Touch10 = 12 Touch11 = 13 Touch12 = 14 )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Button ¶
type Button uint16
Button represents a physical button on the Loupedeck Live. This includes the 8 buttons at the bottom of the device as well as the 'click' function of the 6 dials.
const ( KnobPress1 Button = 1 KnobPress2 Button = 2 KnobPress3 Button = 3 KnobPress4 Button = 4 KnobPress5 Button = 5 KnobPress6 Button = 6 // Circle is sent when the left-most hardware button under the // display is clicked. This has a circle icon on the // Loupedeck Live, but is unfortunately labeled "1" on the // Loupedeck CT. Circle Button = 7 Button1 Button = 8 Button2 Button = 9 Button3 Button = 10 Button4 Button = 11 Button5 Button = 12 Button6 Button = 13 Button7 Button = 14 // CT-specific buttons. CTCircle Button = 15 Undo Button = 16 Keyboard Button = 17 Enter Button = 18 Save Button = 19 LeftFn Button = 20 Up Button = 21 A Button = 21 Left Button = 22 C Button = 22 RightFn Button = 23 Down Button = 24 B Button = 24 Right Button = 25 D Button = 25 E Button = 26 )
type ButtonFunc ¶
type ButtonFunc func(Button, ButtonStatus)
ButtonFunc is a function signature used for callbacks on Button events. When a specified event happens, the ButtonFunc is called with parameters specifying which button was pushed and what its current state is.
type ButtonStatus ¶
type ButtonStatus uint8
ButtonStatus represents the state of Buttons.
const ( // ButtonDown indicates that a button has just been pressed. ButtonDown ButtonStatus = 0 // ButtonUp indicates that a button was just released. ButtonUp = 1 )
type Display ¶
type Display struct { Name string // contains filtered or unexported fields }
Display is part of the Loupedeck protocol, used to identify which of the displays on the Loupedeck to write to.
func (*Display) Draw ¶ added in v1.0.0
Draw draws an image onto a specific display of the Loupedeck Live. The device has 3 seperate displays, the left segment (by knobs 1-3), the right segment (by knobs 4-6) and the main/center segment (underneath the 4x3 array of touch buttons). Drawing subsets of a display is explicitly allowed; writing a 90x90 block of pixels to the main display will only overwrite one button's worth of image, and will not touch other pixels.
Most Loupedeck screens are little-endian, except for the knob screen on the Loupedeck CT, which is big-endian. This does not deal with this case correctly yet.
type IntKnob ¶
type IntKnob struct {
// contains filtered or unexported fields
}
IntKnob is an abstraction over the Loupedeck Live's Knobs. The IntKnob turns left/right dial actions into incrememnting and decrementing an integer within a specified range. In addition, the 'click' action of the knob resets the IntKnob's value to 0.
type KnobFunc ¶
KnobFunc is a function signature used for callbacks on Knob events, similar to ButtonFunc's use with Button events. The exact use of the second parameter depends on the use; in some cases it's simply +1/-1 (for right/left button turns) and in other cases it's the current value of the dial.
type Loupedeck ¶
type Loupedeck struct { Vendor string Product string Model string Version string SerialNo string // contains filtered or unexported fields }
Loupedeck describes a Loupedeck device.
func ConnectAuto ¶
ConnectAuto connects to a Loupedeck Live by automatically locating the first USB Loupedeck device in the system. If you have more than one device and want to connect to a specific one, then use ConnectPath().
func ConnectPath ¶
ConnectPath connects to a Loupedeck Live via a specified serial device. If successful it returns a new Loupedeck.
func (*Loupedeck) BindButton ¶
func (l *Loupedeck) BindButton(b Button, f ButtonFunc)
BindButton sets a callback for actions on a specific button. When the Button is pushed down, then the provided ButtonFunc is called.
func (*Loupedeck) BindButtonUp ¶
func (l *Loupedeck) BindButtonUp(b Button, f ButtonFunc)
BindButtonUp sets a callback for actions on a specific button. When the Button is released, then the provided ButtonFunc is called.
func (*Loupedeck) BindKnob ¶
BindKnob sets a callback for actions on a specific knob. When the Knob is turned then the provided KnobFunc is called.
func (*Loupedeck) BindTouch ¶
func (l *Loupedeck) BindTouch(b TouchButton, f TouchFunc)
BindTouch sets a callback for actions on a specific TouchButton. When the TouchButton is pushed down, then the provided TouchFunc is called.
func (*Loupedeck) BindTouchUp ¶
func (l *Loupedeck) BindTouchUp(b TouchButton, f TouchFunc)
BindTouchUp sets a callback for actions on a specific TouchButton. When the TouchButton is released, then the provided TouchFunc is called.
func (*Loupedeck) Face ¶
Face returns the current font.Face in use for writing text onto the Loupedeck's graphical buttons.
func (*Loupedeck) FontDrawer ¶
FontDrawer returns a font.Drawer object configured to writing text onto the Loupedeck's graphical buttons.
func (*Loupedeck) GetDisplay ¶ added in v1.0.0
GetDisplay returns a Display object with a given name if it exists, otherwise it returns nil.
Traditional Loupedeck devices had 3 displays, Left, Center, and Right. Newer devices make all 3 look like a single display, and it's impossible to know at compile-time what any given device will support, so we need to create them dynamically and then look them up.
In addition, some devices (like the Loupedeck CT) have additional displays.
For now, common display names are:
- left (on all devices, emulated on newer hardware)
- right (on all devices, emulated on newer hardware)
- main (on all devices, emulated on newer hardware)
- dial (Loupedeck CT only)
- main (only on newer hardware)
func (*Loupedeck) IntKnob ¶
IntKnob implements a generic dial knob using the specified Loupedeck Knob. It binds the dial function of the knob to increase/decrease the IntKnob's value and binds the button function of the knob to reset the value to 0. Basically, spin the dial and it changes, and click and it resets.
func (*Loupedeck) Listen ¶
func (l *Loupedeck) Listen()
Listen waits for events from the Loupedeck and calls callbacks as configured.
func (*Loupedeck) NewMessage ¶ added in v1.0.0
func (l *Loupedeck) NewMessage(messageType MessageType, data []byte) *Message
NewMessage creates a new low-level Loupedeck message with a specified type and data. This isn't generally needed for end-use.
func (*Loupedeck) NewMultiButton ¶
func (l *Loupedeck) NewMultiButton(watchedint *WatchedInt, b TouchButton, im image.Image, val int) *MultiButton
NewMultiButton creates a new MultiButton, bound to an existing WatchedInt. One image.Image and value must be provided; this is the first image (and default value) for the MultiButton. Additional images and values can be added via the Add function.
func (*Loupedeck) NewTouchDial ¶
func (l *Loupedeck) NewTouchDial(display *Display, w1, w2, w3 *WatchedInt, min, max int) *TouchDial
NewTouchDial creates a TouchDial.
func (*Loupedeck) ParseMessage ¶ added in v1.0.0
ParseMessage creates a Loupedeck Message from a block of bytes. This is used to decode incoming messages from a Loupedeck, and shouldn't generally be needed outside of this library.
func (*Loupedeck) SendAndWait ¶ added in v1.0.0
SendAndWait sends a message and then waits for a response, returning the response message.
func (*Loupedeck) SendWithCallback ¶ added in v1.0.0
SendWithCallback sends a message to the specified device and registers a callback. When (or if) the Loupedeck sends a response to the message, the callback function will be called and provided with the response message.
func (*Loupedeck) SetBrightness ¶
SetBrightness sets the overall brightness of the Loupedeck display.
func (*Loupedeck) SetButtonColor ¶
SetButtonColor sets the color of a specific Button. The Loupedeck Live allows the 8 buttons below the display to be set to specific colors, however the 'Circle' button's colors may be overridden to show the status of the Loupedeck Live's connection to the host.
func (*Loupedeck) SetDefaultFont ¶
SetDefaultFont sets the default font for drawing onto buttons.
TODO(laird): Actually make it easy to override this default.
func (*Loupedeck) SetDisplays ¶ added in v1.0.0
func (l *Loupedeck) SetDisplays()
SetDisplays configures the Loupdeck's displays based on the hardware ID of the conencted device.
type Message ¶ added in v1.0.0
type Message struct {
// contains filtered or unexported fields
}
Message defines a message for communicating with the Loupedeck over USB. All communication with the Loupedeck occurs via Messages, but most application software can use higher-level functions in this library and never touch messages directly.
The exception would be wanting to use a feature like vibration that isn't currently supported in this library.
type MessageType ¶ added in v1.0.0
type MessageType byte
MessageType is a uint16 used to identify various commands and actions needed for the Loupedeck protocol.
const ( ButtonPress MessageType = 0x00 KnobRotate MessageType = 0x01 SetColor MessageType = 0x02 Serial MessageType = 0x03 Reset MessageType = 0x06 Version MessageType = 0x07 SetBrightness MessageType = 0x09 MCU MessageType = 0x0d Draw MessageType = 0x0f WriteFramebuff MessageType = 0x10 SetVibration MessageType = 0x1b Touch MessageType = 0x4d TouchCT MessageType = 0x52 TouchEnd MessageType = 0x6d TouchEndCT MessageType = 0x72 )
See 'COMMANDS' in https://github.com/foxxyz/loupedeck/blob/master/constants.js
type MultiButton ¶
type MultiButton struct {
// contains filtered or unexported fields
}
MultiButton implements a multi-image touch button for the Loupedeck Live that rotates between a set of images for each touch, changing its value (and image) for each touch. Once the last image is touched, it loops back to the first image in the set.
func (*MultiButton) Add ¶
func (m *MultiButton) Add(im image.Image, value int)
Add adds an additional image+value to a MultiButton.
func (*MultiButton) Advance ¶
func (m *MultiButton) Advance()
Advance moves to the next value of the MultiButton, updating the display and underlying WatchedInt.
func (*MultiButton) Draw ¶
func (m *MultiButton) Draw()
Draw redraws the MultiButton on the Loupedeck live.
func (*MultiButton) GetCur ¶
func (m *MultiButton) GetCur() int
GetCur gets the current value of the MultiButton. The value returned will match one of the values from either NewMultiButton or multibutton.Add, depending on which image is currently displayed.
type SerialWebSockConn ¶
SerialWebSockConn implements an external dialer interface for the Gorilla that allows it to talk to Loupedeck's weird websockets-over-serial-over-USB setup.
The Gorilla websockets library can use an external dialer interface, which means that we can use it *mostly* unmodified to talk to a serial device instead of a network device. We just need to provide something that matches the net.Conn interface. Here's a minimal implementation.
func ConnectSerialAuto ¶
func ConnectSerialAuto() (*SerialWebSockConn, error)
ConnectSerialAuto connects to the first compatible Loupedeck in the system. To connect to a specific Loupedeck, use ConnectSerialPath.
func ConnectSerialPath ¶
func ConnectSerialPath(serialPath string) (*SerialWebSockConn, error)
ConnectSerialPath connects to a specific Loupedeck, using the path to the USB serial device as a key.
func (*SerialWebSockConn) Close ¶
func (l *SerialWebSockConn) Close() error
Close closed the connection.
func (*SerialWebSockConn) LocalAddr ¶
func (l *SerialWebSockConn) LocalAddr() net.Addr
LocalAddr is needed for Gorilla compatibility, but doesn't actually make sense with serial ports.
func (*SerialWebSockConn) Read ¶
func (l *SerialWebSockConn) Read(b []byte) (n int, err error)
Read reads bytes from the connected serial port.
func (*SerialWebSockConn) RemoteAddr ¶
func (l *SerialWebSockConn) RemoteAddr() net.Addr
RemoteAddr is needed for Gorilla compatibility, but doesn't actually make sense with serial ports.
func (*SerialWebSockConn) SetDeadline ¶
func (l *SerialWebSockConn) SetDeadline(t time.Time) error
SetDeadline is needed for Gorilla compatibility, but doesn't actually make sense with serial ports.
func (*SerialWebSockConn) SetReadDeadline ¶
func (l *SerialWebSockConn) SetReadDeadline(t time.Time) error
SetReadDeadline is needed for Gorilla compatibility, but doesn't actually make sense with serial ports.
func (*SerialWebSockConn) SetWriteDeadline ¶
func (l *SerialWebSockConn) SetWriteDeadline(t time.Time) error
SetWriteDeadline is needed for Gorilla compatibility, but doesn't actually make sense with serial ports.
type TouchButton ¶
type TouchButton uint16
TouchButton represents the regions of the touchpad on the Loupedeck Live.
type TouchDial ¶
type TouchDial struct {
Knob1, Knob2, Knob3 *IntKnob
// contains filtered or unexported fields
}
TouchDial implements a "smart" bank of dials for the Loupedeck Live. If displayid is DisplayLeft then the TouchDial will display knobs 1-3 on the left display, otherwise it will show knobs 4-6 on the right display.
The display will show the current value of the WatchedInt for each knob. Turning the knob will increment/decrement each value as expected. Clicking the knob will zero the value. Sliding up or down on the LCD display will increase or decrease all 3 knob values at once.
type TouchFunc ¶
type TouchFunc func(TouchButton, ButtonStatus, uint16, uint16)
TouchFunc is a function signature used for callbacks on TouchButton events, similar to ButtonFunc and KnobFunc. The parameters are:
- The TouchButton touched
- The ButtonStatus (down/up)
- The X location touched (relative to the whole display)
- The Y location touched (relative to the whole display)
type WatchFunc ¶
type WatchFunc func(int)
WatchFunc is used for callbacks for changes to a WatchedInt.
type WatchedInt ¶
type WatchedInt struct {
// contains filtered or unexported fields
}
WatchedInt wraps an int with zero or more callback watchers; whenever the value of the int changes (via Set), all of the callbacks will be called. This is used to implement a sane model for Loupedeck Live knobs, etc. Calling 'myknob.Set(3)' will update any impacted displays and should trigger any required underlying behaviour.
func NewWatchedInt ¶
func NewWatchedInt(value int) *WatchedInt
NewWatchedInt creates a new WatchedInt with the specified initial value.
func (*WatchedInt) AddWatcher ¶
func (w *WatchedInt) AddWatcher(f WatchFunc)
AddWatcher adds a callback function for this WatchedInt. The callback will be called whenever Set is called.
func (*WatchedInt) Get ¶
func (w *WatchedInt) Get() int
Get returns the current value of the WatchedInt.
func (*WatchedInt) Set ¶
func (w *WatchedInt) Set(value int)
Set updates the current value of the WatchedInt and calls all callback functions added via AddWatcher.