Skip to content

Commit

Permalink
feat: support companion provided bitmap scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Jun 24, 2023
1 parent b8070d7 commit b335e2e
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 43 deletions.
28 changes: 21 additions & 7 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export class CompanionSatelliteClient extends EventEmitter<CompanionSatelliteCli
private _host = ''
private _port = DEFAULT_PORT
private _supportsCombinedEncoders = false
private _supportsBitmapResolution = false

public forceSplitEncoders = false

Expand All @@ -113,13 +114,20 @@ export class CompanionSatelliteClient extends EventEmitter<CompanionSatelliteCli
}

/**
* Older versions of Companion do not support rotary encoders.
* Until 2.4 of Companion it does not support rotary encoders.
* For these, we can 'simulate' them by use the press/release actions of a button.
*/
public get useCombinedEncoders(): boolean {
return !this.forceSplitEncoders && this._supportsCombinedEncoders
}

/**
* Until 3.x of Companion it only supports providing 72x72px bitmaps for buttons.
*/
public get useCustomBitmapResolution(): boolean {
return this._supportsBitmapResolution
}

constructor(options: CompanionSatelliteClientOptions = {}) {
super()

Expand Down Expand Up @@ -311,9 +319,15 @@ export class CompanionSatelliteClient extends EventEmitter<CompanionSatelliteCli

private handleBegin(params: Record<string, string | boolean>): void {
const protocolVersion = params.ApiVersion
if (typeof protocolVersion === 'string' && semver.lte('1.3.0', protocolVersion)) {
this._supportsCombinedEncoders = true
console.log('Companion supports combined encoders')
if (typeof protocolVersion === 'string') {
if (semver.lte('1.3.0', protocolVersion)) {
this._supportsCombinedEncoders = true
console.log('Companion supports combined encoders')
}
if (semver.lte('1.5.0', protocolVersion)) {
this._supportsBitmapResolution = true
console.log('Companion supports bitmap resolution')
}
}
}

Expand Down Expand Up @@ -410,9 +424,9 @@ export class CompanionSatelliteClient extends EventEmitter<CompanionSatelliteCli
this.socket.write(
`ADD-DEVICE DEVICEID=${deviceId} PRODUCT_NAME="${productName}" KEYS_TOTAL=${
props.keysTotal
} KEYS_PER_ROW=${props.keysPerRow} BITMAPS=${props.bitmaps ? 1 : 0} COLORS=${
props.colours ? 1 : 0
} TEXT=${props.text ? 1 : 0}\n`
} KEYS_PER_ROW=${props.keysPerRow} BITMAPS=${
this._supportsBitmapResolution ? props.bitmapSize ?? 0 : props.bitmapSize ? 1 : 0
} COLORS=${props.colours ? 1 : 0} TEXT=${props.text ? 1 : 0}\n`
)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/device-types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface DeviceDrawProps {
export interface DeviceRegisterProps {
keysTotal: number
keysPerRow: number
bitmaps: boolean
bitmapSize: number | null
colours: boolean
text: boolean
}
Expand Down
2 changes: 1 addition & 1 deletion src/device-types/infinitton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class InfinittonWrapper implements WrappedDevice {
return {
keysTotal: 15,
keysPerRow: 5,
bitmaps: true,
bitmapSize: 72,
colours: false,
text: false,
}
Expand Down
26 changes: 16 additions & 10 deletions src/device-types/loupedeck-live-s.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class LoupedeckLiveSWrapper implements WrappedDevice {
#isShowingCard = true
#queue: ImageWriteQueue

#companionSupportsScaling = false

public get deviceId(): string {
return this.#deviceId
}
Expand All @@ -40,15 +42,17 @@ export class LoupedeckLiveSWrapper implements WrappedDevice {
const width = this.#deck.lcdKeySize
const height = this.#deck.lcdKeySize

let newbuffer: Buffer
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
.resize(width, height)
.raw()
.toBuffer()
} catch (e) {
console.log(`device(${deviceId}): scale image failed: ${e}`)
return
let newbuffer: Buffer = buffer
if (!this.#companionSupportsScaling) {
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
.resize(width, height)
.raw()
.toBuffer()
} catch (e) {
console.log(`device(${deviceId}): scale image failed: ${e}`)
return
}
}

// Check if generated image is still valid
Expand All @@ -73,7 +77,7 @@ export class LoupedeckLiveSWrapper implements WrappedDevice {
return {
keysTotal: 21,
keysPerRow: 7,
bitmaps: true,
bitmapSize: this.#deck.lcdKeySize,
colours: true,
text: false,
}
Expand All @@ -84,6 +88,8 @@ export class LoupedeckLiveSWrapper implements WrappedDevice {
this.#deck.close()
}
async initDevice(client: CompanionSatelliteClient, status: string): Promise<void> {
this.#companionSupportsScaling = client.useCustomBitmapResolution

const convertButtonId = (type: 'button' | 'rotary', id: number): number => {
if (type === 'button') {
// return 24 + id
Expand Down
26 changes: 16 additions & 10 deletions src/device-types/loupedeck-live.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class LoupedeckLiveWrapper implements WrappedDevice {
#isShowingCard = true
#queue: ImageWriteQueue

#companionSupportsScaling = false

public get deviceId(): string {
return this.#deviceId
}
Expand Down Expand Up @@ -44,15 +46,17 @@ export class LoupedeckLiveWrapper implements WrappedDevice {
const width = this.#deck.lcdKeySize
const height = this.#deck.lcdKeySize

let newbuffer: Buffer
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
.resize(width, height)
.raw()
.toBuffer()
} catch (e) {
console.log(`device(${deviceId}): scale image failed: ${e}`)
return
let newbuffer: Buffer = buffer
if (!this.#companionSupportsScaling) {
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
.resize(width, height)
.raw()
.toBuffer()
} catch (e) {
console.log(`device(${deviceId}): scale image failed: ${e}`)
return
}
}

// Check if generated image is still valid
Expand All @@ -77,7 +81,7 @@ export class LoupedeckLiveWrapper implements WrappedDevice {
return {
keysTotal: 32,
keysPerRow: 8,
bitmaps: true,
bitmapSize: this.#deck.lcdKeySize,
colours: true,
text: false,
}
Expand All @@ -88,6 +92,8 @@ export class LoupedeckLiveWrapper implements WrappedDevice {
this.#deck.close()
}
async initDevice(client: CompanionSatelliteClient, status: string): Promise<void> {
this.#companionSupportsScaling = client.useCustomBitmapResolution

const convertButtonId = (type: 'button' | 'rotary', id: number, rotarySecondary: boolean): number => {
if (type === 'button' && id >= 0 && id < 8) {
return 24 + id
Expand Down
26 changes: 16 additions & 10 deletions src/device-types/razer-stream-controller-x.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class RazerStreamControllerXWrapper implements WrappedDevice {
#isShowingCard = true
#queue: ImageWriteQueue

#companionSupportsScaling = false

public get deviceId(): string {
return this.#deviceId
}
Expand Down Expand Up @@ -41,15 +43,17 @@ export class RazerStreamControllerXWrapper implements WrappedDevice {
const width = this.#deck.lcdKeySize
const height = this.#deck.lcdKeySize

let newbuffer: Buffer
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
.resize(width, height)
.raw()
.toBuffer()
} catch (e) {
console.log(`device(${deviceId}): scale image failed: ${e}`)
return
let newbuffer: Buffer = buffer
if (!this.#companionSupportsScaling) {
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
.resize(width, height)
.raw()
.toBuffer()
} catch (e) {
console.log(`device(${deviceId}): scale image failed: ${e}`)
return
}
}

// Check if generated image is still valid
Expand All @@ -74,7 +78,7 @@ export class RazerStreamControllerXWrapper implements WrappedDevice {
return {
keysTotal: 15,
keysPerRow: 5,
bitmaps: true,
bitmapSize: this.#deck.lcdKeySize,
colours: true,
text: false,
}
Expand All @@ -85,6 +89,8 @@ export class RazerStreamControllerXWrapper implements WrappedDevice {
this.#deck.close()
}
async initDevice(client: CompanionSatelliteClient, status: string): Promise<void> {
this.#companionSupportsScaling = client.useCustomBitmapResolution

const convertButtonId = (type: 'button' | 'rotary', id: number): number => {
if (type === 'button') {
return id
Expand Down
11 changes: 8 additions & 3 deletions src/device-types/streamdeck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class StreamDeckWrapper implements WrappedDevice {
#queue: ImageWriteQueue | undefined
#queueLcdStrip: ImageWriteQueue | undefined

#companionSupportsScaling = false

public get deviceId(): string {
return this.#deviceId
}
Expand All @@ -33,7 +35,7 @@ export class StreamDeckWrapper implements WrappedDevice {
const outputId = this.#queueOutputId

let newbuffer: Buffer = buffer
if (this.#deck.ICON_SIZE !== 72) {
if (this.#deck.ICON_SIZE !== 72 && !this.#companionSupportsScaling) {
// scale if necessary
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
Expand Down Expand Up @@ -66,7 +68,8 @@ export class StreamDeckWrapper implements WrappedDevice {
let newbuffer: Buffer
// scale if necessary
try {
newbuffer = await sharp(buffer, { raw: { width: 72, height: 72, channels: 3 } })
const inputRes = this.#companionSupportsScaling ? this.#deck.ICON_SIZE : 72
newbuffer = await sharp(buffer, { raw: { width: inputRes, height: inputRes, channels: 3 } })
.resize(encoderSize.height, encoderSize.height)
.raw()
.toBuffer()
Expand Down Expand Up @@ -95,7 +98,7 @@ export class StreamDeckWrapper implements WrappedDevice {
const info = {
keysTotal: this.#deck.NUM_KEYS,
keysPerRow: this.#deck.KEY_COLUMNS,
bitmaps: this.#deck.ICON_SIZE !== 0,
bitmapSize: this.#deck.ICON_SIZE,
colours: false,
text: false,
}
Expand All @@ -116,6 +119,8 @@ export class StreamDeckWrapper implements WrappedDevice {
this.#deck.on('down', (key) => client.keyDown(this.deviceId, key))
this.#deck.on('up', (key) => client.keyUp(this.deviceId, key))

this.#companionSupportsScaling = client.useCustomBitmapResolution

if (this.#deck.MODEL === DeviceModelId.PLUS) {
this.#deck.on('encoderDown', (encoder) => {
const index = this.#deck.NUM_KEYS + this.#deck.NUM_ENCODERS + encoder
Expand Down
2 changes: 1 addition & 1 deletion src/device-types/xencelabs-quick-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class QuickKeysWrapper implements WrappedDevice {
return {
keysTotal: 12,
keysPerRow: 6,
bitmaps: false,
bitmapSize: null,
colours: true,
text: true,
}
Expand Down

0 comments on commit b335e2e

Please sign in to comment.