diff --git a/examples/index.html b/examples/index.html
index 7955aac..67a72f7 100644
--- a/examples/index.html
+++ b/examples/index.html
@@ -53,6 +53,12 @@
GET_DEF: 0x87,
}
+ const FIELD_TYPE = {
+ BOOLEAN: 'BOOLEAN',
+ BITMAP: 'BITMAP',
+ NUMBER: 'NUMBER',
+ }
+
const video = document.querySelector('video')
const camSelector = document.querySelector('select')
const camControls = document.querySelector('.cam-controls')
@@ -93,65 +99,100 @@
console.log(controlDescriptions)
const camControlsHTML = await Promise.all(controlDescriptions.map(async ctrl => {
- // TODO support controls with multiple fields
let currentVal = await fetch(`/get/${ctrl.name}`).then(res => res.json())
console.log('currentVal', ctrl.name, currentVal)
- currentVal = Object.values(currentVal)[0]
- // console.log(ctrl.fields[0].type)
+ const fieldControlsHTML = await Promise.all(ctrl.fields.map(async (field, i) => {
+ // console.log(field)
+ const fieldVal = currentVal[field.name]
+ const id = `${ctrl.name}-${field.name}`
+
+ if (ctrl.requests.indexOf(REQUEST.GET_MIN) !== -1) {
+ try {
+ const minMax = await fetch(`/range/${ctrl.name}`).then(res => res.json())
+ return `
`
+ } catch (e) {
+ return ''
+ }
+ } else if (field.options) {
- if (ctrl.requests.indexOf(REQUEST.GET_MIN) !== -1) {
- // range
- // console.log('range', ctrl.name)
- try {
- const minMax = await fetch(`/range/${ctrl.name}`).then(res => res.json())
- return ``
- } catch (e) {
+ let options = Object.entries(field.options).map(([key, val]) => {
+ const selected = fieldVal === val ? 'selected' : ''
+ return ``
+ })
+ return ``
+
+ } else if (field.type === FIELD_TYPE.BOOLEAN) {
+ return ``
+ } else {
return ''
}
- } else if (ctrl.fields[0].options) {
- let options = Object.entries(ctrl.fields[0].options).map(([key, val]) =>
- ``)
- // TODO set selected index
- return ``
+ }))
+ return `${ctrl.name}
${fieldControlsHTML.join('')}`
- } else if (ctrl.fields[0].type === 'Boolean') {
- return ``
- } else {
- return ''
- }
}))
camControls.innerHTML += camControlsHTML.join('')
- document.querySelectorAll('.range.ctrl input').forEach(ctrlEl => {
+ const listenForFieldControlChanges = (ctrlEl) => {
ctrlEl.addEventListener('change', (e) => {
console.log(ctrlEl.id, ctrlEl.value)
- fetch(`/set/${ctrlEl.id}/${ctrlEl.value}`, {
+ const [controlId] = ctrlEl.id.split('-')
+ const values = getSiblingFieldValues(controlId).join()
+ fetch(`/set/${controlId}/${values}`, {
method: 'POST'
})
})
- })
+ }
+ document.querySelectorAll('.range.ctrl input').forEach(listenForFieldControlChanges)
+ document.querySelectorAll('.select.ctrl select').forEach(listenForFieldControlChanges)
+ document.querySelectorAll('.bool.ctrl input').forEach(listenForFieldControlChanges)
+
+ // document.querySelectorAll('.range.ctrl input').forEach(ctrlEl => {
+ // ctrlEl.addEventListener('change', (e) => {
+ // console.log(ctrlEl.id, ctrlEl.value)
+ // const [controlId] = ctrlEl.id.split('-')
+ // const values = getSiblingFieldValues(controlId).join()
+ // fetch(`/set/${controlId}/${values}`, {
+ // method: 'POST'
+ // })
+ // })
+ // })
+
+ // document.querySelectorAll('.select.ctrl select').forEach(ctrlEl => {
+ // ctrlEl.addEventListener('change', (e) => {
+ // console.log(ctrlEl.id, ctrlEl.value)
+ // const [controlId] = ctrlEl.id.split('-')
+ // const values = getSiblingFieldValues(controlId).join()
+ // fetch(`/set/${controlId}/${values}`, {
+ // method: 'POST'
+ // })
+ // })
+ // })
+
+ // document.querySelectorAll('.bool.ctrl input').forEach(ctrlEl => {
+ // ctrlEl.addEventListener('change', (e) => {
+ // console.log(ctrlEl.checked)
+ // const [controlId] = ctrlEl.id.split('-')
+ // const values = getSiblingFieldValues(controlId).join()
+ // fetch(`/set/${controlId}/${values}`, {
+ // method: 'POST'
+ // })
+ // })
+ // })
- document.querySelectorAll('.select.ctrl select').forEach(ctrlEl => {
- ctrlEl.addEventListener('change', (e) => {
- console.log(ctrlEl.id, ctrlEl.value)
- fetch(`/set/${ctrlEl.id}/${ctrlEl.value}`, {
- method: 'POST'
- })
- })
- })
+ }
- document.querySelectorAll('.bool.ctrl input').forEach(ctrlEl => {
- ctrlEl.addEventListener('change', (e) => {
- console.log(ctrlEl.checked)
- fetch(`/set/${ctrlEl.id}/${ctrlEl.checked ? 1 : 0}`, {
- method: 'POST'
- })
- })
+ function getSiblingFieldValues(controlId) {
+ const controlDiv = document.querySelector(`#${controlId}`)
+ const values = []
+ controlDiv.querySelectorAll('.ctrl').forEach(ctrl => {
+ const input = ctrl.querySelector('input, select')
+ if (input.type === 'checkbox') values.push(input.checked ? 1 : 0)
+ else values.push(input.value)
})
-
+ return values
}
setup()
diff --git a/examples/server.js b/examples/server.js
index 34a93e8..fb829d7 100644
--- a/examples/server.js
+++ b/examples/server.js
@@ -39,11 +39,6 @@ app.get('/range/:control', (req, res) => {
app.post('/set/:control/:values', (req, res) => {
let values = req.params.values.split(',')
- // values = values.map(val => {
- // if (val === 'true') return 1
- // else if (val === 'false') return 0
- // else return val
- // })
console.log('setting', req.params.control, values)
cam.set(req.params.control, ...values).then(vals => {
res.send('ok')
diff --git a/index.js b/index.js
index 0a6f6d2..b84f541 100644
--- a/index.js
+++ b/index.js
@@ -7,6 +7,7 @@ const {
// VS,
// VS_DESCRIPTOR_SUBTYPE,
BM_REQUEST_TYPE,
+ FIELD_TYPE,
REQUEST,
KEY,
} = require('./lib/constants')
@@ -181,7 +182,7 @@ class UVCControl extends EventEmitter {
// NOTE min fixes out of bounds error, but this approach doesn't account for multiple fields...
let int = buffer.readIntLE(field.offset, Math.min(buffer.byteLength, field.size))
let result = int
- if (field.type === 'Boolean') {
+ if (field.type === FIELD_TYPE.BOOLEAN) {
result = Boolean(int)
}
const results = {
diff --git a/lib/constants.js b/lib/constants.js
index 963c43a..a39bc9a 100644
--- a/lib/constants.js
+++ b/lib/constants.js
@@ -42,6 +42,12 @@ const KEY = {
PAL_525_60: 'PAL_525_60',
}
+const FIELD_TYPE = {
+ BOOLEAN: 'BOOLEAN',
+ BITMAP: 'BITMAP',
+ NUMBER: 'NUMBER',
+}
+
const BM_REQUEST_TYPE = {
GET: 0b10100001,
SET: 0b00100001,
@@ -183,4 +189,5 @@ module.exports = {
REQUEST,
BM_REQUEST_TYPE,
VS_DESCRIPTOR_SUBTYPE,
+ FIELD_TYPE,
}
diff --git a/lib/controls.js b/lib/controls.js
index 7f49df4..dfc0f5b 100644
--- a/lib/controls.js
+++ b/lib/controls.js
@@ -2,6 +2,7 @@
// http://www.usb.org/developers/docs/devclass_docs/
const {
+ FIELD_TYPE,
REQUEST,
PU,
CT,
@@ -27,7 +28,7 @@ const CONTROLS = {
// description: 'The setting for the Still Image Trigger Control',
// offset: 0,
// size: 1,
- // type: 'Number',
+ // type: FIELD_TYPE.NUMBER,
// options: {
// NORMAL: 0,
// TRANSMIT: 1,
@@ -57,7 +58,7 @@ const CONTROLS = {
description: 'The setting for the attribute of the addressed Auto-Exposure Mode Control',
offset: 0,
size: 1,
- type: 'Bitmap',
+ type: FIELD_TYPE.BITMAP,
options: {
MANUAL: 0b00000001,
AUTO: 0b00000010,
@@ -80,7 +81,7 @@ const CONTROLS = {
fields: [{
name: 'bAutoExposurePriority',
description: 'The setting for the attribute of the addressed AutoExposure Priority control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 1,
}]
@@ -102,7 +103,7 @@ const CONTROLS = {
fields: [{
name: 'dwExposureTimeAbsolute',
description: 'The setting for the attribute of the addressed Exposure Time (Absolute) Control. 0: Reserved, 1: 0.0001 sec, 100000: 10 sec',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 4,
}]
@@ -123,7 +124,7 @@ const CONTROLS = {
fields: [{
name: 'wFocusAbsolute',
description: 'The setting for the attribute of the addressed Focus (Absolute) Control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -147,7 +148,7 @@ const CONTROLS = {
fields: [{
name: 'wObjectiveFocalLength',
description: 'The value of Zcur(see section 2.4.2.5.1 "Optical Zoom".)',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -171,13 +172,13 @@ const CONTROLS = {
fields: [{
name: 'dwPanAbsolute',
description: 'The setting for the attribute of the addressed Pan (Absolute) Control.',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 4,
}, {
name: 'dwTiltAbsolute',
description: 'The setting for the attribute of the addressed Tilt (Absolute) Control.',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 4,
size: 4,
}],
@@ -196,7 +197,7 @@ const CONTROLS = {
fields: [{
name: 'bFocusAuto',
description: 'The setting for the attribute of the addressed Focus Auto control.',
- type: 'Boolean',
+ type: FIELD_TYPE.BOOLEAN,
offset: 0,
size: 1,
}],
@@ -215,7 +216,7 @@ const CONTROLS = {
fields: [{
name: 'bScanningMode',
description: 'The setting for the attribute of the addressed Scanning Mode Control',
- type: 'Boolean',
+ type: FIELD_TYPE.BOOLEAN,
offset: 0,
size: 1,
options: {
@@ -237,7 +238,7 @@ const CONTROLS = {
fields: [{
name: 'bExposureTimeRelative',
description: 'The setting for the attribute of the addressed Exposure Time (Relative) Control',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 1,
options: {
@@ -264,7 +265,7 @@ const CONTROLS = {
fields: [{
name: 'bFocusRelative',
description: 'The setting for the attribute of the addressed Focus (Relative) Control',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 1,
options: {
@@ -275,7 +276,7 @@ const CONTROLS = {
}, {
name: 'bSpeed',
description: 'Speed for the control change',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 1,
size: 1,
}],
@@ -301,7 +302,7 @@ const CONTROLS = {
description: 'The setting for the attribute of the addressed Iris (Absolute) Control.',
offset: 0,
size: 2,
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
}],
},
[KEY.relative_iris]: {
@@ -317,7 +318,7 @@ const CONTROLS = {
fields: [{
name: 'bIrisRelative',
description: 'The setting for the attribute of the addressed Iris (Relative) Control',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 1,
options: {
@@ -344,7 +345,7 @@ const CONTROLS = {
fields: [{
name: 'bZoom',
description: 'The setting for the attribute of the addressed Zoom Control',
- type: 'Number', // Signed number
+ type: FIELD_TYPE.NUMBER, // Signed number
offset: 0,
size: 1,
options: {
@@ -357,7 +358,7 @@ const CONTROLS = {
name: 'bDigitalZoom',
offset: 1,
size: 1,
- type: 'Boolean',
+ type: FIELD_TYPE.BOOLEAN,
options: {
OFF: 0,
ON: 1,
@@ -365,7 +366,7 @@ const CONTROLS = {
}, {
name: 'bSpeed',
description: 'Speed for the control change',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 2,
size: 1,
}
@@ -388,7 +389,7 @@ const CONTROLS = {
fields: [{
name: 'bPanRelative',
description: 'The setting for the attribute of the addressed Pan(Relative) Control',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 1,
options: {
@@ -399,7 +400,7 @@ const CONTROLS = {
}, {
name: 'bPanSpeed',
description: 'Speed of the Pan movement',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 1,
size: 1,
}, {
@@ -407,7 +408,7 @@ const CONTROLS = {
description: 'The setting for the attribute of the addressed Tilt(Relative) Control',
offset: 2,
size: 1,
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
options: {
STOP: 0,
UP: 1,
@@ -416,7 +417,7 @@ const CONTROLS = {
}, {
name: 'bTiltSpeed',
description: 'Speed for the Tilt movement',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 3,
size: 1,
}],
@@ -440,7 +441,7 @@ const CONTROLS = {
fields: [{
name: 'wRollAbsolute',
description: 'The setting for the attribute of the addressed Roll (Absolute) Control.',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 2,
}],
@@ -462,7 +463,7 @@ const CONTROLS = {
fields: [{
name: 'bRollRelative',
description: 'The setting for the attribute of the addressed Roll (Relative) Control',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 1,
options: {
@@ -475,7 +476,7 @@ const CONTROLS = {
description: 'Speed for the Roll movement',
offset: 1,
size: 1,
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
}],
},
[KEY.privacy]: {
@@ -493,7 +494,7 @@ const CONTROLS = {
fields: [{
name: 'bPrivacy',
description: 'The setting for the attribute of the addressed Privacy Control',
- type: 'Boolean',
+ type: FIELD_TYPE.BOOLEAN,
offset: 0,
size: 1,
options: {
@@ -520,7 +521,7 @@ const CONTROLS = {
fields: [{
name: 'bPowerLineFrequency',
description: 'The setting for the attribute of the addressed Power Line Frequency control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 1,
options: {
@@ -549,7 +550,7 @@ const CONTROLS = {
fields: [{
name: 'wHue',
description: 'The setting for the attribute of the addressed Hue control.',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 2,
}],
@@ -573,13 +574,13 @@ const CONTROLS = {
fields: [{
name: 'wWhiteBalanceBlue',
description: 'The setting for the blue component of the addressed White Balance Component control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}, {
name: 'wWhiteBalanceRed',
description: 'The setting for the red component of the addressed White Balance Component control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 1,
size: 2,
}],
@@ -598,7 +599,7 @@ const CONTROLS = {
fields: [{
name: 'bWhiteBalanceComponentAuto',
description: 'The setting for the attribute of the addressed White Balance Component, Auto control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 1,
}],
@@ -620,7 +621,7 @@ const CONTROLS = {
fields: [{
name: 'wMultiplierStep',
description: 'The value Z′cur (see section 2.4.2.5.2 "Digital Zoom".)',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -642,7 +643,7 @@ const CONTROLS = {
fields: [{
name: 'wMultiplierLimit',
description: 'A value specifying the upper bound for Z′cur (see section 2.4.2.5.2 "Digital Zoom".)',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -661,7 +662,7 @@ const CONTROLS = {
fields: [{
name: 'bHueAuto',
description: 'The setting for the attribute of the addressed Hue, Auto control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 1,
}],
@@ -678,7 +679,7 @@ const CONTROLS = {
fields: [{
name: 'bVideoStandard',
description: 'The Analog Video Standard of the input video signal.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 1,
options: {
@@ -703,7 +704,7 @@ const CONTROLS = {
fields: [{
name: 'bStatus',
description: 'Lock status',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 1,
options: {
@@ -729,7 +730,7 @@ const CONTROLS = {
fields: [{
name: 'wBrightness',
description: 'The setting for the attribute of the addressed Brightness control.',
- type: 'Number', // Signed Number
+ type: FIELD_TYPE.NUMBER, // Signed Number
offset: 0,
size: 2,
}],
@@ -751,7 +752,7 @@ const CONTROLS = {
fields: [{
name: 'wContrast',
description: 'The setting for the attribute of the addressed Contrast control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -773,7 +774,7 @@ const CONTROLS = {
fields: [{
name: 'wGain',
description: 'The setting for the attribute of the addressed Gain control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -795,7 +796,7 @@ const CONTROLS = {
fields: [{
name: 'wSaturation',
description: 'The setting for the attribute of the addressed Saturation control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -817,7 +818,7 @@ const CONTROLS = {
fields: [{
name: 'wSharpness',
description: 'The setting for the attribute of the addressed Sharpness control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -841,7 +842,7 @@ const CONTROLS = {
fields: [{
name: 'wWhiteBalanceTemperature',
description: 'The setting for the attribute of the addressed White Balance Temperature control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -863,7 +864,7 @@ const CONTROLS = {
fields: [{
name: 'wBacklightCompensation',
description: 'The setting for the attribute of the addressed Backlight Compensation control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -885,7 +886,7 @@ const CONTROLS = {
fields: [{
name: 'wGain',
description: 'The setting for the attribute of the addressed Gain control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],
@@ -904,7 +905,7 @@ const CONTROLS = {
fields: [{
name: 'bWhiteBalanceTemperatureAuto',
description: 'The setting for the attribute of the addressed White Balance Temperature, Auto control.',
- type: 'Number',
+ type: FIELD_TYPE.BOOLEAN,
offset: 0,
size: 1,
}],
@@ -926,7 +927,7 @@ const CONTROLS = {
fields: [{
name: 'wGamma',
description: 'The setting for the attribute of the addressed Gamma control.',
- type: 'Number',
+ type: FIELD_TYPE.NUMBER,
offset: 0,
size: 2,
}],