Skip to content

Commit

Permalink
feat: improved surface rotation (#2543)
Browse files Browse the repository at this point in the history
Co-authored-by: dnmeid <dnmeid@gmx.net>
  • Loading branch information
Julusian and dnmeid authored Aug 13, 2023
1 parent 836bed8 commit 213ba88
Show file tree
Hide file tree
Showing 15 changed files with 269 additions and 149 deletions.
6 changes: 6 additions & 0 deletions lib/Data/Upgrades/v3tov4.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ function addControlIdsToPages(db) {
/** do the database upgrades to convert from the v3 to the v4 format */
function convertDatabaseToV4(db, logger) {
addControlIdsToPages(db)

// If xkeys was previously enabled, then preserve the old layout
const userconfig = db.getKey('userconfig', {})
if (userconfig.xkeys_enable && userconfig.xkeys_legacy_layout === undefined) {
userconfig.xkeys_legacy_layout = true
}
}

function ParseBankControlId(controlId) {
Expand Down
9 changes: 5 additions & 4 deletions lib/Data/UserConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class DataUserConfig extends CoreBase {
remove_topbar: false,

xkeys_enable: true,
xkeys_legacy_layout: false,
elgato_plugin_enable: false, // Also disables local streamdeck
usb_hotplug: true,
loupedeck_enable: false,
Expand Down Expand Up @@ -344,6 +345,10 @@ class DataUserConfig extends CoreBase {
}

this.data[key] = value
if (save) {
this.db.setKey('userconfig', this.data)
}

this.logger.info(`set '${key}' to: ${JSON.stringify(value)}`)
this.io.emit('set_userconfig_key', key, value)
setImmediate(() => {
Expand All @@ -362,10 +367,6 @@ class DataUserConfig extends CoreBase {

this.graphics.discardAllOutOfBoundsControls()
}

if (save) {
this.db.setKey('userconfig', this.data)
}
}

/**
Expand Down
6 changes: 3 additions & 3 deletions lib/Resources/Util.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ export function clamp(val, min, max) {
}

export function translateRotation(rotation) {
if (rotation === 90) return imageRs.RotationMode.CW270
if (rotation === -90) return imageRs.RotationMode.CW90
if (rotation === 180) return imageRs.RotationMode.CW180
if (rotation === 90 || rotation === 'surface90') return imageRs.RotationMode.CW270
if (rotation === -90 || rotation === 'surface-90') return imageRs.RotationMode.CW90
if (rotation === 180 || rotation === 'surface180') return imageRs.RotationMode.CW180
return null
}

Expand Down
5 changes: 4 additions & 1 deletion lib/Surface/Controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,9 @@ class SurfaceController extends CoreBase {
// } else
if (deviceInfo.vendorId === 1523 && deviceInfo.interface === 0) {
if (this.userconfig.getKey('xkeys_enable')) {
deviceInfo.options = {
useLegacyLayout: !!this.userconfig.getKey('xkeys_legacy_layout'),
}
await this.#addDevice(deviceInfo, 'xkeys', XKeysDriver)
}
}
Expand Down Expand Up @@ -636,7 +639,7 @@ class SurfaceController extends CoreBase {
}

try {
const dev = await factory.create(deviceInfo.path)
const dev = await factory.create(deviceInfo.path, deviceInfo.options)
this.#createSurfaceHandler(deviceInfo.path, type, dev)

setImmediate(() => {
Expand Down
103 changes: 58 additions & 45 deletions lib/Surface/Handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
import CoreBase from '../Core/Base.js'
import { oldBankIndexToXY } from '../Shared/ControlId.js'
import { cloneDeep } from 'lodash-es'
import { LEGACY_BUTTONS_PER_COLUMN, LEGACY_BUTTONS_PER_ROW, LEGACY_MAX_BUTTONS } from '../Util/Constants.js'
import { LEGACY_MAX_BUTTONS } from '../Util/Constants.js'
import { rotateXYForPanel, unrotateXYForPanel } from './Util.js'

const PINCODE_NUMBER_POSITIONS = [
// 0
Expand All @@ -40,19 +41,19 @@ const PINCODE_CODE_POSITION = [0, 1]

const PINCODE_NUMBER_POSITIONS_SKIP_FIRST_COL = [
// 0
[4, 1],
[5, 1],
// 1 2 3
[1, 2],
[2, 2],
[3, 2],
[4, 2],
// 4 5 6
[1, 1],
[2, 1],
[3, 1],
[4, 1],
// 7 8 9
[1, 0],
[2, 0],
[3, 0],
[4, 0],
]

class SurfaceHandler extends CoreBase {
Expand Down Expand Up @@ -92,6 +93,20 @@ class SurfaceHandler extends CoreBase {
*/
#xkeysPageCount = 0

get panelGridSize() {
const rotation = this.panelconfig.config.rotation
if (rotation === 'surface90' || rotation === 'surface-90') {
const rawGridSize = this.panel.gridSize

return {
rows: rawGridSize.columns,
columns: rawGridSize.rows,
}
} else {
return this.panel.gridSize
}
}

constructor(registry, integrationType, panel, isLocked) {
super(registry, `device(${panel.info.deviceId})`, `Surface/Handler/${panel.info.deviceId}`)
this.logger.silly('loading for ' + panel.info.devicepath)
Expand All @@ -113,7 +128,7 @@ class SurfaceHandler extends CoreBase {
}
if (this.panel.info.type === 'Loupedeck CT') {
this.pincodeNumberPositions = PINCODE_NUMBER_POSITIONS_SKIP_FIRST_COL
this.pincodeCodePosition = [2, 4]
this.pincodeCodePosition = [3, 4]
}

this.currentPage = 1 // The current page of the device
Expand Down Expand Up @@ -249,28 +264,10 @@ class SurfaceHandler extends CoreBase {
})
} else if (this.#xkeysPageCount > 0) {
this.#xkeysDrawPages()
} else if (this.panel.info.type === 'Loupedeck CT') {
const gridSize = this.panel.gridSize

for (let y = 0; y < gridSize.rows; y += 1) {
let pageNumber = this.currentPage
if (y >= gridSize.rows) pageNumber += 1
if (pageNumber > 99) pageNumber = 1

for (let x = 0; x < gridSize.columns; x += 1) {
const image = this.graphics.getBank({
pageNumber,
column: x,
row: y % 4,
})

this.panel.draw(x, y, image)
}
}
} else {
const { xOffset, yOffset } = this.#getCurrentOffset()

const gridSize = this.panel.gridSize
const gridSize = this.panelGridSize

for (let y = 0; y < gridSize.rows; y++) {
for (let x = 0; x < gridSize.columns; x++) {
Expand All @@ -280,13 +277,19 @@ class SurfaceHandler extends CoreBase {
row: y + yOffset,
})

this.panel.draw(x, y, image)
this.#drawButtonTransformed(x, y, image)
}
}
}
}
}

#drawButtonTransformed(x, y, image) {
const [transformedX, transformedY] = rotateXYForPanel(x, y, this.panelGridSize, this.panelconfig.config.rotation)

this.panel.draw(transformedX, transformedY, image)
}

