mirror of
https://github.com/DeviceFarmer/stf.git
synced 2026-04-18 08:03:30 +02:00
Integrate new minicap along with a moderate rewrite. What's currently missing is recovering from socket death.
This commit is contained in:
108
lib/units/device/plugins/screen/util/banner.js
Normal file
108
lib/units/device/plugins/screen/util/banner.js
Normal file
@@ -0,0 +1,108 @@
|
||||
var Promise = require('bluebird')
|
||||
|
||||
module.exports.read = function parseBanner(out) {
|
||||
var tryRead
|
||||
|
||||
return new Promise(function(resolve, reject) {
|
||||
var readBannerBytes = 0
|
||||
var needBannerBytes = 2
|
||||
|
||||
var banner = out.banner = {
|
||||
version: 0
|
||||
, length: 0
|
||||
, pid: 0
|
||||
, realWidth: 0
|
||||
, realHeight: 0
|
||||
, virtualWidth: 0
|
||||
, virtualHeight: 0
|
||||
, orientation: 0
|
||||
, quirks: 0
|
||||
}
|
||||
|
||||
tryRead = function() {
|
||||
for (var chunk; (chunk = out.read(needBannerBytes - readBannerBytes));) {
|
||||
for (var cursor = 0, len = chunk.length; cursor < len;) {
|
||||
if (readBannerBytes < needBannerBytes) {
|
||||
switch (readBannerBytes) {
|
||||
case 0:
|
||||
// version
|
||||
banner.version = chunk[cursor]
|
||||
break
|
||||
case 1:
|
||||
// length
|
||||
banner.length = needBannerBytes = chunk[cursor]
|
||||
break
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
// pid
|
||||
banner.pid +=
|
||||
(chunk[cursor] << ((readBannerBytes - 2) * 8)) >>> 0
|
||||
break
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
// real width
|
||||
banner.realWidth +=
|
||||
(chunk[cursor] << ((readBannerBytes - 6) * 8)) >>> 0
|
||||
break
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
// real height
|
||||
banner.realHeight +=
|
||||
(chunk[cursor] << ((readBannerBytes - 10) * 8)) >>> 0
|
||||
break
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
// virtual width
|
||||
banner.virtualWidth +=
|
||||
(chunk[cursor] << ((readBannerBytes - 14) * 8)) >>> 0
|
||||
break
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
// virtual height
|
||||
banner.virtualHeight +=
|
||||
(chunk[cursor] << ((readBannerBytes - 18) * 8)) >>> 0
|
||||
break
|
||||
case 22:
|
||||
// orientation
|
||||
banner.orientation += chunk[cursor] * 90
|
||||
break
|
||||
case 23:
|
||||
// quirks
|
||||
banner.quirks = chunk[cursor]
|
||||
break
|
||||
}
|
||||
|
||||
cursor += 1
|
||||
readBannerBytes += 1
|
||||
|
||||
if (readBannerBytes === needBannerBytes) {
|
||||
return resolve(banner)
|
||||
}
|
||||
}
|
||||
else {
|
||||
reject(new Error(
|
||||
'Supposedly impossible error parsing banner'
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tryRead()
|
||||
|
||||
out.on('readable', tryRead)
|
||||
})
|
||||
.finally(function() {
|
||||
out.removeListener('readable', tryRead)
|
||||
})
|
||||
}
|
||||
40
lib/units/device/plugins/screen/util/broadcastset.js
Normal file
40
lib/units/device/plugins/screen/util/broadcastset.js
Normal file
@@ -0,0 +1,40 @@
|
||||
var util = require('util')
|
||||
|
||||
var EventEmitter = require('eventemitter3').EventEmitter
|
||||
|
||||
function BroadcastSet() {
|
||||
this.set = Object.create(null)
|
||||
this.count = 0
|
||||
}
|
||||
|
||||
util.inherits(BroadcastSet, EventEmitter)
|
||||
|
||||
BroadcastSet.prototype.insert = function(id, ws) {
|
||||
if (!(id in this.set)) {
|
||||
this.set[id] = ws
|
||||
this.count += 1
|
||||
this.emit('insert', id)
|
||||
if (this.count === 1) {
|
||||
this.emit('nonempty')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BroadcastSet.prototype.remove = function(id) {
|
||||
if (id in this.set) {
|
||||
delete this.set[id]
|
||||
this.count -= 1
|
||||
this.emit('remove', id)
|
||||
if (this.count === 0) {
|
||||
this.emit('empty')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BroadcastSet.prototype.each = function(fn) {
|
||||
return Object.keys(this.set).forEach(function(id) {
|
||||
return fn(this.set[id])
|
||||
}, this)
|
||||
}
|
||||
|
||||
module.exports = BroadcastSet
|
||||
22
lib/units/device/plugins/screen/util/frameconfig.js
Normal file
22
lib/units/device/plugins/screen/util/frameconfig.js
Normal file
@@ -0,0 +1,22 @@
|
||||
var util = require('util')
|
||||
|
||||
function FrameConfig(real, virtual) {
|
||||
this.realWidth = real.width
|
||||
this.realHeight = real.height
|
||||
this.virtualWidth = virtual.width
|
||||
this.virtualHeight = virtual.height
|
||||
this.rotation = virtual.rotation
|
||||
}
|
||||
|
||||
FrameConfig.prototype.toString = function() {
|
||||
return util.format(
|
||||
'%dx%d@%dx%d/%d'
|
||||
, this.realWidth
|
||||
, this.realHeight
|
||||
, this.virtualWidth
|
||||
, this.virtualHeight
|
||||
, this.rotation
|
||||
)
|
||||
}
|
||||
|
||||
module.exports = FrameConfig
|
||||
56
lib/units/device/plugins/screen/util/frameparser.js
Normal file
56
lib/units/device/plugins/screen/util/frameparser.js
Normal file
@@ -0,0 +1,56 @@
|
||||
var stream = require('stream')
|
||||
var util = require('util')
|
||||
|
||||
function FrameParser() {
|
||||
this.readFrameBytes = 0
|
||||
this.frameBodyLength = 0
|
||||
this.frameBody = new Buffer(0)
|
||||
stream.Transform.call(this)
|
||||
}
|
||||
|
||||
util.inherits(FrameParser, stream.Transform)
|
||||
|
||||
FrameParser.prototype._transform = function(chunk, encoding, done) {
|
||||
var cursor, len, bytesLeft
|
||||
|
||||
for (cursor = 0, len = chunk.length; cursor < len;) {
|
||||
if (this.readFrameBytes < 4) {
|
||||
this.frameBodyLength +=
|
||||
(chunk[cursor] << (this.readFrameBytes * 8)) >>> 0
|
||||
cursor += 1
|
||||
this.readFrameBytes += 1
|
||||
}
|
||||
else {
|
||||
bytesLeft = len - cursor
|
||||
|
||||
if (bytesLeft >= this.frameBodyLength) {
|
||||
this.frameBody = Buffer.concat([
|
||||
this.frameBody
|
||||
, chunk.slice(cursor, cursor + this.frameBodyLength)
|
||||
])
|
||||
|
||||
this.push(this.frameBody)
|
||||
|
||||
cursor += this.frameBodyLength
|
||||
this.frameBodyLength = this.readFrameBytes = 0
|
||||
this.frameBody = new Buffer(0)
|
||||
}
|
||||
else {
|
||||
// @todo Consider/benchmark continuation frames to prevent
|
||||
// potential Buffer thrashing.
|
||||
this.frameBody = Buffer.concat([
|
||||
this.frameBody
|
||||
, chunk.slice(cursor, len)
|
||||
])
|
||||
|
||||
this.frameBodyLength -= bytesLeft
|
||||
this.readFrameBytes += bytesLeft
|
||||
cursor = len
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return done()
|
||||
}
|
||||
|
||||
module.exports = FrameParser
|
||||
26
lib/units/device/plugins/screen/util/statequeue.js
Normal file
26
lib/units/device/plugins/screen/util/statequeue.js
Normal file
@@ -0,0 +1,26 @@
|
||||
function StateQueue() {
|
||||
this.queue = []
|
||||
}
|
||||
|
||||
StateQueue.prototype.next = function() {
|
||||
return this.queue.shift()
|
||||
}
|
||||
|
||||
StateQueue.prototype.push = function(state) {
|
||||
var found = false
|
||||
|
||||
// Not super efficient, but this shouldn't be running all the time anyway.
|
||||
for (var i = 0, l = this.queue.length; i < l; ++i) {
|
||||
if (this.queue[i] === state) {
|
||||
this.queue.splice(i + 1)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
this.queue.push(state)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StateQueue
|
||||
Reference in New Issue
Block a user