//OTHER devices follow a general format:
/*
connect -> init device and scripts
disconnect -> close device connection
onconnect -> onconnect callback you can customize
ondata -> ondata callback you can customize
ondisconnect -> disconnect callback you can customize
codec -> optionally used to transform streams e.g. on a separate thread, libraries like muse-js already do it for us so we can just customize ondata to handle output, or use the codec to do some kind of special math on a thread
*/
import { WebglLinePlotProps } from "webgl-plot-utils";
import { FilterSettings } from "../../util/BiquadFilters";
import {webgazer} from "./dependencies/webgazer.esm" //imports "webgazer"
export {webgazer}
const sps = 30; //?? variable
export const webgazerSettings = { //include muse-js and import {MuseClient} from 'muse-js' for this to work
sps,
deviceType:'CUSTOM',
deviceName:'webgazer',
debug:false, //set to true to see a video feed with face tracking data
regression:'weightedRidge',
regressionModule:undefined,
tracker:undefined,
trackerModule:undefined,
connect:(settings:any={}) => {
return new Promise(async (res,rej) => {
let _id = `webgazer${Math.floor(Math.random()*1000000000000000)}`;
// //@ts-ignore
// if(typeof Ganglion === 'undefined') { document.head.insertAdjacentHTML('beforeend',``) }
let info = {
_id,
webgazer,
//begun:false,
settings:Object.assign(Object.assign({},webgazerSettings),settings) //e.g. customize ondisconnect
}
//if(!info.begun) {
webgazer.setGazeListener((data:{
eyeFeatures: any,
x: number,
y: number
},_:number) => {
if(data == null) return;
info.settings.ondata(data);
}).begin();
//} else webgazer.resume();
if(settings.tracker)
webgazer.setTracker(settings.tracker);
if(settings.trackerModule)
webgazer.addTrackerModule("newTracker", settings.trackerModule);
if(settings.regression)
webgazer.setRegression(settings.regression);
if(settings.regressionModule)
webgazer.addRegressionModule("newReg", settings.regressionModule);
if(info.settings.debug) {
webgazer.showVideo(true);
webgazer.showFaceOverlay(true);
webgazer.showFaceFeedbackBox(true);
webgazer.showPredictionPoints(true);
let interval = setInterval(() => {
if(webgazer.isReady()) {
clearInterval(interval);
let video = document.getElementById('webgazerVideoContainer')
if (video) {
video.style.position = 'absolute';
video.style.top = '0';
video.style.left = 'auto';
video.style.right = '0';
video.style.zIndex = '1000';
video.style.width = '200px';
video.style.height = '200px';
}
}
else {
console.log('webgazer not loaded ____')
}
},1000);
}
if(info.settings.onconnect) info.settings.onconnect(info);
res(info);
})
},
codec:(reading:{eyeFeatures:any, x:number, y:number}) => { //remap outputs to more or less match the rest of our formatting
return reading
},
disconnect:(info) => {
info.webgazer.end();
//info.webgazer.pause();
},
onconnect:(info)=>{
console.log('webgazer connected!', info);
},
beforedisconnect:(info) => {
},
ondisconnect:(info)=>{
console.log('webgazer disconnected!', info);
},
ondata:(data:any)=>{
console.log(data); //direct from teh device output
},
read:(info:any,command?:any)=>{
return info.webgazer.getCurrentPrediction();
},
distance:function (x1, y1, x2, y2) {
let x = (x1-x2)*(x1-x2);
let y = (y1-y2)*(y1-y2);
return Math.sqrt(x+y);
}
//write:(info:any,command?:any)=>{}
}
const defaultChartSetting = {nSec:10, sps, units:'px'};
export const webgazerChartSettings:Partial = {
lines:{
'x':JSON.parse(JSON.stringify(defaultChartSetting)),
'y':JSON.parse(JSON.stringify(defaultChartSetting)),
},
generateNewLines:false
};