getPanelConfig() {
return this.panelconfig.config
}
Expand Down Expand Up @@ -315,20 +318,20 @@ class SurfaceHandler extends CoreBase {
// xkeys mode
const pageOffset = location.pageNumber - this.currentPage
if (pageOffset >= 0 && pageOffset < this.#xkeysPageCount) {
this.panel.drawColor(pageOffset, location.column, location.row, render.style?.bgcolor || 0)
const [transformedX, transformedY] = rotateXYForPanel(
location.column,
location.row,
this.panelGridSize,
this.panelconfig.config.rotation
)

this.panel.drawColor(pageOffset, transformedX, transformedY, render.style?.bgcolor || 0)
}
} else if (
this.panel.info.type === 'Loupedeck CT' &&
(location.pageNumber - this.currentPage == 1 || (location.pageNumber == 1 && this.currentPage == 99)) &&
location.row < 3 // lower half of CT has only 3 rows, zero based
) {
// Loupdeck CT lower half, draw button with row offset by 4
this.panel.draw(location.column, location.row + 4, render)
} else if (location.pageNumber == this.currentPage) {
// normal mode
const { xOffset, yOffset } = this.#getCurrentOffset()

this.panel.draw(location.column - xOffset, location.row - yOffset, render)
this.#drawButtonTransformed(location.column - xOffset, location.row - yOffset, render)
}
}

