UNPKG

gazeplotter

Version:

Gazeplotter is a Svelte application for visualizing eye-tracking data.

96 lines (95 loc) 3.08 kB
import { EyePipeline } from '../class/Eye/EyePipeline/EyePipeline.ts'; /** * A worker file handling whole eyefiles processing. * It is a separate file to avoid blocking the main thread. */ let fileNames = []; let pipeline = null; let streams = []; let userInputResolver; const isStringArray = (data) => { if (!Array.isArray(data)) return false; if (data.length === 0) return false; return typeof data[0] === 'string'; }; const isReadableStream = (data) => { if (typeof data !== 'object') return false; if (data === null) return false; return typeof data.getReader === 'function'; }; const requestUserInput = () => { self.postMessage({ type: 'request-user-input' }); return new Promise(resolve => { userInputResolver = resolve; }); }; self.onmessage = async (e) => await processEvent(e); async function processEvent(e) { const { data, type } = e.data; switch (type) { case 'file-names': if (!isStringArray(data)) throw new Error('File names are not string[]'); fileNames = data; pipeline = new EyePipeline(fileNames, requestUserInput); return; case 'test-stream': if (!isReadableStream(data)) throw new Error('Stream is not ReadableStream'); return; case 'stream': return await evalStream(data); case 'buffer': return await evalBuffer(data); case 'user-input': return userInputResolver(data); default: throw new Error('Unknown const type in worker', data); } } /** * Converts ArrayBuffer to ReadableStream and passes it to evalStream * @param buffer - The buffer to convert. */ const evalBuffer = async (buffer) => { const chunkSize = 1024 * 1024; const chunks = Math.ceil(buffer.byteLength / chunkSize); const stream = new ReadableStream({ start(controller) { for (let i = 0; i < chunks; i++) { const start = i * chunkSize; const end = Math.min(start + chunkSize, buffer.byteLength); controller.enqueue(new Uint8Array(buffer.slice(start, end))); } controller.close(); }, }); await evalStream(stream); }; /** * Adds a new stream to the pipeline and processes it if all streams are present. * @param rs - The stream to add. */ const evalStream = async (rs) => { if (pipeline === null) throw new Error('Pipeline is not initialized'); if (fileNames.length === 0) throw new Error('No files to process'); streams.push(rs); // if have everything, process if (streams.length === fileNames.length) { for (const stream of streams) { const data = await pipeline.addNewStream(stream); if (data !== null) { console.log('Done', data); self.postMessage({ type: 'done', data }); streams = []; fileNames = []; } } } };