embody
Version:
A digital consciousness training environment
121 lines (89 loc) • 3.14 kB
text/typescript
import robot from 'robotjs'
import Jimp from 'jimp'
import * as path from 'path'
class RobotJSProviderOptions { }
class RobotJSProvider {
options: RobotJSProviderOptions
recordScreenSubscribers: {
[subscriberID: string]: {
callback: (data: any) => void
options: {}
}
} = {}
recordScreenPublisher?: NodeJS.Timeout
x: number = 0
y: number = 0
boundaryWidth: number = 600
boundaryHeight: number = 500
constructor (options: RobotJSProviderOptions) {
this.options = options
const { width, height } = robot.getScreenSize()
this.x = (width / 2) - this.boundaryWidth
this.y = (height / 2) - (this.boundaryHeight / 2)
}
initScreenPublisher () {
// Ensure the screen data publisher isn't already initialized.
// Ensure there are subscribers available to send data to.
if (this.recordScreenPublisher || !this.recordScreenSubscribers) {
return
}
const frameRate = 60
// The screen publisher is a repeated call to capture the screen data and
// send it to the subscribers.
const screenPublisher = setInterval(async () => {
const screenImage = await this.getScreenImage()
// const screenImage = 0
for (const subscriberID of Object.keys(this.recordScreenSubscribers)) {
if (!this.recordScreenSubscribers[subscriberID]) {
continue
}
this.recordScreenSubscribers[subscriberID].callback(screenImage)
}
}, 1000 / frameRate)
this.recordScreenPublisher = screenPublisher
}
startRecordingScreen (subscriberID: string, callback: (data: any) => void, options?: {}): void {
this.recordScreenSubscribers[subscriberID] = {
callback,
options: options || {}
}
this.initScreenPublisher()
}
stopRecordingScreen (subscriberID: string): void {
// Remove the subscriber.
delete this.recordScreenSubscribers[subscriberID]
// If there are no subscribers, stop the publisher.
if (Object.keys(this.recordScreenSubscribers).length < 1) {
clearInterval(this.recordScreenPublisher!)
this.recordScreenPublisher = undefined
}
}
getScreenImage (): Promise<string|Buffer> {
const picture = robot.screen.capture(this.x, this.y, this.boundaryWidth, this.boundaryHeight)
return new Promise((resolve, reject) => {
try {
const image = new Jimp(picture.width, picture.height)
let pos = 0
image.scan(0, 0, image.bitmap.width, image.bitmap.height, (x, y, idx) => {
image.bitmap.data[idx + 2] = picture.image.readUInt8(pos++)
image.bitmap.data[idx + 1] = picture.image.readUInt8(pos++)
image.bitmap.data[idx + 0] = picture.image.readUInt8(pos++)
image.bitmap.data[idx + 3] = picture.image.readUInt8(pos++)
})
image.getBuffer(Jimp.MIME_PNG, (err2, png) => {
resolve(png)
})
} catch (err) {
reject(err)
}
})
}
moveMousePosition (dx: number, dy: number): void {
const { x, y } = robot.getMousePos()
robot.moveMouse(x - dx, y - dy)
}
}
export {
RobotJSProvider,
RobotJSProviderOptions
}