Expand Down Expand Up @@ -363,10 +366,12 @@ class SurfaceHandler extends CoreBase {
if (!this.isSurfaceLocked) {
this.emit('interaction')

const [x2, y2] = unrotateXYForPanel(x, y, this.panelGridSize, this.panelconfig.config.rotation)

// Translate key for offset
const { xOffset, yOffset } = this.#getCurrentOffset()

const coordinate = `${x + xOffset}/${y + yOffset}`
const coordinate = `${y2 + yOffset}/${x2 + xOffset}`

let thisPage = this.currentPage

Expand All @@ -379,19 +384,19 @@ class SurfaceHandler extends CoreBase {
delete this.#currentButtonPresses[coordinate]
}

// allow the xkeys and loupedeck CT to span pages
// allow the xkeys (legacy mode) to span pages
thisPage += pageOffset ?? 0
// loop at page 99
if (thisPage > 99) thisPage = 1

const controlId = this.page.getControlIdAt({
pageNumber: thisPage,
column: x + xOffset,
row: y + yOffset,
column: x2 + xOffset,
row: y2 + yOffset,
})

this.controls.pressControl(controlId, pressed, this.deviceId)
this.logger.debug(`Button ${thisPage}/${x + xOffset}/${y + yOffset} ${pressed ? 'pressed' : 'released'}`)
this.logger.debug(`Button ${thisPage}/${coordinate} ${pressed ? 'pressed' : 'released'}`)
} else {
if (pressed) {
const pressCode = this.pincodeNumberPositions.findIndex((pos) => pos[0] == x && pos[1] == y)
Expand Down Expand Up @@ -425,24 +430,26 @@ class SurfaceHandler extends CoreBase {
if (!this.isSurfaceLocked) {
this.emit('interaction')

const [x2, y2] = unrotateXYForPanel(x, y, this.panelGridSize, this.panelconfig.config.rotation)

// Translate key for offset
const { xOffset, yOffset } = this.#getCurrentOffset()

let thisPage = this.currentPage

// allow the xkeys and loupedeck CT to span pages
// allow the xkeys (legacy mode) to span pages
thisPage += pageOffset ?? 0
// loop at page 99
if (thisPage > 99) thisPage = 1

const controlId = this.page.getControlIdAt({
pageNumber: thisPage,
column: x + xOffset,
row: y + yOffset,
column: x2 + xOffset,
row: y2 + yOffset,
})

this.controls.rotateControl(controlId, direction, this.deviceId)
this.logger.debug(`Rotary ${thisPage}/${x + xOffset}/${y + yOffset} rotated ${direction ? 'right' : 'left'}`)
this.logger.debug(`Rotary ${thisPage}/${x2 + xOffset}/${y2 + yOffset} rotated ${direction ? 'right' : 'left'}`)
} else {
// Ignore when locked out
}
Expand All @@ -466,7 +473,13 @@ class SurfaceHandler extends CoreBase {
row: xy[1],
})

this.panel.drawColor(page, ...xy, render.style?.bgcolor || 0)
const [transformedX, transformedY] = rotateXYForPanel(
...xy,
this.panelGridSize,
this.panelconfig.config.rotation
)

this.panel.drawColor(page, transformedX, transformedY, render.style?.bgcolor || 0)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Surface/IP/ElgatoPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SurfaceIPElgatoPlugin extends EventEmitter {
this.info = {
type: 'Elgato Streamdeck Plugin',
devicepath: devicepath,
configFields: ['rotation'],
configFields: ['legacy_rotation'],
deviceId: 'plugin',
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Surface/IP/Satellite.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class SurfaceIPSatellite extends EventEmitter {
this.logger.info(`Adding Satellite device "${this.deviceId}"`)

if (this.#streamBitmapSize) {
this.info.configFields.push('rotation')
this.info.configFields.push('legacy_rotation')
}

this._config = {
Expand Down
4 changes: 2 additions & 2 deletions lib/Surface/USB/ElgatoStreamDeck.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import imageRs from '@julusian/image-rs'
import LogController from '../../Log/Controller.js'
import ImageWriteQueue from '../../Resources/ImageWriteQueue.js'
import { translateRotation } from '../../Resources/Util.js'
import { convertXYToIndexForPanel, convertPanelIndexToXY } from '../Util.js'
import { convertXYToIndexForPanel, convertPanelIndexToXY, rotateXYForPanel } from '../Util.js'
const setTimeoutPromise = util.promisify(setTimeout)

class SurfaceUSBElgatoStreamDeck extends EventEmitter {
Expand All @@ -43,7 +43,7 @@ class SurfaceUSBElgatoStreamDeck extends EventEmitter {
this.info = {
type: `Elgato ${this.streamDeck.PRODUCT_NAME}`,
devicepath: devicepath,
configFields: ['brightness', 'rotation'],
configFields: ['brightness', 'legacy_rotation'],
deviceId: undefined, // set in #init()
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Surface/USB/Infinitton.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class SurfaceUSBInfinitton {
this.info = {
type: 'Infinitton iDisplay device',
devicepath: devicepath,
configFields: ['brightness', 'rotation'],
configFields: ['brightness', 'legacy_rotation'],
deviceId: `infinitton:${serialnumber}`,
}

Expand Down
Loading

0 comments on commit 213ba88

Please sign in to comment.