@viji-dev/core 0.2.13 → 0.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/artist-dts-p5.d.ts +1 -0
- package/dist/artist-dts-p5.js +1 -0
- package/dist/artist-dts.js +1 -1
- package/dist/artist-global.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shader-uniforms.d.ts +4 -0
- package/dist/shader-uniforms.js +278 -0
- package/package.json +9 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/types/index.ts","../src/iframe/IFrameManager.ts","../src/worker/WorkerManager.ts","../src/interaction/InteractionManager.ts","../src/audio/AudioSystem.ts","../src/video/VideoCoordinator.ts","../src/VijiCore.ts","../src/index.ts"],"sourcesContent":["// Core configuration types\nexport interface VijiCoreConfig {\n /** Container element where the scene will be rendered */\n hostContainer: HTMLElement;\n \n /** Artist scene code to execute */\n sceneCode: string;\n \n /** Frame rate mode - 'full' for every animation frame, 'half' for every second frame */\n frameRateMode?: FrameRateMode;\n \n /** Enable automatic performance optimization */\n autoOptimize?: boolean;\n \n /** Audio input stream */\n audioStream?: MediaStream;\n \n /** Video input stream */\n videoStream?: MediaStream;\n \n /** Audio analysis configuration */\n analysisConfig?: AnalysisConfiguration;\n \n /** Initial parameter values */\n parameters?: ParameterGroup[];\n \n /** Disable input processing (for preview instances) */\n noInputs?: boolean;\n \n /** Enable user interaction events */\n allowUserInteraction?: boolean;\n}\n\n// Capture frame options\nexport interface CaptureFrameOptions {\n /** MIME type for output, e.g., 'image/png', 'image/jpeg', 'image/webp' */\n type?: string;\n /**\n * Target resolution.\n * - number: scale factor relative to current canvas size (e.g., 0.5 = 50%)\n * - { width, height }: exact output size; if aspect ratio differs from canvas,\n * the source is center-cropped to match the target aspect ratio before scaling\n */\n resolution?: number | { width: number; height: number };\n}\n\n// Core capabilities state\nexport interface CoreCapabilities {\n /** Audio input is active and connected */\n hasAudio: boolean;\n \n /** Video input is active and connected */\n hasVideo: boolean;\n \n /** User interactions (mouse, touch, keyboard) are enabled */\n hasInteraction: boolean;\n \n /** General parameters are always available */\n hasGeneral: boolean;\n}\n\n// Resolution types\nexport type Resolution = { width: number; height: number; }\n\n// Parameter category system\nexport type ParameterCategory = 'audio' | 'video' | 'interaction' | 'general';\n\n// Enhanced parameter system types for Phase 2\nexport interface ParameterGroup {\n groupName: string;\n category?: ParameterCategory;\n description?: string;\n collapsed?: boolean;\n order?: number;\n parameters: Record<string, ParameterDefinition>;\n}\n\nexport interface ParameterDefinition {\n type: 'slider' | 'color' | 'toggle' | 'select' | 'text' | 'number' | 'image';\n defaultValue: any;\n label?: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n config?: ParameterConfig;\n // Validation function\n validate?: (value: any) => boolean;\n}\n\nexport interface ParameterConfig {\n // For slider/number types\n min?: number;\n max?: number;\n step?: number;\n \n // For select type\n options?: string[] | number[];\n \n // For text type\n maxLength?: number;\n \n // UI configuration\n label?: string;\n description?: string;\n hidden?: boolean;\n \n // Advanced configuration\n precision?: number; // For number display precision\n}\n\n// Parameter object types (returned by helper functions)\nexport interface SliderParameter {\n value: number;\n min: number;\n max: number;\n step: number;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface ColorParameter {\n value: string;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface ToggleParameter {\n value: boolean;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface SelectParameter {\n value: string | number;\n options: string[] | number[];\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface TextParameter {\n value: string;\n maxLength?: number;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface NumberParameter {\n value: number;\n min: number;\n max: number;\n step: number;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface ImageParameter {\n value: ImageBitmap | OffscreenCanvas | null;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\n// Parameter helper function configurations\nexport interface SliderConfig {\n min?: number;\n max?: number;\n step?: number;\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface ColorConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface ToggleConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface SelectConfig {\n options: string[] | number[];\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface TextConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n maxLength?: number;\n}\n\nexport interface NumberConfig {\n min?: number;\n max?: number;\n step?: number;\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface ImageConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\n// Parameter value types\nexport type ParameterValue = string | number | boolean | ImageBitmap | OffscreenCanvas | null;\n\n// Parameter update message data\nexport interface ParameterUpdateData {\n name: string;\n value: ParameterValue;\n}\n\nexport interface ParameterBatchUpdateData {\n updates: ParameterUpdateData[];\n}\n\n// Parameter definition extraction data\nexport interface ParameterDefinitionData {\n groups: ParameterGroup[];\n}\n\n// Audio analysis configuration\nexport interface AnalysisConfiguration {\n fftSize?: number;\n smoothing?: number;\n frequencyBands?: FrequencyBand[];\n beatDetection?: boolean;\n onsetDetection?: boolean;\n}\n\nexport interface FrequencyBand {\n name: string;\n min: number;\n max: number;\n}\n\n// Frame rate mode types\nexport type FrameRateMode = 'full' | 'half';\n\n// CV frame rate mode types (relative to scene processing rate)\nexport type CVFrameRateMode = 'full' | 'half' | 'quarter' | 'eighth';\n\n// Renderer type for P5.js support\nexport type RendererType = 'native' | 'p5' | 'shader';\n\nexport interface FrameRateInfo {\n mode: FrameRateMode;\n screenRefreshRate: number;\n effectiveRefreshRate: number;\n}\n\n// Performance monitoring\nexport interface PerformanceStats {\n frameTime: number;\n resolution: Resolution;\n scale: number;\n frameRate: FrameRateInfo;\n rendererType: RendererType;\n memoryUsage?: number;\n activeStreams?: number;\n parameterCount?: number;\n // CV Processing Stats (integrated)\n cv?: {\n activeFeatures: CVFeature[];\n processingTime: number; // average processing time in milliseconds\n targetFPS: number; // target CV FPS based on scene rate and CV rate mode\n actualFPS: number; // actual measured CV processing FPS\n isProcessing: boolean;\n };\n}\n\n// Communication message types\nexport interface Message {\n type: string;\n id: string;\n timestamp: number;\n data?: any;\n}\n\nexport interface HostToWorkerMessage extends Message {\n type:\n | 'init'\n | 'parameter-update'\n | 'parameter-batch-update'\n | 'stream-update'\n | 'performance-update'\n | 'capture-frame';\n}\n\nexport interface WorkerToHostMessage extends Message {\n type:\n | 'init-response'\n | 'ready'\n | 'parameters-defined'\n | 'parameter-validation-error'\n | 'error'\n | 'performance-warning'\n | 'capture-frame-result';\n}\n\n// Resource management types\nexport interface ResourceTracker {\n workers: Set<Worker>;\n iframes: Set<HTMLIFrameElement>;\n streams: Set<MediaStream>;\n contexts: Set<AudioContext | CanvasRenderingContext2D | WebGLRenderingContext>;\n}\n\n// Enhanced Artist API types (provided to artist code)\nexport interface VijiAPI {\n // Canvas and rendering\n canvas: OffscreenCanvas;\n ctx?: OffscreenCanvasRenderingContext2D;\n gl?: WebGL2RenderingContext;\n width: number;\n height: number;\n pixelRatio: number;\n \n // Timing\n time: number;\n deltaTime: number;\n frameCount: number;\n fps: number;\n \n // Audio (when available)\n audio: AudioAPI;\n \n // Video (when available) \n video: VideoAPI;\n \n // User interaction\n mouse: MouseAPI;\n keyboard: KeyboardAPI;\n touches: TouchAPI;\n \n // Parameter helper functions (return parameter objects)\n slider: (defaultValue: number, config: SliderConfig) => SliderParameter;\n color: (defaultValue: string, config: ColorConfig) => ColorParameter;\n toggle: (defaultValue: boolean, config: ToggleConfig) => ToggleParameter;\n select: (defaultValue: string | number, config: SelectConfig) => SelectParameter;\n text: (defaultValue: string, config: TextConfig) => TextParameter;\n number: (defaultValue: number, config: NumberConfig) => NumberParameter;\n image: (defaultValue: null, config: ImageConfig) => ImageParameter;\n \n // Utility methods\n useContext(type: '2d' | 'webgl'): OffscreenCanvasRenderingContext2D | WebGLRenderingContext | WebGL2RenderingContext | null;\n}\n\n// Audio API\nexport interface AudioAPI {\n isConnected: boolean;\n volume: {\n rms: number;\n peak: number;\n };\n beat?: {\n isKick: boolean;\n confidence: number;\n };\n bands: Record<string, number>;\n getFrequencyData: () => Uint8Array;\n}\n\n// Video API\nexport interface VideoAPI {\n isConnected: boolean;\n currentFrame: OffscreenCanvas | null;\n frameWidth: number;\n frameHeight: number;\n frameRate: number;\n getFrameData: () => ImageData | null;\n \n // CV Results (automatically cleaned up when features disabled)\n faces: FaceData[];\n hands: HandData[];\n pose: PoseData | null;\n segmentation: SegmentationData | null;\n \n // CV Control Interface (activation only)\n cv: {\n enableFaceDetection(enabled: boolean): Promise<void>;\n enableFaceMesh(enabled: boolean): Promise<void>;\n enableHandTracking(enabled: boolean): Promise<void>;\n enablePoseDetection(enabled: boolean): Promise<void>;\n enableBodySegmentation(enabled: boolean): Promise<void>;\n getActiveFeatures(): CVFeature[];\n isProcessing(): boolean;\n };\n}\n\n// CV Feature Types\nexport type CVFeature = 'faceDetection' | 'faceMesh' | 'handTracking' | 'poseDetection' | 'bodySegmentation';\n\n// Enhanced Face Data with comprehensive landmarks and expressions\nexport interface FaceData {\n id: number;\n bounds: { x: number; y: number; width: number; height: number };\n confidence: number;\n landmarks?: { x: number; y: number; z?: number }[]; // 468 points for mesh, 6 points for basic\n expressions: {\n neutral: number;\n happy: number;\n sad: number;\n angry: number;\n surprised: number;\n disgusted: number;\n fearful: number;\n };\n headPose: {\n pitch: number; // Up/down rotation (-90 to 90 degrees)\n yaw: number; // Left/right rotation (-90 to 90 degrees)\n roll: number; // Tilt rotation (-180 to 180 degrees)\n };\n}\n\n// Enhanced Hand Data with comprehensive landmarks and gesture recognition\nexport interface HandData {\n id: number;\n handedness: 'left' | 'right';\n confidence: number;\n bounds: { x: number; y: number; width: number; height: number };\n landmarks: { x: number; y: number; z: number }[]; // 21 points\n \n // Palm and finger positions\n palm: { x: number; y: number; z: number };\n fingers: {\n thumb: { tip: {x: number; y: number; z: number}; extended: boolean };\n index: { tip: {x: number; y: number; z: number}; extended: boolean };\n middle: { tip: {x: number; y: number; z: number}; extended: boolean };\n ring: { tip: {x: number; y: number; z: number}; extended: boolean };\n pinky: { tip: {x: number; y: number; z: number}; extended: boolean };\n };\n \n // Recognized gestures with confidence scores\n gestures: {\n fist: number; // 0-1 confidence\n openPalm: number; // 0-1 confidence\n peace: number; // 0-1 confidence\n thumbsUp: number; // 0-1 confidence\n pointing: number; // 0-1 confidence\n };\n}\n\n// Body Pose Data with 33-point BlazePose landmarks\nexport interface PoseData {\n confidence: number;\n landmarks: { x: number; y: number; z: number; visibility: number }[]; // 33 points\n \n // Key body parts for easy access\n face: { x: number; y: number }[];\n torso: { x: number; y: number }[];\n leftArm: { x: number; y: number }[];\n rightArm: { x: number; y: number }[];\n leftLeg: { x: number; y: number }[];\n rightLeg: { x: number; y: number }[];\n}\n\n// Body Segmentation Data for background replacement effects\nexport interface SegmentationData {\n mask: Uint8Array; // Per-pixel segmentation mask (0=background, 1=person)\n width: number; // Mask width in pixels\n height: number; // Mask height in pixels\n}\n\n// CV Processing Statistics\nexport interface CVProcessingStats {\n activeFeatures: CVFeature[];\n processingTime: number; // average processing time in milliseconds\n effectiveFPS: number; // target CV FPS based on scene rate and CV rate mode\n actualFPS: number; // actual measured CV processing FPS\n isProcessing: boolean;\n}\n\nexport interface CVWorkerInitMessage {\n type: 'init';\n}\n\nexport interface CVWorkerConfigMessage {\n type: 'config';\n features: CVFeature[];\n}\n\nexport interface CVWorkerProcessMessage {\n type: 'process';\n bitmap: ImageBitmap;\n timestamp: number;\n features: CVFeature[];\n}\n\nexport interface CVWorkerResultPayload {\n faces?: FaceData[];\n hands?: HandData[];\n pose?: PoseData | null;\n segmentation?: SegmentationData | null;\n timestamp: number;\n}\n\nexport interface CVWorkerResultMessage {\n type: 'result';\n success: boolean;\n data?: CVWorkerResultPayload;\n error?: string;\n}\n\n// Input APIs - Phase 7 Implementation\nexport interface MouseAPI {\n // Position (canvas coordinates)\n x: number;\n y: number;\n \n // Canvas bounds\n isInCanvas: boolean;\n \n // Button states\n isPressed: boolean;\n leftButton: boolean;\n rightButton: boolean;\n middleButton: boolean;\n \n // Movement\n velocity: { x: number; y: number };\n deltaX: number;\n deltaY: number;\n \n // Scroll wheel\n wheelDelta: number;\n wheelX: number;\n wheelY: number;\n \n // Events (frame-based)\n wasPressed: boolean;\n wasReleased: boolean;\n wasMoved: boolean;\n}\n\nexport interface KeyboardAPI {\n // Key state queries\n isPressed(key: string): boolean;\n wasPressed(key: string): boolean;\n wasReleased(key: string): boolean;\n \n // Active state\n activeKeys: Set<string>;\n pressedThisFrame: Set<string>;\n releasedThisFrame: Set<string>;\n \n // Recent activity\n lastKeyPressed: string;\n lastKeyReleased: string;\n \n // Modifier keys\n shift: boolean;\n ctrl: boolean;\n alt: boolean;\n meta: boolean;\n}\n\nexport interface TouchPoint {\n id: number;\n x: number;\n y: number;\n pressure: number;\n radius: number;\n radiusX: number;\n radiusY: number;\n rotationAngle: number;\n force: number;\n \n // Movement\n deltaX: number;\n deltaY: number;\n velocity: { x: number; y: number };\n \n // Lifecycle\n isNew: boolean;\n isActive: boolean;\n isEnding: boolean;\n}\n\nexport interface TouchAPI {\n // Current touches\n points: TouchPoint[];\n count: number;\n \n // Touch events\n started: TouchPoint[];\n moved: TouchPoint[];\n ended: TouchPoint[];\n \n // Convenience accessors\n primary: TouchPoint | null;\n \n // Gesture detection\n gestures: TouchGestureAPI;\n}\n\nexport interface TouchGestureAPI {\n // Gesture states\n isPinching: boolean;\n isRotating: boolean;\n isPanning: boolean;\n isTapping: boolean;\n \n // Gesture values\n pinchScale: number;\n pinchDelta: number;\n rotationAngle: number;\n rotationDelta: number;\n panDelta: { x: number; y: number };\n \n // Tap detection\n tapCount: number;\n lastTapTime: number;\n tapPosition: { x: number; y: number } | null;\n}\n\n// Enhanced Parameter API for Phase 2\nexport interface ParameterAPI {\n // Define parameters (called once outside render loop)\n define(groups: ParameterGroup[]): void;\n \n // Proxy access to parameter values (fast render-time access)\n [key: string]: any;\n}\n\n// Error types\nexport class VijiCoreError extends Error {\n constructor(\n message: string,\n public code: string,\n public context?: any\n ) {\n super(message);\n this.name = 'VijiCoreError';\n }\n} ","import { Resolution, VijiCoreError } from '../types/index.js';\n\n/**\n * Manages the secure IFrame that contains the canvas for scene rendering.\n * Provides complete isolation while allowing controlled canvas access.\n * Enhanced with Phase 7 interaction support.\n */\nexport class IFrameManager {\n private iframe: HTMLIFrameElement | null = null;\n private canvas: HTMLCanvasElement | null = null;\n private offscreenCanvas: OffscreenCanvas | null = null;\n private isInitialized = false;\n private scale: number = 1.0;\n \n // Debug logging control\n private debugMode = false;\n\n /**\n * Enable or disable debug logging\n */\n setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n }\n\n /**\n * Debug logging helper\n */\n private debugLog(message: string, ...args: any[]): void {\n if (this.debugMode) {\n console.log(message, ...args);\n }\n }\n\n // Phase 7: Interaction event listeners\n private interactionListeners = new Map<string, (data: any) => void>();\n private isInteractionEnabled = true;\n\n // Mouse canvas tracking\n private isMouseInCanvas = false;\n\n // Touch tracking for gesture recognition\n private activeTouchIds = new Set<number>();\n\n constructor(\n private hostContainer: HTMLElement,\n ) {}\n\n /**\n * Creates a secure IFrame with proper sandbox attributes\n */\n async createSecureIFrame(): Promise<HTMLIFrameElement> {\n try {\n // Create IFrame with security sandbox\n const iframe = document.createElement('iframe');\n \n // Security: Sandbox with controlled permissions\n // Note: allow-same-origin is required for canvas access but limits sandboxing\n // In future phases, consider message-passing for better security\n iframe.sandbox.add('allow-scripts');\n iframe.sandbox.add('allow-same-origin'); // Required for canvas/WebGL access\n \n // Styling: Full container size\n iframe.style.width = '100%';\n iframe.style.height = '100%';\n iframe.style.border = 'none';\n iframe.style.display = 'block';\n \n // Generate secure IFrame content\n const iframeContent = this.generateIFrameHTML();\n const blob = new Blob([iframeContent], { type: 'text/html' });\n iframe.src = URL.createObjectURL(blob);\n \n // Mount to container\n this.hostContainer.appendChild(iframe);\n \n // Wait for IFrame to load and document to be ready\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new VijiCoreError('IFrame load timeout', 'IFRAME_TIMEOUT'));\n }, 5000);\n \n const checkReady = () => {\n if (iframe.contentDocument && iframe.contentDocument.readyState === 'complete') {\n clearTimeout(timeout);\n resolve();\n }\n };\n \n iframe.onload = () => {\n // Double-check document is ready\n if (iframe.contentDocument?.readyState === 'complete') {\n clearTimeout(timeout);\n resolve();\n } else {\n // Wait a bit more for document to be ready\n iframe.contentDocument?.addEventListener('DOMContentLoaded', checkReady);\n // Fallback check\n setTimeout(checkReady, 100);\n }\n };\n \n iframe.onerror = () => {\n clearTimeout(timeout);\n reject(new VijiCoreError('IFrame load failed', 'IFRAME_LOAD_ERROR'));\n };\n });\n \n this.iframe = iframe;\n return iframe;\n } catch (error) {\n throw new VijiCoreError(\n `Failed to create secure IFrame: ${error}`,\n 'IFRAME_CREATION_ERROR',\n { error }\n );\n }\n }\n\n /**\n * Creates canvas inside the IFrame and returns OffscreenCanvas for WebWorker\n */\n async createCanvas(): Promise<OffscreenCanvas> {\n if (!this.iframe?.contentWindow) {\n throw new VijiCoreError('IFrame not ready for canvas creation', 'IFRAME_NOT_READY');\n }\n\n try {\n // Wait for iframe document to be accessible with retry logic\n const iframeDoc = await this.waitForIFrameDocument();\n \n // Create canvas in IFrame\n const canvas = iframeDoc.createElement('canvas');\n canvas.id = 'viji-canvas';\n this.canvas = canvas;\n \n // Set canvas size based on resolution\n const { width, height } = this.calculateCanvasSize();\n canvas.width = width * this.scale;\n canvas.height = height * this.scale;\n \n // Styling: Full container size\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n canvas.style.display = 'block';\n \n // Add to IFrame body\n const body = iframeDoc.querySelector('body');\n if (!body) {\n throw new VijiCoreError('IFrame body not found', 'IFRAME_BODY_ERROR');\n }\n \n body.appendChild(canvas);\n \n // Phase 7: Set up interaction event listeners\n this.setupInteractionListeners(canvas, iframeDoc);\n \n // Create OffscreenCanvas for WebWorker\n const offscreenCanvas = canvas.transferControlToOffscreen();\n this.offscreenCanvas = offscreenCanvas;\n this.isInitialized = true;\n \n return offscreenCanvas;\n } catch (error) {\n throw new VijiCoreError(\n `Failed to create canvas: ${error}`,\n 'CANVAS_CREATION_ERROR',\n { error }\n );\n }\n }\n\n /**\n * Waits for iframe document to be accessible with retry logic\n */\n private async waitForIFrameDocument(): Promise<Document> {\n const maxRetries = 15;\n const retryDelay = 150;\n \n for (let i = 0; i < maxRetries; i++) {\n try {\n const iframeDoc = this.iframe?.contentDocument;\n \n // Check multiple readiness indicators\n if (iframeDoc && \n (iframeDoc.readyState === 'complete' || iframeDoc.readyState === 'interactive') &&\n iframeDoc.body &&\n this.iframe?.contentWindow) {\n \n this.debugLog(`IFrame document ready after ${i + 1} attempts`);\n return iframeDoc;\n }\n \n this.debugLog(`IFrame not ready attempt ${i + 1}/${maxRetries}:`, {\n hasDocument: !!iframeDoc,\n readyState: iframeDoc?.readyState,\n hasBody: !!iframeDoc?.body,\n hasWindow: !!this.iframe?.contentWindow\n });\n \n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n } catch (error) {\n this.debugLog(`IFrame access error attempt ${i + 1}/${maxRetries}:`, error);\n // Security or access error - wait and retry\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n }\n }\n \n throw new VijiCoreError('Cannot access IFrame document after retries', 'IFRAME_ACCESS_ERROR');\n }\n\n /**\n * Updates canvas resolution setting (scaling handled in worker)\n */\n updateScale(scale: number): { width: number; height: number } {\n this.scale = scale;\n return this.getEffectiveResolution();\n }\n\n /**\n * Gets current scale\n */\n getScale(): number {\n return this.scale;\n }\n\n /**\n * Destroys the IFrame and cleans up resources\n */\n destroy(): void {\n try {\n if (this.iframe) {\n // Revoke blob URL to prevent memory leaks\n if (this.iframe.src.startsWith('blob:')) {\n URL.revokeObjectURL(this.iframe.src);\n }\n \n // Remove from DOM\n this.iframe.remove();\n this.iframe = null;\n }\n \n this.offscreenCanvas = null;\n this.isInitialized = false;\n } catch (error) {\n console.warn('Error during IFrame cleanup:', error);\n }\n }\n\n /**\n * Checks if IFrame is ready for use\n */\n get ready(): boolean {\n return this.isInitialized && \n this.iframe !== null && \n this.offscreenCanvas !== null;\n }\n\n /**\n * Gets the IFrame element\n */\n get element(): HTMLIFrameElement | null {\n return this.iframe;\n }\n\n /**\n * Generates the HTML content for the secure IFrame\n */\n private generateIFrameHTML(): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Viji Scene Container</title>\n <style>\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n \n html, body {\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: #000;\n }\n \n canvas {\n display: block;\n width: 100%;\n height: 100%;\n image-rendering: auto;\n }\n </style>\n</head>\n<body>\n <!-- Canvas will be created dynamically -->\n</body>\n</html>\n `.trim();\n }\n\n /**\n * Calculates canvas dimensions based on container size\n * Canvas internal size starts as container size, then worker updates it based on resolution\n */\n private calculateCanvasSize(): { width: number; height: number } {\n // Use full container size for initial canvas resolution\n // Worker will update canvas.width/height based on effective resolution messages\n const containerRect = this.hostContainer.getBoundingClientRect();\n \n return {\n width: Math.round(containerRect.width),\n height: Math.round(containerRect.height)\n };\n }\n\n /**\n * Gets the effective resolution that should be used for rendering\n */\n getEffectiveResolution(): Resolution {\n const containerRect = this.hostContainer.getBoundingClientRect();\n const containerWidth = Math.round(containerRect.width);\n const containerHeight = Math.round(containerRect.height);\n\n const scale = Math.max(0.1, Math.min(1.0, this.scale));\n return {\n width: Math.round(containerWidth * scale),\n height: Math.round(containerHeight * scale),\n };\n }\n\n // Phase 7: Interaction Management Methods\n\n /**\n * Sets up interaction event listeners on the canvas and document\n */\n private setupInteractionListeners(canvas: HTMLCanvasElement, iframeDoc: Document): void {\n if (!this.isInteractionEnabled) return;\n\n // Make canvas focusable for keyboard events\n canvas.tabIndex = 0;\n canvas.style.outline = 'none';\n\n // Mouse events\n canvas.addEventListener('mousedown', this.handleMouseEvent.bind(this), { passive: false });\n canvas.addEventListener('mousemove', this.handleMouseEvent.bind(this), { passive: false });\n canvas.addEventListener('mouseup', this.handleMouseEvent.bind(this), { passive: false });\n canvas.addEventListener('mouseenter', this.handleMouseEnter.bind(this), { passive: false });\n canvas.addEventListener('mouseleave', this.handleMouseLeave.bind(this), { passive: false });\n canvas.addEventListener('wheel', this.handleWheelEvent.bind(this), { passive: false });\n canvas.addEventListener('contextmenu', (e) => e.preventDefault()); // Disable right-click menu\n\n // Keyboard events (on document to capture all keys)\n iframeDoc.addEventListener('keydown', this.handleKeyboardEvent.bind(this), { passive: false });\n iframeDoc.addEventListener('keyup', this.handleKeyboardEvent.bind(this), { passive: false });\n\n // Touch events\n canvas.addEventListener('touchstart', this.handleTouchEvent.bind(this), { passive: false });\n canvas.addEventListener('touchmove', this.handleTouchEvent.bind(this), { passive: false });\n canvas.addEventListener('touchend', this.handleTouchEvent.bind(this), { passive: false });\n canvas.addEventListener('touchcancel', this.handleTouchEvent.bind(this), { passive: false });\n\n // Focus management\n canvas.addEventListener('mousedown', () => canvas.focus());\n canvas.addEventListener('touchstart', () => canvas.focus());\n }\n\n /**\n * Handles mouse events and transforms coordinates\n */\n private handleMouseEvent(event: MouseEvent): void {\n if (!this.canvas || !this.isInteractionEnabled) return;\n\n event.preventDefault();\n\n const rect = this.canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (this.canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (this.canvas.height / rect.height);\n\n // Calculate movement deltas\n const deltaX = event.movementX || 0;\n const deltaY = event.movementY || 0;\n\n const data = {\n x,\n y,\n buttons: event.buttons,\n deltaX,\n deltaY,\n wheelDeltaX: 0,\n wheelDeltaY: 0,\n isInCanvas: this.isMouseInCanvas,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('mouse-update', data);\n }\n\n /**\n * Handles mouse enter events\n */\n private handleMouseEnter(event: MouseEvent): void {\n if (!this.isInteractionEnabled) return;\n \n this.isMouseInCanvas = true;\n \n // Trigger a mouse update to immediately reflect the isInCanvas state\n this.handleMouseEvent(event);\n }\n\n /**\n * Handles mouse leave events\n */\n private handleMouseLeave(event: MouseEvent): void {\n if (!this.isInteractionEnabled) return;\n \n this.isMouseInCanvas = false;\n \n // Trigger a mouse update to immediately reflect the isInCanvas state\n this.handleMouseEvent(event);\n }\n\n /**\n * Handles wheel events\n */\n private handleWheelEvent(event: WheelEvent): void {\n if (!this.canvas || !this.isInteractionEnabled) return;\n\n event.preventDefault();\n\n const rect = this.canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (this.canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (this.canvas.height / rect.height);\n\n const data = {\n x,\n y,\n buttons: event.buttons,\n deltaX: 0,\n deltaY: 0,\n wheelDeltaX: event.deltaX,\n wheelDeltaY: event.deltaY,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('mouse-update', data);\n }\n\n /**\n * Handles keyboard events\n */\n private handleKeyboardEvent(event: KeyboardEvent): void {\n if (!this.isInteractionEnabled) return;\n\n // Allow some default behaviors for accessibility/usability\n const allowedKeys = ['Tab', 'F1', 'F2', 'F3', 'F4', 'F5', 'F11', 'F12'];\n if (!allowedKeys.includes(event.key)) {\n event.preventDefault();\n }\n\n const data = {\n type: event.type as 'keydown' | 'keyup',\n key: event.key,\n code: event.code,\n shiftKey: event.shiftKey,\n ctrlKey: event.ctrlKey,\n altKey: event.altKey,\n metaKey: event.metaKey,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('keyboard-update', data);\n }\n\n /**\n * Handles touch events and tracks multi-touch\n */\n private handleTouchEvent(event: TouchEvent): void {\n if (!this.canvas || !this.isInteractionEnabled) return;\n\n event.preventDefault();\n\n const rect = this.canvas.getBoundingClientRect();\n const scaleX = this.canvas.width / rect.width;\n const scaleY = this.canvas.height / rect.height;\n\n // Convert TouchList to array with transformed coordinates\n const touches = Array.from(event.touches).map(touch => ({\n identifier: touch.identifier,\n clientX: (touch.clientX - rect.left) * scaleX,\n clientY: (touch.clientY - rect.top) * scaleY,\n pressure: (touch as any).pressure || 0,\n radiusX: (touch as any).radiusX || 10,\n radiusY: (touch as any).radiusY || 10,\n rotationAngle: (touch as any).rotationAngle || 0,\n force: (touch as any).force || (touch as any).pressure || 0\n }));\n\n // Track active touch IDs for gesture recognition\n if (event.type === 'touchstart') {\n for (const touch of event.changedTouches) {\n this.activeTouchIds.add(touch.identifier);\n }\n } else if (event.type === 'touchend' || event.type === 'touchcancel') {\n for (const touch of event.changedTouches) {\n this.activeTouchIds.delete(touch.identifier);\n }\n }\n\n const data = {\n type: event.type as 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel',\n touches,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('touch-update', data);\n }\n\n /**\n * Emits an interaction event to registered listeners\n */\n private emitInteractionEvent(eventType: string, data: any): void {\n const listener = this.interactionListeners.get(eventType);\n if (listener) {\n listener(data);\n }\n }\n\n /**\n * Registers an interaction event listener\n */\n onInteractionEvent(eventType: string, listener: (data: any) => void): void {\n this.interactionListeners.set(eventType, listener);\n }\n\n /**\n * Removes an interaction event listener\n */\n offInteractionEvent(eventType: string): void {\n this.interactionListeners.delete(eventType);\n }\n\n /**\n * Enables or disables interaction event capture\n */\n setInteractionEnabled(enabled: boolean): void {\n this.isInteractionEnabled = enabled;\n }\n\n /**\n * Gets the canvas element (for coordinate calculations)\n */\n getCanvas(): HTMLCanvasElement | null {\n return this.canvas;\n }\n} ","import { VijiCoreError, HostToWorkerMessage, WorkerToHostMessage } from '../types/index.js';\nimport VijiWorker from './viji.worker.ts?worker&module';\n\n/**\n * Manages the WebWorker that executes artist scene code.\n * Provides secure sandboxed execution with controlled API access.\n */\nexport class WorkerManager {\n private worker: Worker | null = null;\n private messageId = 0;\n private pendingMessages = new Map<string, {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n timeout: ReturnType<typeof setTimeout>;\n }>();\n private messageHandlers = new Map<string, (data: any) => void>();\n private isInitialized = false;\n\n constructor(\n private sceneCode: string,\n private offscreenCanvas: OffscreenCanvas\n ) {}\n\n /**\n * Creates and initializes the WebWorker with artist code\n */\n async createWorker(): Promise<void> {\n try {\n // Create worker using Vite's worker import (hashed asset, correct MIME)\n this.worker = new VijiWorker();\n \n // Setup message handling\n this.setupMessageHandling();\n \n // Transfer OffscreenCanvas to worker and wait for init response\n // IMPORTANT: Canvas must be initialized BEFORE scene code to avoid race conditions\n await this.initializeWorker();\n \n // Send scene code to worker (after canvas is ready)\n this.postMessage('set-scene-code', { sceneCode: this.sceneCode });\n \n this.isInitialized = true;\n } catch (error) {\n throw new VijiCoreError(\n `Failed to create worker: ${error}`,\n 'WORKER_CREATION_ERROR',\n { error }\n );\n }\n }\n\n /**\n * Sends a message to the worker and returns a promise for the response\n */\n async sendMessage(type: string, data?: any, timeout = 5000): Promise<any> {\n if (!this.worker) {\n throw new VijiCoreError('Worker not initialized', 'WORKER_NOT_READY');\n }\n\n const id = `msg_${++this.messageId}`;\n const message: HostToWorkerMessage = {\n type: type as any,\n id,\n timestamp: Date.now(),\n data\n };\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingMessages.delete(id);\n reject(new VijiCoreError(`Message timeout: ${type}`, 'MESSAGE_TIMEOUT'));\n }, timeout);\n\n this.pendingMessages.set(id, {\n resolve,\n reject,\n timeout: timeoutId\n });\n\n this.worker!.postMessage(message);\n });\n }\n\n /**\n * Sends a message without waiting for response (fire and forget)\n */\n postMessage(type: string, data?: any): void;\n postMessage(type: string, data: any, transfer: Transferable[]): void;\n postMessage(type: string, data?: any, transfer?: Transferable[]): void {\n if (!this.worker) {\n console.warn('Attempted to post message to uninitialized worker');\n return;\n }\n\n const message: HostToWorkerMessage = {\n type: type as any,\n id: `fire_${++this.messageId}`,\n timestamp: Date.now(),\n data\n };\n\n if (transfer && transfer.length > 0) {\n this.worker.postMessage(message, transfer);\n } else {\n this.worker.postMessage(message);\n }\n }\n\n\n /**\n * Registers a handler for worker messages\n */\n onMessage(type: string, handler: (data: any) => void): void {\n this.messageHandlers.set(type, handler);\n }\n\n /**\n * Removes a message handler\n */\n offMessage(type: string): void {\n this.messageHandlers.delete(type);\n }\n\n /**\n * Terminates the worker and cleans up resources\n */\n destroy(): void {\n try {\n // Clear pending messages\n this.pendingMessages.forEach(({ timeout, reject }) => {\n clearTimeout(timeout);\n reject(new VijiCoreError('Worker destroyed', 'WORKER_DESTROYED'));\n });\n this.pendingMessages.clear();\n\n // Clear message handlers\n this.messageHandlers.clear();\n\n // Terminate worker\n if (this.worker) {\n this.worker.terminate();\n this.worker = null;\n }\n\n this.isInitialized = false;\n } catch (error) {\n console.warn('Error during worker cleanup:', error);\n }\n }\n\n /**\n * Checks if worker is ready for use\n */\n get ready(): boolean {\n return this.isInitialized && this.worker !== null;\n }\n\n /**\n * Gets the worker instance\n */\n get instance(): Worker | null {\n return this.worker;\n }\n\n /**\n * Sets up message handling for worker communication\n */\n private setupMessageHandling(): void {\n if (!this.worker) return;\n\n this.worker.onmessage = (event) => {\n const message: WorkerToHostMessage = event.data;\n \n // Handle pending message responses\n if (this.pendingMessages.has(message.id)) {\n const pending = this.pendingMessages.get(message.id)!;\n clearTimeout(pending.timeout);\n this.pendingMessages.delete(message.id);\n \n if (message.type === 'error') {\n pending.reject(new VijiCoreError(\n message.data?.message || 'Worker error',\n message.data?.code || 'WORKER_ERROR',\n message.data\n ));\n } else {\n pending.resolve(message.data);\n }\n return;\n }\n\n // Handle event messages\n const handler = this.messageHandlers.get(message.type);\n if (handler) {\n try {\n handler(message.data);\n } catch (error) {\n console.error(`Error in message handler for ${message.type}:`, error);\n }\n }\n };\n\n this.worker.onerror = (error) => {\n console.error('Worker error:', error);\n \n // Reject all pending messages\n this.pendingMessages.forEach(({ timeout, reject }) => {\n clearTimeout(timeout);\n reject(new VijiCoreError('Worker error', 'WORKER_ERROR', error));\n });\n this.pendingMessages.clear();\n };\n }\n\n /**\n * Initializes the worker with canvas and basic setup\n * Waits for init-response message (worker will also send separate 'ready' event)\n */\n private async initializeWorker(): Promise<void> {\n if (!this.worker) {\n throw new VijiCoreError('Worker not created', 'WORKER_NOT_CREATED');\n }\n\n // Create message for canvas transfer\n const id = `msg_${++this.messageId}`;\n const message: HostToWorkerMessage = {\n type: 'init',\n id,\n timestamp: Date.now(),\n data: {\n canvas: this.offscreenCanvas\n }\n };\n\n // Transfer OffscreenCanvas (not clone) - this is critical!\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingMessages.delete(id);\n reject(new VijiCoreError('Canvas transfer timeout', 'CANVAS_TRANSFER_TIMEOUT'));\n }, 10000);\n\n this.pendingMessages.set(id, {\n resolve,\n reject,\n timeout: timeoutId\n });\n\n // Transfer the canvas using the transferable objects parameter\n this.worker!.postMessage(message, [this.offscreenCanvas]);\n });\n }\n\n\n} ","import { MouseAPI, KeyboardAPI, TouchAPI, TouchPoint } from '../types/index.js';\n\n/**\n * Manages user interaction state and provides APIs for mouse, keyboard, and touch input.\n * Handles event processing, state tracking, and gesture recognition for Phase 7.\n */\nexport class InteractionManager {\n // Mouse state\n private mouseState: MouseAPI = {\n x: 0,\n y: 0,\n isInCanvas: false,\n isPressed: false,\n leftButton: false,\n rightButton: false,\n middleButton: false,\n velocity: { x: 0, y: 0 },\n deltaX: 0,\n deltaY: 0,\n wheelDelta: 0,\n wheelX: 0,\n wheelY: 0,\n wasPressed: false,\n wasReleased: false,\n wasMoved: false\n };\n\n // Mouse velocity tracking\n private mouseVelocityHistory: Array<{ x: number; y: number; time: number }> = [];\n\n // Keyboard state\n private keyboardState: KeyboardAPI = {\n isPressed: (key: string) => this.activeKeys.has(key.toLowerCase()),\n wasPressed: (key: string) => this.pressedThisFrame.has(key.toLowerCase()),\n wasReleased: (key: string) => this.releasedThisFrame.has(key.toLowerCase()),\n activeKeys: new Set<string>(),\n pressedThisFrame: new Set<string>(),\n releasedThisFrame: new Set<string>(),\n lastKeyPressed: '',\n lastKeyReleased: '',\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n };\n\n private activeKeys = new Set<string>();\n private pressedThisFrame = new Set<string>();\n private releasedThisFrame = new Set<string>();\n\n // Touch state\n private touchState: TouchAPI = {\n points: [],\n count: 0,\n started: [],\n moved: [],\n ended: [],\n primary: null,\n gestures: {\n isPinching: false,\n isRotating: false,\n isPanning: false,\n isTapping: false,\n pinchScale: 1,\n pinchDelta: 0,\n rotationAngle: 0,\n rotationDelta: 0,\n panDelta: { x: 0, y: 0 },\n tapCount: 0,\n lastTapTime: 0,\n tapPosition: null\n }\n };\n\n private activeTouches = new Map<number, TouchPoint>();\n private gestureState = {\n initialDistance: 0,\n initialAngle: 0,\n lastPinchScale: 1,\n lastRotationAngle: 0,\n panStartPosition: { x: 0, y: 0 },\n tapStartTime: 0,\n tapCount: 0,\n lastTapTime: 0\n };\n\n constructor() {}\n\n /**\n * Processes mouse update from the host\n */\n updateMouse(data: {\n x: number;\n y: number;\n buttons: number;\n deltaX: number;\n deltaY: number;\n wheelDeltaX: number;\n wheelDeltaY: number;\n isInCanvas?: boolean;\n timestamp: number;\n }): void {\n // Convert coordinates to canvas space\n const canvasX = data.x;\n const canvasY = data.y;\n\n // Calculate deltas\n const deltaX = canvasX - this.mouseState.x;\n const deltaY = canvasY - this.mouseState.y;\n\n // Update velocity with smoothing\n this.updateMouseVelocity(deltaX, deltaY, data.timestamp);\n\n // Detect button state changes\n const prevPressed = this.mouseState.isPressed;\n const currentPressed = data.buttons > 0;\n\n this.mouseState.wasPressed = !prevPressed && currentPressed;\n this.mouseState.wasReleased = prevPressed && !currentPressed;\n this.mouseState.wasMoved = deltaX !== 0 || deltaY !== 0;\n\n // Update mouse state\n this.mouseState.x = canvasX;\n this.mouseState.y = canvasY;\n this.mouseState.deltaX = deltaX;\n this.mouseState.deltaY = deltaY;\n this.mouseState.isPressed = currentPressed;\n this.mouseState.leftButton = (data.buttons & 1) !== 0;\n this.mouseState.rightButton = (data.buttons & 2) !== 0;\n this.mouseState.middleButton = (data.buttons & 4) !== 0;\n this.mouseState.isInCanvas = data.isInCanvas !== undefined ? data.isInCanvas : true;\n\n // Update wheel\n this.mouseState.wheelDelta = data.wheelDeltaY;\n this.mouseState.wheelX = data.wheelDeltaX;\n this.mouseState.wheelY = data.wheelDeltaY;\n }\n\n /**\n * Updates mouse velocity with smoothing\n */\n private updateMouseVelocity(deltaX: number, deltaY: number, timestamp: number): void {\n // Add current velocity sample\n this.mouseVelocityHistory.push({ x: deltaX, y: deltaY, time: timestamp });\n\n // Keep only recent samples (last 100ms)\n const cutoff = timestamp - 100;\n this.mouseVelocityHistory = this.mouseVelocityHistory.filter(sample => sample.time > cutoff);\n\n // Calculate smoothed velocity\n if (this.mouseVelocityHistory.length > 1) {\n const recent = this.mouseVelocityHistory.slice(-5); // Last 5 samples\n const avgX = recent.reduce((sum, s) => sum + s.x, 0) / recent.length;\n const avgY = recent.reduce((sum, s) => sum + s.y, 0) / recent.length;\n \n this.mouseState.velocity.x = avgX;\n this.mouseState.velocity.y = avgY;\n } else {\n this.mouseState.velocity.x = deltaX;\n this.mouseState.velocity.y = deltaY;\n }\n }\n\n /**\n * Processes keyboard update from the host\n */\n updateKeyboard(data: {\n type: 'keydown' | 'keyup';\n key: string;\n code: string;\n shiftKey: boolean;\n ctrlKey: boolean;\n altKey: boolean;\n metaKey: boolean;\n timestamp: number;\n }): void {\n const key = data.key.toLowerCase();\n\n if (data.type === 'keydown') {\n if (!this.activeKeys.has(key)) {\n this.activeKeys.add(key);\n this.pressedThisFrame.add(key);\n this.keyboardState.lastKeyPressed = data.key;\n }\n } else if (data.type === 'keyup') {\n this.activeKeys.delete(key);\n this.releasedThisFrame.add(key);\n this.keyboardState.lastKeyReleased = data.key;\n }\n\n // Update modifier keys\n this.keyboardState.shift = data.shiftKey;\n this.keyboardState.ctrl = data.ctrlKey;\n this.keyboardState.alt = data.altKey;\n this.keyboardState.meta = data.metaKey;\n }\n\n /**\n * Processes touch update from the host\n */\n updateTouch(data: {\n type: 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel';\n touches: Array<{\n identifier: number;\n clientX: number;\n clientY: number;\n pressure: number;\n radiusX: number;\n radiusY: number;\n rotationAngle: number;\n force: number;\n }>;\n timestamp: number;\n }): void {\n // Clear frame-based touch events\n this.touchState.started = [];\n this.touchState.moved = [];\n this.touchState.ended = [];\n\n // Process touches based on event type\n if (data.type === 'touchstart') {\n this.processTouchStart(data.touches, data.timestamp);\n } else if (data.type === 'touchmove') {\n this.processTouchMove(data.touches, data.timestamp);\n } else if (data.type === 'touchend' || data.type === 'touchcancel') {\n this.processTouchEnd(data.touches, data.timestamp);\n }\n\n // Update touch array and count\n this.touchState.points = Array.from(this.activeTouches.values());\n this.touchState.count = this.touchState.points.length;\n this.touchState.primary = this.touchState.points[0] || null;\n\n // Update gestures\n this.updateGestures();\n }\n\n /**\n * Processes touch start events\n */\n private processTouchStart(touches: any[], timestamp: number): void {\n for (const touch of touches) {\n const touchPoint = this.createTouchPoint(touch, timestamp, true);\n this.activeTouches.set(touch.identifier, touchPoint);\n this.touchState.started.push(touchPoint);\n }\n\n // Handle tap gesture start\n if (this.touchState.count === 1) {\n this.gestureState.tapStartTime = timestamp;\n const touch = this.touchState.points[0];\n this.touchState.gestures.tapPosition = { x: touch.x, y: touch.y };\n }\n }\n\n /**\n * Processes touch move events\n */\n private processTouchMove(touches: any[], timestamp: number): void {\n for (const touch of touches) {\n const existing = this.activeTouches.get(touch.identifier);\n if (existing) {\n const updated = this.createTouchPoint(touch, timestamp, false, existing);\n this.activeTouches.set(touch.identifier, updated);\n this.touchState.moved.push(updated);\n }\n }\n }\n\n /**\n * Processes touch end events\n */\n private processTouchEnd(touches: any[], timestamp: number): void {\n for (const touch of touches) {\n const existing = this.activeTouches.get(touch.identifier);\n if (existing) {\n const ended = { ...existing, isEnding: true, isActive: false };\n this.touchState.ended.push(ended);\n this.activeTouches.delete(touch.identifier);\n }\n }\n\n // Handle tap gesture completion\n if (this.touchState.count === 0 && this.gestureState.tapStartTime > 0) {\n const tapDuration = timestamp - this.gestureState.tapStartTime;\n if (tapDuration < 300) { // Quick tap\n this.handleTap(timestamp);\n }\n this.gestureState.tapStartTime = 0;\n }\n }\n\n /**\n * Creates a touch point from raw touch data\n */\n private createTouchPoint(\n touch: any, \n timestamp: number, \n isNew: boolean, \n previous?: TouchPoint\n ): TouchPoint {\n const x = touch.clientX;\n const y = touch.clientY;\n \n const deltaX = previous ? x - previous.x : 0;\n const deltaY = previous ? y - previous.y : 0;\n \n // Calculate velocity\n const timeDelta = previous ? timestamp - (previous as any).timestamp : 16;\n const velocityX = timeDelta > 0 ? deltaX / timeDelta * 1000 : 0;\n const velocityY = timeDelta > 0 ? deltaY / timeDelta * 1000 : 0;\n\n return {\n id: touch.identifier,\n x,\n y,\n pressure: touch.pressure || 0,\n radius: Math.max(touch.radiusX || 0, touch.radiusY || 0),\n radiusX: touch.radiusX || 0,\n radiusY: touch.radiusY || 0,\n rotationAngle: touch.rotationAngle || 0,\n force: touch.force || touch.pressure || 0,\n deltaX,\n deltaY,\n velocity: { x: velocityX, y: velocityY },\n isNew,\n isActive: true,\n isEnding: false\n };\n }\n\n /**\n * Updates gesture recognition\n */\n private updateGestures(): void {\n const touches = this.touchState.points;\n const gestures = this.touchState.gestures;\n\n if (touches.length === 2) {\n // Two-finger gestures: pinch and rotate\n const touch1 = touches[0];\n const touch2 = touches[1];\n \n const distance = Math.sqrt(\n Math.pow(touch2.x - touch1.x, 2) + Math.pow(touch2.y - touch1.y, 2)\n );\n \n const angle = Math.atan2(touch2.y - touch1.y, touch2.x - touch1.x);\n\n if (this.gestureState.initialDistance === 0) {\n this.gestureState.initialDistance = distance;\n this.gestureState.initialAngle = angle;\n this.gestureState.lastPinchScale = 1;\n this.gestureState.lastRotationAngle = 0;\n }\n\n // Pinch gesture\n const scale = distance / this.gestureState.initialDistance;\n const scaleDelta = scale - this.gestureState.lastPinchScale;\n \n gestures.isPinching = Math.abs(scaleDelta) > 0.01;\n gestures.pinchScale = scale;\n gestures.pinchDelta = scaleDelta;\n this.gestureState.lastPinchScale = scale;\n\n // Rotation gesture\n const rotationAngle = angle - this.gestureState.initialAngle;\n const rotationDelta = rotationAngle - this.gestureState.lastRotationAngle;\n \n gestures.isRotating = Math.abs(rotationDelta) > 0.02;\n gestures.rotationAngle = rotationAngle;\n gestures.rotationDelta = rotationDelta;\n this.gestureState.lastRotationAngle = rotationAngle;\n\n } else {\n // Reset two-finger gesture state\n this.gestureState.initialDistance = 0;\n gestures.isPinching = false;\n gestures.isRotating = false;\n gestures.pinchDelta = 0;\n gestures.rotationDelta = 0;\n }\n\n // Pan gesture (one or more fingers)\n if (touches.length > 0) {\n const primaryTouch = touches[0];\n if (this.gestureState.panStartPosition.x === 0) {\n this.gestureState.panStartPosition = { x: primaryTouch.x, y: primaryTouch.y };\n }\n \n const panDeltaX = primaryTouch.x - this.gestureState.panStartPosition.x;\n const panDeltaY = primaryTouch.y - this.gestureState.panStartPosition.y;\n const panDistance = Math.sqrt(panDeltaX * panDeltaX + panDeltaY * panDeltaY);\n \n gestures.isPanning = panDistance > 10;\n gestures.panDelta = { x: panDeltaX, y: panDeltaY };\n } else {\n // Reset pan gesture\n this.gestureState.panStartPosition = { x: 0, y: 0 };\n gestures.isPanning = false;\n gestures.panDelta = { x: 0, y: 0 };\n }\n }\n\n /**\n * Handles tap gesture detection\n */\n private handleTap(timestamp: number): void {\n const timeSinceLastTap = timestamp - this.gestureState.lastTapTime;\n \n if (timeSinceLastTap < 300) {\n // Multi-tap\n this.gestureState.tapCount++;\n } else {\n // New tap sequence\n this.gestureState.tapCount = 1;\n }\n \n this.touchState.gestures.tapCount = this.gestureState.tapCount;\n this.touchState.gestures.lastTapTime = timestamp;\n this.touchState.gestures.isTapping = true;\n this.gestureState.lastTapTime = timestamp;\n }\n\n /**\n * Called at the start of each frame to reset frame-based events\n */\n frameStart(): void {\n // Reset mouse frame events\n this.mouseState.wasPressed = false;\n this.mouseState.wasReleased = false;\n this.mouseState.wasMoved = false;\n this.mouseState.wheelDelta = 0;\n this.mouseState.wheelX = 0;\n this.mouseState.wheelY = 0;\n\n // Reset keyboard frame events\n this.pressedThisFrame.clear();\n this.releasedThisFrame.clear();\n\n // Reset touch gesture frame events\n this.touchState.gestures.isTapping = false;\n this.touchState.gestures.pinchDelta = 0;\n this.touchState.gestures.rotationDelta = 0;\n }\n\n /**\n * Get current mouse state (read-only)\n */\n getMouseState(): Readonly<MouseAPI> {\n return this.mouseState;\n }\n\n /**\n * Get current keyboard state (read-only)\n */\n getKeyboardState(): Readonly<KeyboardAPI> {\n return this.keyboardState;\n }\n\n /**\n * Get current touch state (read-only)\n */\n getTouchState(): Readonly<TouchAPI> {\n return this.touchState;\n }\n\n /**\n * Cleanup resources\n */\n destroy(): void {\n this.mouseVelocityHistory.length = 0;\n this.activeTouches.clear();\n this.activeKeys.clear();\n this.pressedThisFrame.clear();\n this.releasedThisFrame.clear();\n }\n} ","import { AnalysisConfiguration } from '../types/index.js';\n\n/**\n * Manages audio analysis and processing for the host side.\n * Handles audio stream processing and provides real-time audio analysis for Phase 5.\n * \n * This system provides:\n * - Real-time audio analysis (RMS, peak, frequency bands)\n * - AudioContext management and cleanup\n * - Raw FFT data access for custom analysis\n * - Analysis results sent to worker for artist API\n * - Message handling for audio stream updates\n */\nexport class AudioSystem {\n // Audio context and analysis nodes\n private audioContext: AudioContext | null = null;\n private analyser: AnalyserNode | null = null;\n private mediaStreamSource: MediaStreamAudioSourceNode | null = null;\n private currentStream: MediaStream | null = null;\n \n // Debug logging control\n private debugMode = false;\n\n /**\n * Enable or disable debug logging\n */\n setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n }\n\n /**\n * Debug logging helper\n */\n private debugLog(message: string, ...args: any[]): void {\n if (this.debugMode) {\n console.log(message, ...args);\n }\n }\n \n // Analysis configuration (good balance, leaning towards quality)\n private fftSize = 2048; // Good balance for quality vs performance\n private smoothingTimeConstant = 0.8; // Smooth but responsive\n \n // Analysis data arrays\n private frequencyData: Uint8Array<ArrayBuffer> | null = null;\n private timeDomainData: Uint8Array<ArrayBuffer> | null = null;\n \n // Audio analysis state (host-side state)\n private audioState = {\n isConnected: false,\n volume: {\n rms: 0,\n peak: 0\n },\n bands: {\n bass: 0,\n mid: 0,\n treble: 0,\n subBass: 0,\n lowMid: 0,\n highMid: 0,\n presence: 0,\n brilliance: 0\n }\n };\n \n // Analysis loop\n private analysisLoopId: number | null = null;\n private isAnalysisRunning = false;\n \n // Callback to send results to worker\n private sendAnalysisResults: ((data: any) => void) | null = null;\n\n constructor(sendAnalysisResultsCallback?: (data: any) => void) {\n // Bind methods for proper context\n this.handleAudioStreamUpdate = this.handleAudioStreamUpdate.bind(this);\n this.performAnalysis = this.performAnalysis.bind(this);\n this.sendAnalysisResults = sendAnalysisResultsCallback || null;\n }\n\n /**\n * Get the current audio analysis state (for host-side usage)\n */\n public getAudioState() {\n return { ...this.audioState };\n }\n\n /**\n * Handle audio stream update (called from VijiCore)\n */\n public handleAudioStreamUpdate(data: {\n audioStream?: MediaStream | null;\n analysisConfig?: AnalysisConfiguration;\n timestamp: number;\n }): void {\n try {\n if (data.audioStream) {\n this.setAudioStream(data.audioStream);\n } else {\n // Stream removed or null\n this.disconnectAudioStream();\n }\n \n // Update analysis configuration if provided\n if (data.analysisConfig) {\n this.updateAnalysisConfig(data.analysisConfig);\n }\n } catch (error) {\n console.error('Error handling audio stream update:', error);\n this.audioState.isConnected = false;\n this.sendAnalysisResultsToWorker();\n }\n }\n\n /**\n * Set the audio stream for analysis\n */\n private async setAudioStream(audioStream: MediaStream): Promise<void> {\n // Clean up existing connections\n this.disconnectAudioStream();\n \n // Validate stream has audio tracks\n const audioTracks = audioStream.getAudioTracks();\n if (audioTracks.length === 0) {\n console.warn('No audio tracks in provided stream');\n this.audioState.isConnected = false;\n this.sendAnalysisResultsToWorker();\n return;\n }\n \n try {\n // Create AudioContext if needed\n if (!this.audioContext) {\n this.audioContext = new AudioContext();\n \n // Resume context if suspended (required by browser policies)\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume();\n }\n }\n \n // Create analyser node with our configuration\n this.analyser = this.audioContext.createAnalyser();\n this.analyser.fftSize = this.fftSize;\n this.analyser.smoothingTimeConstant = this.smoothingTimeConstant;\n \n // Create media stream source\n this.mediaStreamSource = this.audioContext.createMediaStreamSource(audioStream);\n \n // Connect stream to analyser (no need to connect to destination for analysis)\n this.mediaStreamSource.connect(this.analyser);\n \n // Initialize data arrays\n const bufferLength = this.analyser.frequencyBinCount;\n this.frequencyData = new Uint8Array(bufferLength);\n this.timeDomainData = new Uint8Array(bufferLength);\n \n // Store stream reference\n this.currentStream = audioStream;\n this.audioState.isConnected = true;\n \n // Start analysis loop\n this.startAnalysisLoop();\n \n this.debugLog('Audio stream connected successfully (host-side)', {\n sampleRate: this.audioContext.sampleRate,\n fftSize: this.fftSize,\n bufferLength\n });\n \n } catch (error) {\n console.error('Failed to set up audio analysis:', error);\n this.audioState.isConnected = false;\n this.disconnectAudioStream();\n }\n \n // Send initial state to worker\n this.sendAnalysisResultsToWorker();\n }\n\n /**\n * Disconnect current audio stream and clean up resources\n */\n private disconnectAudioStream(): void {\n // Stop analysis loop\n this.stopAnalysisLoop();\n \n // Disconnect and clean up audio nodes\n if (this.mediaStreamSource) {\n this.mediaStreamSource.disconnect();\n this.mediaStreamSource = null;\n }\n \n if (this.analyser) {\n this.analyser.disconnect();\n this.analyser = null;\n }\n \n // Reset data arrays\n this.frequencyData = null;\n this.timeDomainData = null;\n \n // Clear stream reference\n this.currentStream = null;\n \n // Update state\n this.audioState.isConnected = false;\n this.resetAudioValues();\n \n // Send updated state to worker\n this.sendAnalysisResultsToWorker();\n \n this.debugLog('Audio stream disconnected (host-side)');\n }\n\n /**\n * Update analysis configuration\n */\n private updateAnalysisConfig(config: AnalysisConfiguration): void {\n let needsReconnect = false;\n \n if (config.fftSize && config.fftSize !== this.fftSize) {\n this.fftSize = config.fftSize;\n needsReconnect = true;\n }\n \n if (config.smoothing !== undefined) {\n this.smoothingTimeConstant = config.smoothing;\n if (this.analyser) {\n this.analyser.smoothingTimeConstant = this.smoothingTimeConstant;\n }\n }\n \n // Reconnect if FFT size changed (requires new analyser)\n if (needsReconnect && this.currentStream) {\n const stream = this.currentStream;\n this.setAudioStream(stream);\n }\n }\n\n /**\n * Start the audio analysis loop\n */\n private startAnalysisLoop(): void {\n if (this.isAnalysisRunning) return;\n \n this.isAnalysisRunning = true;\n this.performAnalysis();\n }\n\n /**\n * Stop the audio analysis loop\n */\n private stopAnalysisLoop(): void {\n this.isAnalysisRunning = false;\n if (this.analysisLoopId !== null) {\n cancelAnimationFrame(this.analysisLoopId);\n this.analysisLoopId = null;\n }\n }\n\n /**\n * Perform audio analysis (called every frame)\n */\n private performAnalysis(): void {\n if (!this.isAnalysisRunning || !this.analyser || !this.frequencyData || !this.timeDomainData) {\n return;\n }\n \n // Get current audio data\n this.analyser.getByteFrequencyData(this.frequencyData);\n this.analyser.getByteTimeDomainData(this.timeDomainData);\n \n // Calculate volume metrics\n this.calculateVolumeMetrics();\n \n // Calculate frequency bands\n this.calculateFrequencyBands();\n \n // Send results to worker\n this.sendAnalysisResultsToWorker();\n \n // Schedule next analysis\n this.analysisLoopId = requestAnimationFrame(() => this.performAnalysis());\n }\n\n /**\n * Calculate RMS and peak volume from time domain data\n */\n private calculateVolumeMetrics(): void {\n if (!this.timeDomainData) return;\n \n let rmsSum = 0;\n let peak = 0;\n \n for (let i = 0; i < this.timeDomainData.length; i++) {\n // Convert from 0-255 to -1 to 1\n const sample = (this.timeDomainData[i] - 128) / 128;\n \n // RMS calculation\n rmsSum += sample * sample;\n \n // Peak calculation\n const absValue = Math.abs(sample);\n if (absValue > peak) {\n peak = absValue;\n }\n }\n \n // Calculate RMS (Root Mean Square)\n const rms = Math.sqrt(rmsSum / this.timeDomainData.length);\n \n // Update audio state (values between 0 and 1)\n this.audioState.volume.rms = rms;\n this.audioState.volume.peak = peak;\n }\n\n /**\n * Calculate frequency band values from frequency data\n */\n private calculateFrequencyBands(): void {\n if (!this.frequencyData || !this.audioContext) return;\n \n const nyquist = this.audioContext.sampleRate / 2;\n const binCount = this.frequencyData.length;\n \n // Define frequency bands (in Hz)\n const bands = {\n subBass: { min: 20, max: 60 }, // Sub-bass\n bass: { min: 60, max: 250 }, // Bass\n lowMid: { min: 250, max: 500 }, // Low midrange\n mid: { min: 500, max: 2000 }, // Midrange\n highMid: { min: 2000, max: 4000 }, // High midrange\n presence: { min: 4000, max: 6000 }, // Presence\n brilliance: { min: 6000, max: 20000 }, // Brilliance\n treble: { min: 2000, max: 20000 } // Treble (combined high frequencies)\n };\n \n // Calculate band values\n for (const [bandName, range] of Object.entries(bands)) {\n const startBin = Math.floor((range.min / nyquist) * binCount);\n const endBin = Math.min(Math.floor((range.max / nyquist) * binCount), binCount - 1);\n \n let sum = 0;\n let count = 0;\n \n for (let i = startBin; i <= endBin; i++) {\n sum += this.frequencyData[i];\n count++;\n }\n \n // Average and normalize (0-255 to 0-1)\n const average = count > 0 ? sum / count : 0;\n (this.audioState.bands as any)[bandName] = average / 255;\n }\n }\n\n /**\n * Send analysis results to worker\n */\n private sendAnalysisResultsToWorker(): void {\n if (this.sendAnalysisResults) {\n // Include raw frequency data access\n const frequencyData = this.frequencyData ? new Uint8Array(this.frequencyData) : new Uint8Array(0);\n \n this.sendAnalysisResults({\n type: 'audio-analysis-update',\n data: {\n ...this.audioState,\n frequencyData, // For getFrequencyData() access\n timestamp: performance.now()\n }\n });\n }\n }\n\n /**\n * Reset audio values to defaults\n */\n private resetAudioValues(): void {\n this.audioState.volume.rms = 0;\n this.audioState.volume.peak = 0;\n \n for (const band in this.audioState.bands) {\n (this.audioState.bands as any)[band] = 0;\n }\n }\n\n /**\n * Reset all audio state (called when destroying)\n */\n public resetAudioState(): void {\n this.disconnectAudioStream();\n \n // Close AudioContext if it exists\n if (this.audioContext && this.audioContext.state !== 'closed') {\n this.audioContext.close();\n this.audioContext = null;\n }\n \n this.resetAudioValues();\n }\n\n /**\n * Get current analysis configuration\n */\n public getAnalysisConfig(): { fftSize: number; smoothing: number } {\n return {\n fftSize: this.fftSize,\n smoothing: this.smoothingTimeConstant\n };\n }\n} ","/**\r\n * Lightweight Video Coordinator for the host side.\r\n * Handles MediaStream management and coordinates with worker-side VideoSystem.\r\n * \r\n * CORRECT OffscreenCanvas Approach:\r\n * - Create OffscreenCanvas on host (no context!)\r\n * - Transfer to worker immediately \r\n * - Worker gets context and handles all processing\r\n * - Send video frames as ImageBitmap for worker to draw\r\n */\r\nexport class VideoCoordinator {\r\n // Video elements for MediaStream processing\r\n private videoElement: HTMLVideoElement | null = null;\r\n private canvas: HTMLCanvasElement | null = null;\r\n private ctx: CanvasRenderingContext2D | null = null;\r\n // Note: currentStream was removed as it was unused\r\n \r\n // Transfer coordination\r\n private transferLoopId: number | null = null;\r\n private isTransferRunning = false;\r\n private lastTransferTime = 0;\r\n private transferInterval = 1000 / 30; // Transfer at 30 FPS\r\n \r\n // Video state (lightweight - main state is in worker)\r\n private coordinatorState = {\r\n isConnected: false,\r\n sourceType: '',\r\n frameWidth: 0,\r\n frameHeight: 0\r\n };\r\n \r\n // Track if OffscreenCanvas has been sent to worker\r\n private hasTransferredCanvas = false;\r\n \r\n // Callback to send data to worker\r\n private sendToWorker: ((data: any, transfer?: Transferable[]) => void) | null = null;\r\n \r\n // Debug logging control\r\n private debugMode = false;\r\n\r\n /**\r\n * Enable or disable debug logging\r\n */\r\n setDebugMode(enabled: boolean): void {\r\n this.debugMode = enabled;\r\n }\r\n\r\n /**\r\n * Debug logging helper\r\n */\r\n private debugLog(message: string, ...args: any[]): void {\r\n if (this.debugMode) {\r\n console.log(message, ...args);\r\n }\r\n }\r\n\r\n constructor(sendToWorkerCallback?: (data: any, transfer?: Transferable[]) => void) {\r\n // Bind methods for proper context\r\n this.handleVideoStreamUpdate = this.handleVideoStreamUpdate.bind(this);\r\n this.transferVideoFrame = this.transferVideoFrame.bind(this);\r\n this.sendToWorker = sendToWorkerCallback || null;\r\n }\r\n\r\n /**\r\n * Get the current video coordinator state (for host-side usage)\r\n */\r\n public getCoordinatorState() {\r\n return { ...this.coordinatorState };\r\n }\r\n\r\n /**\r\n * Handle video stream update (called from VijiCore)\r\n */\r\n public handleVideoStreamUpdate(data: {\r\n videoStream?: MediaStream | null;\r\n targetFrameRate?: number;\r\n cvConfig?: any; // Phase 11 preparation\r\n timestamp: number;\r\n }): void {\r\n try {\r\n if (data.videoStream) {\r\n this.setVideoStream(data.videoStream);\r\n } else {\r\n // Stream removed or null\r\n this.disconnectVideoStream();\r\n }\r\n \r\n // Forward configuration to worker\r\n if (data.targetFrameRate || data.cvConfig) {\r\n this.sendConfigurationToWorker({\r\n ...(data.targetFrameRate && { targetFrameRate: data.targetFrameRate }),\r\n ...(data.cvConfig && { cvConfig: data.cvConfig }),\r\n timestamp: data.timestamp\r\n });\r\n }\r\n } catch (error) {\r\n console.error('Error handling video stream update:', error);\r\n this.coordinatorState.isConnected = false;\r\n this.sendDisconnectionToWorker();\r\n }\r\n }\r\n\r\n /**\r\n * Set the video stream for processing\r\n */\r\n private async setVideoStream(videoStream: MediaStream): Promise<void> {\r\n // Clean up existing connections\r\n this.disconnectVideoStream();\r\n \r\n // Check if stream has video tracks\r\n const videoTracks = videoStream.getVideoTracks();\r\n if (videoTracks.length === 0) {\r\n console.warn('No video tracks in provided stream');\r\n this.coordinatorState.isConnected = false;\r\n this.sendDisconnectionToWorker();\r\n return;\r\n }\r\n \r\n try {\r\n // Create video element for stream playback\r\n this.videoElement = document.createElement('video');\r\n this.videoElement.autoplay = true;\r\n this.videoElement.muted = true; // Prevent audio from playing\r\n this.videoElement.playsInline = true; // Important for mobile\r\n \r\n // Create canvas for frame capture\r\n this.canvas = document.createElement('canvas');\r\n this.ctx = this.canvas.getContext('2d');\r\n \r\n if (!this.ctx) {\r\n throw new Error('Failed to get 2D context from canvas');\r\n }\r\n \r\n // Set up video element\r\n this.videoElement.srcObject = videoStream;\r\n \r\n // Wait for video metadata to load and ensure video is playing\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(() => reject(new Error('Video metadata load timeout')), 5000);\r\n \r\n this.videoElement!.addEventListener('loadedmetadata', async () => {\r\n clearTimeout(timeout);\r\n \r\n try {\r\n // Ensure video starts playing\r\n await this.videoElement!.play();\r\n this.debugLog('✅ Video element is now playing:', {\r\n videoWidth: this.videoElement!.videoWidth,\r\n videoHeight: this.videoElement!.videoHeight,\r\n readyState: this.videoElement!.readyState,\r\n paused: this.videoElement!.paused\r\n });\r\n resolve();\r\n } catch (playError) {\r\n console.error('🔴 Failed to start video playback:', playError);\r\n reject(playError);\r\n }\r\n }, { once: true });\r\n \r\n this.videoElement!.addEventListener('error', (e) => {\r\n clearTimeout(timeout);\r\n reject(new Error(`Video load error: ${e}`));\r\n }, { once: true });\r\n });\r\n \r\n // Set canvas dimensions to match video\r\n this.canvas.width = this.videoElement.videoWidth;\r\n this.canvas.height = this.videoElement.videoHeight;\r\n \r\n // Update state (stream reference stored in coordinatorState)\r\n this.coordinatorState.isConnected = true;\r\n this.coordinatorState.frameWidth = this.videoElement.videoWidth;\r\n this.coordinatorState.frameHeight = this.videoElement.videoHeight;\r\n this.coordinatorState.sourceType = 'MediaStream';\r\n \r\n // ✅ CORRECT OffscreenCanvas approach: Transfer canvas to worker FIRST\r\n await this.transferOffscreenCanvasToWorker(this.videoElement.videoWidth, this.videoElement.videoHeight);\r\n \r\n // Start frame transfer loop\r\n this.startTransferLoop();\r\n \r\n this.debugLog('Video stream connected successfully (host-side coordinator)', {\r\n width: this.videoElement.videoWidth,\r\n height: this.videoElement.videoHeight\r\n });\r\n \r\n } catch (error) {\r\n console.error('Failed to set up video coordination:', error);\r\n this.coordinatorState.isConnected = false;\r\n this.disconnectVideoStream();\r\n }\r\n }\r\n\r\n /**\r\n * ✅ CORRECT: Transfer OffscreenCanvas to worker BEFORE getting context\r\n */\r\n private async transferOffscreenCanvasToWorker(width: number, height: number): Promise<void> {\r\n if (this.hasTransferredCanvas) {\r\n // Canvas already transferred, just update dimensions\r\n this.sendConfigurationToWorker({\r\n width: width,\r\n height: height,\r\n timestamp: performance.now()\r\n });\r\n return;\r\n }\r\n\r\n try {\r\n // Create OffscreenCanvas - NO CONTEXT on host side!\r\n const offscreenCanvas = new OffscreenCanvas(width, height);\r\n \r\n // Transfer immediately to worker (before any context creation)\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-canvas-setup',\r\n data: {\r\n offscreenCanvas,\r\n width,\r\n height,\r\n timestamp: performance.now()\r\n }\r\n }, [offscreenCanvas]); // ✅ Transfer ownership to worker\r\n \r\n this.hasTransferredCanvas = true;\r\n this.debugLog('✅ OffscreenCanvas transferred to worker (correct approach)', {\r\n width,\r\n height\r\n });\r\n }\r\n } catch (error) {\r\n console.error('Failed to transfer OffscreenCanvas to worker:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Disconnect current video stream and clean up resources\r\n */\r\n private disconnectVideoStream(): void {\r\n // Stop transfer loop\r\n this.stopTransferLoop();\r\n \r\n // Clean up video element\r\n if (this.videoElement) {\r\n this.videoElement.pause();\r\n this.videoElement.srcObject = null;\r\n this.videoElement = null;\r\n }\r\n \r\n // Clean up canvas\r\n if (this.canvas) {\r\n this.canvas = null;\r\n this.ctx = null;\r\n }\r\n \r\n // Clear stream reference\r\n // Stream cleanup handled by MediaStream track stopping\r\n \r\n // Update state\r\n this.coordinatorState.isConnected = false;\r\n this.coordinatorState.frameWidth = 0;\r\n this.coordinatorState.frameHeight = 0;\r\n this.coordinatorState.sourceType = '';\r\n this.hasTransferredCanvas = false;\r\n \r\n // Notify worker of disconnection\r\n this.sendDisconnectionToWorker();\r\n \r\n this.debugLog('Video stream disconnected (host-side coordinator)');\r\n }\r\n\r\n /**\r\n * Start the video frame transfer loop\r\n */\r\n private startTransferLoop(): void {\r\n if (this.isTransferRunning) return;\r\n \r\n this.isTransferRunning = true;\r\n this.lastTransferTime = performance.now();\r\n this.transferVideoFrame();\r\n }\r\n\r\n /**\r\n * Stop the video frame transfer loop\r\n */\r\n private stopTransferLoop(): void {\r\n this.isTransferRunning = false;\r\n if (this.transferLoopId !== null) {\r\n cancelAnimationFrame(this.transferLoopId);\r\n this.transferLoopId = null;\r\n }\r\n }\r\n\r\n /**\r\n * Transfer video frame to worker using ImageBitmap (for worker to draw on its OffscreenCanvas)\r\n */\r\n private transferVideoFrame(): void {\r\n if (!this.isTransferRunning || !this.videoElement || !this.canvas || !this.ctx) {\r\n if (!this.isTransferRunning) {\r\n this.debugLog('🔴 Transfer loop stopped');\r\n }\r\n return;\r\n }\r\n \r\n const currentTime = performance.now();\r\n const deltaTime = currentTime - this.lastTransferTime;\r\n \r\n // Only transfer frame if enough time has passed (FPS-based transfer)\r\n if (deltaTime >= this.transferInterval) {\r\n // Log occasionally to avoid spam (very rarely now that it's working)\r\n if (Math.random() < 0.01) { // Log ~1% of frames\r\n this.debugLog(`🔄 Transfer loop tick: ${deltaTime.toFixed(1)}ms since last frame`);\r\n }\r\n \r\n this.transferFrameToWorker().catch(error => {\r\n console.error('🔴 Error transferring video frame to worker:', error);\r\n });\r\n \r\n this.lastTransferTime = currentTime;\r\n }\r\n \r\n // Schedule next transfer check\r\n this.transferLoopId = requestAnimationFrame(() => this.transferVideoFrame());\r\n }\r\n\r\n /**\r\n * Async frame transfer using ImageBitmap (for worker to draw)\r\n */\r\n private async transferFrameToWorker(): Promise<void> {\r\n if (!this.videoElement || !this.canvas || !this.ctx) {\r\n console.warn('🔴 Frame transfer called but missing elements:', {\r\n hasVideo: !!this.videoElement,\r\n hasCanvas: !!this.canvas,\r\n hasCtx: !!this.ctx\r\n });\r\n return;\r\n }\r\n\r\n try {\r\n // Check if video is actually playing\r\n if (this.videoElement.readyState < 2) {\r\n console.warn('🔴 Video not ready for frame capture, readyState:', this.videoElement.readyState);\r\n return;\r\n }\r\n \r\n if (this.videoElement.videoWidth === 0 || this.videoElement.videoHeight === 0) {\r\n console.warn('🔴 Video has no dimensions:', {\r\n width: this.videoElement.videoWidth,\r\n height: this.videoElement.videoHeight\r\n });\r\n return;\r\n }\r\n \r\n // Draw current video frame to canvas\r\n this.ctx.drawImage(this.videoElement, 0, 0, this.canvas.width, this.canvas.height);\r\n \r\n // Create ImageBitmap from canvas (for worker to draw onto its OffscreenCanvas)\r\n const imageBitmap = await createImageBitmap(this.canvas);\r\n \r\n // Log occasionally to avoid spam (very rarely now that it's working)\r\n if (Math.random() < 0.01) { // Log ~1% of frames\r\n this.debugLog('✅ Frame captured and ImageBitmap created:', {\r\n videoDimensions: `${this.videoElement.videoWidth}x${this.videoElement.videoHeight}`,\r\n canvasDimensions: `${this.canvas.width}x${this.canvas.height}`,\r\n bitmapDimensions: `${imageBitmap.width}x${imageBitmap.height}`\r\n });\r\n }\r\n \r\n // Send ImageBitmap to worker (worker will draw it on its OffscreenCanvas)\r\n this.sendFrameToWorker(imageBitmap);\r\n \r\n } catch (error) {\r\n console.error('🔴 Failed to create ImageBitmap:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Send ImageBitmap frame to worker (for worker to draw on its OffscreenCanvas)\r\n */\r\n private sendFrameToWorker(imageBitmap: ImageBitmap): void {\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-frame-update',\r\n data: {\r\n imageBitmap,\r\n timestamp: performance.now()\r\n }\r\n }, [imageBitmap]); // Transfer the ImageBitmap\r\n }\r\n }\r\n\r\n /**\r\n * Send configuration updates to worker\r\n */\r\n private sendConfigurationToWorker(config: {\r\n targetFrameRate?: number;\r\n cvConfig?: any;\r\n width?: number;\r\n height?: number;\r\n timestamp: number;\r\n }): void {\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-config-update',\r\n data: config\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Send disconnection notification to worker\r\n */\r\n private sendDisconnectionToWorker(): void {\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-config-update',\r\n data: {\r\n disconnect: true,\r\n timestamp: performance.now()\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Handle image file as video source\r\n */\r\n public async setImageSource(imageFile: File): Promise<void> {\r\n try {\r\n // Create image element\r\n const img = new Image();\r\n const url = URL.createObjectURL(imageFile);\r\n \r\n // Load image\r\n await new Promise<void>((resolve, reject) => {\r\n img.onload = () => {\r\n URL.revokeObjectURL(url);\r\n resolve();\r\n };\r\n img.onerror = () => {\r\n URL.revokeObjectURL(url);\r\n reject(new Error('Failed to load image'));\r\n };\r\n img.src = url;\r\n });\r\n \r\n // Clean up existing connections\r\n this.disconnectVideoStream();\r\n \r\n // Update state for static image\r\n this.coordinatorState.isConnected = true;\r\n this.coordinatorState.frameWidth = img.width;\r\n this.coordinatorState.frameHeight = img.height;\r\n this.coordinatorState.sourceType = 'Image';\r\n \r\n // Transfer OffscreenCanvas to worker first\r\n await this.transferOffscreenCanvasToWorker(img.width, img.height);\r\n \r\n // Create ImageBitmap and send to worker for drawing\r\n const imageBitmap = await createImageBitmap(img);\r\n this.sendFrameToWorker(imageBitmap);\r\n \r\n this.debugLog('Image source set successfully (host-side coordinator)', {\r\n width: img.width,\r\n height: img.height\r\n });\r\n \r\n } catch (error) {\r\n console.error('Failed to set image source:', error);\r\n this.coordinatorState.isConnected = false;\r\n this.sendDisconnectionToWorker();\r\n }\r\n }\r\n\r\n /**\r\n * Reset all video coordinator state (called when destroying)\r\n */\r\n public resetVideoState(): void {\r\n this.disconnectVideoStream();\r\n }\r\n\r\n /**\r\n * Get current coordinator configuration\r\n */\r\n public getCoordinatorConfig(): { transferInterval: number } {\r\n return {\r\n transferInterval: this.transferInterval\r\n };\r\n }\r\n} ","import { IFrameManager } from './iframe/IFrameManager.js';\nimport { WorkerManager } from './worker/WorkerManager.js';\nimport { InteractionManager } from './interaction/InteractionManager.js';\nimport { AudioSystem } from './audio/AudioSystem.js';\nimport { VideoCoordinator } from './video/VideoCoordinator.js';\nimport { \n VijiCoreConfig, \n VijiCoreError, \n PerformanceStats, \n ParameterGroup,\n ParameterDefinition,\n FrameRateMode,\n CVFrameRateMode,\n ParameterValue,\n ParameterDefinitionData,\n ParameterUpdateData,\n CoreCapabilities,\n ParameterCategory,\n CaptureFrameOptions\n} from './types/index.js';\n\n/**\n * Main VijiCore class - Universal execution engine for creative scenes.\n * \n * Orchestrates secure IFrame + WebWorker execution with controlled communication.\n * Provides the foundation for scene execution across platform and SDK contexts.\n */\nexport class VijiCore {\n private iframeManager: IFrameManager | null = null;\n private workerManager: WorkerManager | null = null;\n private interactionManager: InteractionManager | null = null;\n private audioSystem: AudioSystem | null = null;\n private videoCoordinator: VideoCoordinator | null = null;\n private isInitialized = false;\n private isDestroyed = false;\n private isInitializing = false;\n private instanceId: string;\n private screenRefreshRate = 60; // Will be detected\n private debugMode = false; // Debug logging control\n\n /**\n * Debug logging helper\n */\n private debugLog(message: string, ...args: any[]): void {\n if (this.debugMode) {\n console.log(message, ...args);\n }\n }\n \n // Configuration\n private config: VijiCoreConfig & { \n frameRateMode: FrameRateMode;\n autoOptimize: boolean;\n parameters: ParameterGroup[];\n noInputs: boolean;\n allowUserInteraction: boolean;\n };\n\n // Audio stream management\n private currentAudioStream: MediaStream | null = null;\n\n // Video stream management\n private currentVideoStream: MediaStream | null = null;\n\n // Interaction state management\n private currentInteractionEnabled: boolean;\n\n // Parameter system for Phase 2\n private parameterGroups = new Map<string, ParameterGroup>();\n private parameterValues = new Map<string, ParameterValue>();\n private parametersInitialized = false;\n \n // Event listeners for parameter system\n private parameterListeners = new Map<string, Set<(value: ParameterValue) => void>>();\n private parameterDefinedListeners = new Set<(groups: ParameterGroup[]) => void>();\n private parameterErrorListeners = new Set<(error: { message: string; code: string }) => void>();\n private capabilitiesChangeListeners = new Set<(capabilities: CoreCapabilities) => void>();\n \n // Performance tracking (basic for Phase 1)\n private stats: PerformanceStats = {\n frameTime: 0,\n resolution: { width: 0, height: 0 },\n scale: 1.0,\n frameRate: {\n mode: 'full',\n screenRefreshRate: 60,\n effectiveRefreshRate: 60\n },\n rendererType: 'native',\n parameterCount: 0\n };\n\n constructor(config: VijiCoreConfig) {\n // Validate required configuration\n this.validateConfig(config);\n \n // Generate unique instance ID for debugging\n this.instanceId = `viji-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n \n // Set default configuration values\n this.config = {\n ...config,\n frameRateMode: config.frameRateMode || 'full',\n autoOptimize: config.autoOptimize ?? true,\n parameters: config.parameters || [],\n noInputs: config.noInputs ?? false,\n allowUserInteraction: config.allowUserInteraction ?? true\n };\n \n // Initialize interaction state from config\n this.currentInteractionEnabled = this.config.allowUserInteraction;\n \n this.debugLog(`VijiCore instance created: ${this.instanceId}`);\n }\n\n /**\n * Capture current scene frame as an image Blob.\n * Resolution can be a scale (0-1+) or explicit width/height with center-crop.\n */\n async captureFrame(options: CaptureFrameOptions = {}): Promise<Blob> {\n if (!this.workerManager || !this.workerManager.ready) {\n throw new VijiCoreError('Core not initialized', 'NOT_INITIALIZED');\n }\n\n const response = await this.workerManager.sendMessage('capture-frame', {\n type: options.type,\n resolution: options.resolution\n }, 10000);\n\n // response contains { mimeType, buffer, width, height }\n const buffer: ArrayBuffer = response.buffer;\n const mimeType: string = response.mimeType || options.type || 'image/jpeg';\n return new Blob([buffer], { type: mimeType });\n }\n\n /**\n * Enable or disable debug logging\n */\n setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n // Propagate debug mode to child components when they exist\n if (this.iframeManager && 'setDebugMode' in this.iframeManager) {\n (this.iframeManager as any).setDebugMode(enabled);\n }\n if (this.workerManager && 'setDebugMode' in this.workerManager) {\n (this.workerManager as any).setDebugMode(enabled);\n }\n if (this.interactionManager && 'setDebugMode' in this.interactionManager) {\n (this.interactionManager as any).setDebugMode(enabled);\n }\n if (this.audioSystem && 'setDebugMode' in this.audioSystem) {\n (this.audioSystem as any).setDebugMode(enabled);\n }\n if (this.videoCoordinator && 'setDebugMode' in this.videoCoordinator) {\n (this.videoCoordinator as any).setDebugMode(enabled);\n }\n \n // Also propagate to worker runtime if available\n if (this.workerManager) {\n this.workerManager.postMessage('debug-mode', { enabled });\n }\n }\n\n /**\n * Get current debug mode status\n */\n getDebugMode(): boolean {\n return this.debugMode;\n }\n\n /**\n * Initializes the core components in sequence\n */\n async initialize(): Promise<void> {\n try {\n if (this.isDestroyed) {\n throw new VijiCoreError('Cannot initialize destroyed instance', 'INSTANCE_DESTROYED');\n }\n\n if (this.isInitializing) {\n throw new VijiCoreError('Initialization already in progress', 'CONCURRENT_INITIALIZATION');\n }\n\n if (this.isInitialized) {\n throw new VijiCoreError('Core already initialized', 'ALREADY_INITIALIZED');\n }\n\n this.isInitializing = true;\n this.debugLog(`Starting VijiCore initialization... (${this.instanceId})`);\n\n // Clear any existing content in the container\n this.config.hostContainer.innerHTML = '';\n\n // 1. Create secure IFrame\n this.iframeManager = new IFrameManager(\n this.config.hostContainer,\n );\n \n await this.iframeManager.createSecureIFrame();\n \n // 2. Create canvas inside IFrame with retry logic\n const offscreenCanvas = await this.createCanvasWithRetry();\n \n // 3. Phase 7: Always setup interaction system for runtime control\n // DOM event listeners are still conditionally created based on enabled state\n this.interactionManager = new InteractionManager();\n this.setupInteractionSystem();\n \n // 4. Create and initialize WebWorker\n this.workerManager = new WorkerManager(\n this.config.sceneCode,\n offscreenCanvas\n );\n \n // 5. Setup communication handlers BEFORE creating worker\n this.setupCommunication();\n \n await this.workerManager.createWorker();\n \n // 6. Initialize AudioSystem (host-side) with callback to send results to worker\n this.audioSystem = new AudioSystem((message) => {\n if (this.workerManager) {\n this.workerManager.postMessage(message.type, message.data);\n }\n });\n\n // 7. Initialize VideoCoordinator (host-side) with callback to send results to worker\n this.videoCoordinator = new VideoCoordinator((message, transfer) => {\n if (this.workerManager) {\n if (transfer && transfer.length > 0) {\n this.workerManager.postMessage(message.type, message.data, transfer);\n } else {\n this.workerManager.postMessage(message.type, message.data);\n }\n }\n });\n \n // 5. Send initial resolution info to worker\n const effectiveResolution = this.iframeManager.getEffectiveResolution();\n this.workerManager.postMessage('resolution-update', {\n effectiveWidth: effectiveResolution.width,\n effectiveHeight: effectiveResolution.height\n });\n \n // 6. Detect screen refresh rate and update stats\n await this.detectScreenRefreshRate();\n \n // Send detected refresh rate to worker\n this.workerManager.postMessage('refresh-rate-update', {\n screenRefreshRate: this.screenRefreshRate\n });\n \n // 8. Phase 5: Setup audio stream if provided\n if (this.config.audioStream) {\n await this.setAudioStream(this.config.audioStream);\n }\n \n // 9. Phase 10: Setup video stream if provided\n if (this.config.videoStream) {\n await this.setVideoStream(this.config.videoStream);\n }\n \n this.stats.resolution = effectiveResolution;\n this.stats.scale = this.iframeManager.getScale();\n this.updateFrameRateStats();\n \n this.isInitialized = true;\n this.isInitializing = false;\n \n this.debugLog(`VijiCore initialized successfully (${this.instanceId}):`, {\n resolution: `${effectiveResolution.width}x${effectiveResolution.height}`,\n frameRateMode: this.config.frameRateMode,\n hasAudio: !!this.config.audioStream,\n hasVideo: !!this.config.videoStream\n });\n } catch (error) {\n // Clean up on initialization failure\n this.isInitializing = false;\n await this.cleanup();\n \n throw new VijiCoreError(\n `Failed to initialize VijiCore: ${error}`,\n 'INITIALIZATION_ERROR',\n { error, config: this.config }\n );\n }\n }\n\n /**\n * Creates canvas with retry logic to handle timing issues\n */\n private async createCanvasWithRetry(): Promise<OffscreenCanvas> {\n const maxRetries = 3; // Reduced retries since we have better error handling\n const retryDelay = 200;\n \n for (let i = 0; i < maxRetries; i++) {\n // Check if we should continue (not destroyed/destroyed during retry)\n if (this.isDestroyed || !this.isInitializing) {\n throw new VijiCoreError('Initialization cancelled', 'INITIALIZATION_CANCELLED');\n }\n \n if (!this.iframeManager) {\n throw new VijiCoreError('IFrameManager not available', 'MANAGER_NOT_READY');\n }\n \n try {\n return await this.iframeManager.createCanvas();\n } catch (error) {\n console.warn(`Canvas creation attempt ${i + 1}/${maxRetries} failed:`, error);\n \n if (i === maxRetries - 1) {\n // Last attempt failed\n throw error;\n }\n \n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n }\n }\n \n throw new VijiCoreError('Canvas creation failed after all retries', 'CANVAS_CREATION_TIMEOUT');\n }\n\n /**\n * Sets up the interaction system for Phase 7\n */\n private setupInteractionSystem(): void {\n if (!this.iframeManager || !this.interactionManager) return;\n\n // Set up event forwarding from iframe to interaction manager\n this.iframeManager.onInteractionEvent('mouse-update', (data) => {\n this.interactionManager?.updateMouse(data);\n \n // Forward to worker if available\n if (this.workerManager) {\n this.workerManager.postMessage('mouse-update', data);\n }\n });\n\n this.iframeManager.onInteractionEvent('keyboard-update', (data) => {\n this.interactionManager?.updateKeyboard(data);\n \n // Forward to worker if available\n if (this.workerManager) {\n this.workerManager.postMessage('keyboard-update', data);\n }\n });\n\n this.iframeManager.onInteractionEvent('touch-update', (data) => {\n this.interactionManager?.updateTouch(data);\n \n // Forward to worker if available\n if (this.workerManager) {\n this.workerManager.postMessage('touch-update', data);\n }\n });\n\n // Enable interaction events on the iframe based on current state\n this.iframeManager.setInteractionEnabled(this.currentInteractionEnabled);\n }\n\n /**\n * Sets up communication between components\n */\n private setupCommunication(): void {\n if (!this.workerManager) return;\n\n // Handle worker ready event (separate from init response)\n this.workerManager.onMessage('ready', (data) => {\n this.debugLog('Worker ready:', data);\n // Capture rendererType from ready event\n if (data.rendererType !== undefined) {\n this.stats.rendererType = data.rendererType;\n }\n });\n\n this.workerManager.onMessage('error', (data) => {\n console.error('Worker error:', data);\n });\n\n this.workerManager.onMessage('performance-warning', (data) => {\n console.warn('Performance warning:', data);\n // TODO: Handle performance optimization in Phase 8\n });\n\n this.workerManager.onMessage('performance-update', (data) => {\n // Update stats with real-time performance data from worker\n if (data.effectiveRefreshRate !== undefined) {\n this.stats.frameRate.effectiveRefreshRate = data.effectiveRefreshRate;\n this.stats.frameRate.mode = data.frameRateMode;\n this.stats.frameRate.screenRefreshRate = data.screenRefreshRate;\n }\n if (data.rendererType !== undefined) {\n this.stats.rendererType = data.rendererType;\n }\n if (data.parameterCount !== undefined) {\n this.stats.parameterCount = data.parameterCount;\n }\n // Update CV stats if available\n if (data.cv !== undefined) {\n this.stats.cv = data.cv;\n }\n });\n\n // Parameter system message handlers for Phase 2\n this.workerManager.onMessage('parameters-defined', (data: ParameterDefinitionData) => {\n this.handleParametersDefined(data);\n });\n\n this.workerManager.onMessage('parameter-validation-error', (data) => {\n this.handleParameterError(data);\n });\n }\n\n // Parameter system implementation for Phase 2\n\n /**\n * Handle parameter definitions received from worker\n */\n private handleParametersDefined(data: ParameterDefinitionData): void {\n try {\n // Store parameter groups\n this.parameterGroups.clear();\n this.parameterValues.clear();\n\n for (const group of data.groups) {\n this.parameterGroups.set(group.groupName, group);\n \n // Initialize parameter values with defaults\n for (const [paramName, paramDef] of Object.entries(group.parameters)) {\n this.parameterValues.set(paramName, paramDef.defaultValue);\n }\n }\n\n this.parametersInitialized = true;\n \n this.debugLog(`Parameters initialized: ${this.parameterValues.size} parameters in ${this.parameterGroups.size} groups`);\n\n // Send initial parameter values to worker\n this.syncAllParametersToWorker();\n\n // Notify listeners that parameters are defined\n for (const listener of this.parameterDefinedListeners) {\n try {\n listener(Array.from(this.parameterGroups.values()));\n } catch (error) {\n console.error('Error in parameter defined listener:', error);\n }\n }\n } catch (error) {\n console.error('Error handling parameters defined:', error);\n this.handleParameterError({\n message: `Failed to process parameter definitions: ${(error as Error).message}`,\n code: 'PARAMETER_PROCESSING_ERROR'\n });\n }\n }\n\n /**\n * Handle parameter validation errors\n */\n private handleParameterError(error: { message: string; code: string }): void {\n console.error('Parameter error:', error);\n \n // Notify error listeners\n for (const listener of this.parameterErrorListeners) {\n try {\n listener(error);\n } catch (listenerError) {\n console.error('Error in parameter error listener:', listenerError);\n }\n }\n }\n\n /**\n * Get parameter definition by name\n */\n private getParameterDefinition(name: string): ParameterDefinition | undefined {\n for (const group of this.parameterGroups.values()) {\n if (group.parameters[name]) {\n return group.parameters[name];\n }\n }\n return undefined;\n }\n\n /**\n * Set a single parameter value\n * Handles all parameter types including images intelligently\n */\n async setParameter(name: string, value: ParameterValue | File | Blob): Promise<void> {\n this.validateReady();\n \n if (!this.parametersInitialized) {\n throw new VijiCoreError('Parameters not yet initialized', 'PARAMETERS_NOT_INITIALIZED');\n }\n\n if (!this.parameterValues.has(name)) {\n throw new VijiCoreError(`Unknown parameter: ${name}`, 'UNKNOWN_PARAMETER');\n }\n\n // Get parameter definition to check type\n const paramDef = this.getParameterDefinition(name);\n \n // Handle image parameters specially\n if (paramDef?.type === 'image') {\n await this.handleImageParameter(name, value);\n return;\n }\n\n // Handle standard parameters (number, boolean, string, color, etc.)\n const oldValue = this.parameterValues.get(name);\n this.parameterValues.set(name, value as ParameterValue);\n\n // Send to worker\n if (this.workerManager) {\n this.workerManager.postMessage('parameter-update', {\n name,\n value\n });\n }\n\n // Notify listeners if value changed\n if (oldValue !== value) {\n this.notifyParameterListeners(name, value as ParameterValue);\n }\n }\n\n /**\n * Internal method to handle image parameter loading and transfer\n * Loads the image on the host side and creates TWO ImageBitmaps:\n * - One for the host (listeners, previews)\n * - One to transfer to the worker\n */\n private async handleImageParameter(name: string, value: ParameterValue | File | Blob): Promise<void> {\n try {\n let hostImageBitmap: ImageBitmap | null = null;\n let workerImageBitmap: ImageBitmap | null = null;\n\n if (value === null || value === undefined) {\n // Clear the image parameter\n hostImageBitmap = null;\n workerImageBitmap = null;\n } else if (typeof value === 'string') {\n // Load from URL - create two ImageBitmaps from the same source\n const response = await fetch(value);\n const blob = await response.blob();\n // Create both bitmaps from the blob\n [hostImageBitmap, workerImageBitmap] = await Promise.all([\n createImageBitmap(blob),\n createImageBitmap(blob)\n ]);\n } else if (value instanceof File || value instanceof Blob) {\n // Load from File or Blob - create two ImageBitmaps from the same source\n [hostImageBitmap, workerImageBitmap] = await Promise.all([\n createImageBitmap(value),\n createImageBitmap(value)\n ]);\n } else if (value instanceof ImageBitmap) {\n // Already an ImageBitmap - need to clone it by drawing to canvas\n const canvas = document.createElement('canvas');\n canvas.width = value.width;\n canvas.height = value.height;\n const ctx = canvas.getContext('2d')!;\n ctx.drawImage(value, 0, 0);\n \n // Keep original for host, create new one from canvas for worker\n hostImageBitmap = value;\n workerImageBitmap = await createImageBitmap(canvas);\n } else {\n throw new Error(`Invalid value type for image parameter. Expected File, Blob, string (URL), or null.`);\n }\n\n // Update local value (store host copy)\n const oldValue = this.parameterValues.get(name);\n this.parameterValues.set(name, hostImageBitmap);\n\n // Send worker copy to worker using unified parameter-update message\n // Transfer worker ImageBitmap (host copy remains intact for listeners)\n if (this.workerManager) {\n const messageData = {\n name,\n value: workerImageBitmap\n };\n \n // Transfer worker ImageBitmap if present (more efficient than cloning)\n const transferList = workerImageBitmap ? [workerImageBitmap] : [];\n this.workerManager.postMessage('parameter-update', messageData, transferList);\n }\n\n // Notify listeners with host copy (not transferred, still usable)\n if (oldValue !== hostImageBitmap) {\n this.notifyParameterListeners(name, hostImageBitmap);\n }\n\n this.debugLog(`Image parameter '${name}' ${hostImageBitmap ? 'loaded' : 'cleared'} (${this.instanceId})`);\n } catch (error) {\n throw new VijiCoreError(\n `Failed to load image for parameter '${name}': ${error}`,\n 'IMAGE_LOAD_ERROR',\n { error, name }\n );\n }\n }\n\n /**\n * Set multiple parameter values efficiently\n */\n async setParameters(values: Record<string, ParameterValue>): Promise<void> {\n this.validateReady();\n \n if (!this.parametersInitialized) {\n throw new VijiCoreError('Parameters not yet initialized', 'PARAMETERS_NOT_INITIALIZED');\n }\n\n const updates: ParameterUpdateData[] = [];\n const changedParams: Array<{ name: string; value: ParameterValue }> = [];\n\n // Prepare updates\n for (const [name, value] of Object.entries(values)) {\n if (!this.parameterValues.has(name)) {\n console.warn(`Unknown parameter: ${name}`);\n continue;\n }\n\n const oldValue = this.parameterValues.get(name);\n this.parameterValues.set(name, value);\n \n updates.push({\n name,\n value\n });\n\n if (oldValue !== value) {\n changedParams.push({ name, value });\n }\n }\n\n // Send batch update to worker\n if (updates.length > 0 && this.workerManager) {\n this.workerManager.postMessage('parameter-batch-update', {\n updates\n });\n }\n\n // Notify listeners for changed parameters\n for (const { name, value } of changedParams) {\n this.notifyParameterListeners(name, value);\n }\n }\n\n /**\n * Get current parameter value\n */\n getParameter(name: string): ParameterValue | undefined {\n return this.parameterValues.get(name);\n }\n\n /**\n * Get all current parameter values\n */\n getParameterValues(): Record<string, ParameterValue> {\n const values: Record<string, ParameterValue> = {};\n for (const [name, value] of this.parameterValues) {\n values[name] = value;\n }\n return values;\n }\n\n /**\n * Get parameter groups (for UI generation)\n */\n getParameterGroups(): ParameterGroup[] {\n return Array.from(this.parameterGroups.values());\n }\n\n /**\n * Get current core capabilities (what's currently active)\n */\n getCapabilities(): CoreCapabilities {\n return {\n hasAudio: this.currentAudioStream !== null,\n hasVideo: this.currentVideoStream !== null,\n hasInteraction: this.currentInteractionEnabled,\n hasGeneral: true // General parameters are always available\n };\n }\n\n /**\n * Get parameter groups filtered by active capabilities\n */\n getVisibleParameterGroups(): ParameterGroup[] {\n const capabilities = this.getCapabilities();\n const allGroups = this.getParameterGroups();\n \n return allGroups.filter(group => {\n // Filter based on group category\n switch (group.category) {\n case 'audio':\n return capabilities.hasAudio;\n case 'video':\n return capabilities.hasVideo;\n case 'interaction':\n return capabilities.hasInteraction;\n case 'general':\n default:\n return capabilities.hasGeneral;\n }\n }).map(group => ({\n ...group,\n // Also filter individual parameters within groups\n parameters: Object.fromEntries(\n Object.entries(group.parameters).filter(([_, paramDef]) => {\n switch (paramDef.category) {\n case 'audio':\n return capabilities.hasAudio;\n case 'video':\n return capabilities.hasVideo;\n case 'interaction':\n return capabilities.hasInteraction;\n case 'general':\n default:\n return capabilities.hasGeneral;\n }\n })\n )\n }));\n }\n\n /**\n * Get all parameter groups without capability filtering.\n * Returns a deep-cloned structure to prevent external mutation.\n */\n getAllParameterGroups(): ParameterGroup[] {\n const allGroups = this.getParameterGroups();\n return allGroups.map(group => ({\n ...group,\n parameters: Object.fromEntries(\n Object.entries(group.parameters).map(([name, def]) => {\n const clonedDef: any = { ...def };\n if (def.config) {\n clonedDef.config = { ...def.config };\n }\n return [name, clonedDef];\n })\n )\n }));\n }\n\n /**\n * Check if a specific parameter category is currently active\n */\n isCategoryActive(category: ParameterCategory): boolean {\n const capabilities = this.getCapabilities();\n switch (category) {\n case 'audio':\n return capabilities.hasAudio;\n case 'video':\n return capabilities.hasVideo;\n case 'interaction':\n return capabilities.hasInteraction;\n case 'general':\n default:\n return capabilities.hasGeneral;\n }\n }\n\n /**\n * Check if parameters have been initialized\n */\n get parametersReady(): boolean {\n return this.parametersInitialized;\n }\n\n /**\n * Send all current parameter values to worker (used for initial sync)\n */\n private syncAllParametersToWorker(): void {\n if (!this.workerManager || this.parameterValues.size === 0) {\n return;\n }\n\n const updates: ParameterUpdateData[] = [];\n for (const [name, value] of this.parameterValues) {\n updates.push({\n name,\n value\n });\n }\n\n this.workerManager.postMessage('parameter-batch-update', {\n updates\n });\n\n this.debugLog(`Synced ${updates.length} parameter values to worker`);\n }\n\n /**\n * Add listener for when parameters are defined\n */\n onParametersDefined(listener: (groups: ParameterGroup[]) => void): void {\n this.parameterDefinedListeners.add(listener);\n }\n\n /**\n * Remove parameter defined listener\n */\n offParametersDefined(listener: (groups: ParameterGroup[]) => void): void {\n this.parameterDefinedListeners.delete(listener);\n }\n\n /**\n * Add listener for parameter value changes\n */\n onParameterChange(parameterName: string, listener: (value: ParameterValue) => void): void {\n if (!this.parameterListeners.has(parameterName)) {\n this.parameterListeners.set(parameterName, new Set());\n }\n this.parameterListeners.get(parameterName)!.add(listener);\n }\n\n /**\n * Remove parameter change listener\n */\n offParameterChange(parameterName: string, listener: (value: ParameterValue) => void): void {\n const listeners = this.parameterListeners.get(parameterName);\n if (listeners) {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.parameterListeners.delete(parameterName);\n }\n }\n }\n\n /**\n * Add listener for parameter errors\n */\n onParameterError(listener: (error: { message: string; code: string }) => void): void {\n this.parameterErrorListeners.add(listener);\n }\n\n /**\n * Add listener for when core capabilities change (audio/video/interaction state)\n */\n onCapabilitiesChange(listener: (capabilities: CoreCapabilities) => void): void {\n this.capabilitiesChangeListeners.add(listener);\n }\n\n /**\n * Remove capabilities change listener\n */\n removeCapabilitiesListener(listener: (capabilities: CoreCapabilities) => void): void {\n this.capabilitiesChangeListeners.delete(listener);\n }\n\n /**\n * Notify capability change listeners\n */\n private notifyCapabilitiesChange(): void {\n const capabilities = this.getCapabilities();\n for (const listener of this.capabilitiesChangeListeners) {\n try {\n listener(capabilities);\n } catch (error) {\n console.error('Error in capabilities change listener:', error);\n }\n }\n }\n\n /**\n * Remove parameter error listener\n */\n offParameterError(listener: (error: { message: string; code: string }) => void): void {\n this.parameterErrorListeners.delete(listener);\n }\n\n /**\n * Notify parameter change listeners\n */\n private notifyParameterListeners(name: string, value: ParameterValue): void {\n const listeners = this.parameterListeners.get(name);\n if (listeners) {\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n console.error(`Error in parameter listener for '${name}':`, error);\n }\n }\n }\n }\n\n /**\n * Sets the scene frame rate mode\n * @param mode - 'full' for every animation frame, 'half' for every second frame\n */\n async setFrameRate(mode: FrameRateMode): Promise<void> {\n this.validateReady();\n \n this.config.frameRateMode = mode;\n \n // Send frame rate update to worker\n if (this.workerManager) {\n this.workerManager.postMessage('frame-rate-update', { mode });\n }\n \n // Update stats\n this.updateFrameRateStats();\n \n this.debugLog(`Scene frame rate set to ${mode} (${this.instanceId})`);\n }\n\n /**\n * Sets the CV processing frame rate mode (relative to scene frame rate)\n * @param mode - CV processing rate: 'full', 'half', 'quarter', or 'eighth' of scene rate\n */\n async setCVFrameRate(mode: CVFrameRateMode): Promise<void> {\n this.validateReady();\n \n // Send CV frame rate update to worker\n if (this.workerManager) {\n this.workerManager.postMessage('cv-frame-rate-update', { mode });\n }\n \n this.debugLog(`CV frame rate set to ${mode} of scene rate (${this.instanceId})`);\n }\n\n\n /**\n * Updates the canvas resolution by sending effective dimensions to the worker\n */\n updateResolution() {\n this.validateReady();\n \n if (!this.iframeManager || !this.workerManager) {\n throw new VijiCoreError('Managers not available', 'MANAGERS_NOT_READY');\n }\n\n const effectiveResolution = this.iframeManager.getEffectiveResolution();\n this.workerManager.postMessage('resolution-update', {\n effectiveWidth: effectiveResolution.width,\n effectiveHeight: effectiveResolution.height\n });\n\n // Update stats\n this.stats.resolution = effectiveResolution;\n this.stats.scale = this.iframeManager.getScale();\n \n this.debugLog(`Resolution updated successfully (${this.instanceId})`, effectiveResolution);\n }\n\n /**\n * Sets the audio stream for analysis\n */\n async setAudioStream(audioStream: MediaStream | null): Promise<void> {\n // Don't validate ready during initialization\n if (this.isInitialized && !this.isInitializing) {\n this.validateReady();\n }\n \n // Store current stream and track capability change\n const previouslyHadAudio = this.currentAudioStream !== null;\n this.currentAudioStream = audioStream;\n const nowHasAudio = this.currentAudioStream !== null;\n \n // Process audio on host side using AudioSystem\n if (this.audioSystem) {\n this.audioSystem.handleAudioStreamUpdate({\n audioStream: audioStream,\n ...(this.config.analysisConfig && { analysisConfig: this.config.analysisConfig }),\n timestamp: performance.now()\n });\n }\n \n // Notify capabilities change if audio state changed\n if (previouslyHadAudio !== nowHasAudio) {\n this.notifyCapabilitiesChange();\n }\n \n this.debugLog(`Audio stream ${audioStream ? 'connected' : 'disconnected'} (${this.instanceId})`);\n }\n\n /**\n * Sets the video stream for processing\n */\n async setVideoStream(videoStream: MediaStream | null): Promise<void> {\n // Don't validate ready during initialization\n if (this.isInitialized && !this.isInitializing) {\n this.validateReady();\n }\n \n // Store current stream and track capability change\n const previouslyHadVideo = this.currentVideoStream !== null;\n this.currentVideoStream = videoStream;\n const nowHasVideo = this.currentVideoStream !== null;\n \n // Process video on host side using VideoCoordinator\n if (this.videoCoordinator) {\n this.videoCoordinator.handleVideoStreamUpdate({\n videoStream: videoStream,\n targetFrameRate: 30, // Default target FPS\n timestamp: performance.now()\n });\n }\n \n // Notify capabilities change if video state changed\n if (previouslyHadVideo !== nowHasVideo) {\n this.notifyCapabilitiesChange();\n }\n \n this.debugLog(`Video stream ${videoStream ? 'connected' : 'disconnected'} (${this.instanceId})`);\n }\n\n /**\n * Gets the current audio stream\n */\n getAudioStream(): MediaStream | null {\n return this.currentAudioStream;\n }\n\n /**\n * Gets the current video stream\n */\n getVideoStream(): MediaStream | null {\n return this.currentVideoStream;\n }\n\n /**\n * Enables or disables user interactions (mouse, keyboard, touch) at runtime\n */\n async setInteractionEnabled(enabled: boolean): Promise<void> {\n // Don't validate ready during initialization\n if (this.isInitialized && !this.isInitializing) {\n this.validateReady();\n }\n \n // Track capability change\n const previouslyHadInteraction = this.currentInteractionEnabled;\n this.currentInteractionEnabled = enabled;\n \n // Enable/disable interaction capture in IFrameManager\n if (this.iframeManager) {\n this.iframeManager.setInteractionEnabled(enabled);\n }\n \n // Notify worker about interaction state change\n if (this.workerManager) {\n this.workerManager.postMessage('interaction-enabled', { enabled });\n }\n \n // Notify capabilities change if interaction state changed\n if (previouslyHadInteraction !== enabled) {\n this.notifyCapabilitiesChange();\n }\n \n this.debugLog(`Interaction ${enabled ? 'enabled' : 'disabled'} (${this.instanceId})`);\n }\n\n /**\n * Gets the current interaction enabled state\n */\n getInteractionEnabled(): boolean {\n return this.currentInteractionEnabled;\n }\n\n /**\n * Updates audio analysis configuration\n */\n async setAudioAnalysisConfig(config: { fftSize?: number; smoothing?: number }): Promise<void> {\n this.validateReady();\n \n // Update config\n this.config.analysisConfig = { ...this.config.analysisConfig, ...config };\n \n // Update config in host-side AudioSystem\n if (this.audioSystem) {\n this.audioSystem.handleAudioStreamUpdate({\n audioStream: this.currentAudioStream,\n ...(this.config.analysisConfig && { analysisConfig: this.config.analysisConfig }),\n timestamp: performance.now()\n });\n }\n \n this.debugLog(`Audio analysis config updated (${this.instanceId})`, config);\n }\n\n /**\n * Updates the canvas resolution by scale\n */\n setResolution(scale: number) {\n this.validateReady();\n \n if (!this.iframeManager || !this.workerManager) {\n throw new VijiCoreError('Managers not available', 'MANAGERS_NOT_READY');\n }\n \n this.debugLog(`Updating resolution scale to:`, scale, `(${this.instanceId})`);\n \n // Update resolution setting\n const effectiveResolution = this.iframeManager.updateScale(scale);\n \n // Send resolution update to worker\n this.workerManager.postMessage('resolution-update', {\n effectiveWidth: effectiveResolution.width,\n effectiveHeight: effectiveResolution.height\n });\n \n // Update stats\n this.stats.resolution = effectiveResolution;\n this.stats.scale = scale;\n \n this.debugLog(`Resolution updated successfully (${this.instanceId})`, effectiveResolution);\n }\n\n /**\n * Detects the screen refresh rate\n */\n private async detectScreenRefreshRate(): Promise<void> {\n return new Promise((resolve) => {\n let frameCount = 0;\n let startTime = performance.now();\n \n const measureFrames = () => {\n frameCount++;\n if (frameCount === 60) { // Measure for 60 frames\n const elapsed = performance.now() - startTime;\n this.screenRefreshRate = Math.round(60000 / elapsed); // Convert to FPS\n this.debugLog('Detected screen refresh rate:', this.screenRefreshRate + 'Hz');\n resolve();\n } else if (frameCount < 60) {\n requestAnimationFrame(measureFrames);\n }\n };\n \n requestAnimationFrame(measureFrames);\n });\n }\n\n /**\n * Updates frame rate statistics\n */\n private updateFrameRateStats(): void {\n this.stats.frameRate = {\n mode: this.config.frameRateMode,\n screenRefreshRate: this.screenRefreshRate,\n effectiveRefreshRate: 0 // Will be updated by worker during execution\n };\n }\n\n /**\n * Gets current performance statistics\n */\n getStats(): PerformanceStats {\n this.validateReady();\n \n if (!this.iframeManager) {\n throw new VijiCoreError('IFrame manager not available', 'MANAGER_NOT_READY');\n }\n \n return this.stats;\n }\n\n\n /**\n * Checks if the core is ready for use\n */\n get ready(): boolean {\n return this.isInitialized && \n !this.isDestroyed && \n this.iframeManager?.ready === true && \n this.workerManager?.ready === true;\n }\n\n /**\n * Gets the current configuration\n */\n get configuration(): Readonly<VijiCoreConfig> {\n return { ...this.config };\n }\n\n /**\n * Destroys the core instance and cleans up all resources\n */\n async destroy(): Promise<void> {\n if (this.isDestroyed) {\n return; // Already destroyed\n }\n \n this.isDestroyed = true;\n \n // Clear parameter system\n this.parameterGroups.clear();\n this.parameterValues.clear();\n this.parameterListeners.clear();\n this.parameterDefinedListeners.clear();\n this.parameterErrorListeners.clear();\n this.capabilitiesChangeListeners.clear();\n \n // Clean up audio system\n if (this.audioSystem) {\n this.audioSystem.resetAudioState();\n this.audioSystem = null;\n }\n this.currentAudioStream = null;\n \n // Clean up video coordinator\n if (this.videoCoordinator) {\n this.videoCoordinator.resetVideoState();\n this.videoCoordinator = null;\n }\n this.currentVideoStream = null;\n \n await this.cleanup();\n \n this.debugLog(`VijiCore destroyed (${this.instanceId})`);\n }\n\n /**\n * Validates that the core is ready for operations\n */\n private validateReady(): void {\n if (this.isDestroyed) {\n throw new VijiCoreError('Core instance has been destroyed', 'INSTANCE_DESTROYED');\n }\n \n if (!this.ready) {\n throw new VijiCoreError('Core is not ready', 'CORE_NOT_READY');\n }\n }\n\n /**\n * Validates the provided configuration\n */\n private validateConfig(config: VijiCoreConfig): void {\n if (!config.hostContainer) {\n throw new VijiCoreError('hostContainer is required', 'INVALID_CONFIG');\n }\n \n if (!config.sceneCode || typeof config.sceneCode !== 'string') {\n throw new VijiCoreError('sceneCode must be a non-empty string', 'INVALID_CONFIG');\n }\n \n if (config.frameRateMode !== undefined && config.frameRateMode !== 'full' && config.frameRateMode !== 'half') {\n throw new VijiCoreError('frameRateMode must be either \"full\" or \"half\"', 'INVALID_CONFIG');\n }\n }\n\n /**\n * Cleans up all resources\n */\n private async cleanup(): Promise<void> {\n try {\n // Destroy worker first to stop rendering\n if (this.workerManager) {\n this.workerManager.destroy();\n this.workerManager = null;\n }\n \n // Destroy IFrame\n if (this.iframeManager) {\n this.iframeManager.destroy();\n this.iframeManager = null;\n }\n \n this.isInitialized = false;\n this.isInitializing = false;\n } catch (error) {\n console.warn('Error during cleanup:', error);\n }\n }\n} ","// Main VijiCore class\r\nexport { VijiCore } from './VijiCore.js';\r\n\r\n// Public types and interfaces\r\nexport type {\r\n VijiCoreConfig,\r\n Resolution,\r\n CaptureFrameOptions,\r\n ParameterGroup,\r\n ParameterDefinition,\r\n ParameterConfig,\r\n AnalysisConfiguration,\r\n FrequencyBand,\r\n PerformanceStats,\r\n VijiAPI,\r\n AudioAPI,\r\n VideoAPI,\r\n FaceData,\r\n HandData,\r\n MouseAPI,\r\n KeyboardAPI,\r\n TouchAPI,\r\n ParameterAPI\r\n} from './types/index.js';\r\n\r\n// Error class\r\nexport { VijiCoreError } from './types/index.js';\r\n\r\n// Version information\r\nexport const VERSION = '0.2.13'; "],"names":["VijiWorker"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/types/index.ts","../src/iframe/IFrameManager.ts","../src/worker/WorkerManager.ts","../src/interaction/InteractionManager.ts","../src/audio/AudioSystem.ts","../src/video/VideoCoordinator.ts","../src/VijiCore.ts","../src/index.ts"],"sourcesContent":["// Core configuration types\nexport interface VijiCoreConfig {\n /** Container element where the scene will be rendered */\n hostContainer: HTMLElement;\n \n /** Artist scene code to execute */\n sceneCode: string;\n \n /** Frame rate mode - 'full' for every animation frame, 'half' for every second frame */\n frameRateMode?: FrameRateMode;\n \n /** Enable automatic performance optimization */\n autoOptimize?: boolean;\n \n /** Audio input stream */\n audioStream?: MediaStream;\n \n /** Video input stream */\n videoStream?: MediaStream;\n \n /** Audio analysis configuration */\n analysisConfig?: AnalysisConfiguration;\n \n /** Initial parameter values */\n parameters?: ParameterGroup[];\n \n /** Disable input processing (for preview instances) */\n noInputs?: boolean;\n \n /** Enable user interaction events */\n allowUserInteraction?: boolean;\n}\n\n// Capture frame options\nexport interface CaptureFrameOptions {\n /** MIME type for output, e.g., 'image/png', 'image/jpeg', 'image/webp' */\n type?: string;\n /**\n * Target resolution.\n * - number: scale factor relative to current canvas size (e.g., 0.5 = 50%)\n * - { width, height }: exact output size; if aspect ratio differs from canvas,\n * the source is center-cropped to match the target aspect ratio before scaling\n */\n resolution?: number | { width: number; height: number };\n}\n\n// Core capabilities state\nexport interface CoreCapabilities {\n /** Audio input is active and connected */\n hasAudio: boolean;\n \n /** Video input is active and connected */\n hasVideo: boolean;\n \n /** User interactions (mouse, touch, keyboard) are enabled */\n hasInteraction: boolean;\n \n /** General parameters are always available */\n hasGeneral: boolean;\n}\n\n// Resolution types\nexport type Resolution = { width: number; height: number; }\n\n// Parameter category system\nexport type ParameterCategory = 'audio' | 'video' | 'interaction' | 'general';\n\n// Enhanced parameter system types for Phase 2\nexport interface ParameterGroup {\n groupName: string;\n category?: ParameterCategory;\n description?: string;\n collapsed?: boolean;\n order?: number;\n parameters: Record<string, ParameterDefinition>;\n}\n\nexport interface ParameterDefinition {\n type: 'slider' | 'color' | 'toggle' | 'select' | 'text' | 'number' | 'image';\n defaultValue: any;\n label?: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n config?: ParameterConfig;\n // Validation function\n validate?: (value: any) => boolean;\n}\n\nexport interface ParameterConfig {\n // For slider/number types\n min?: number;\n max?: number;\n step?: number;\n \n // For select type\n options?: string[] | number[];\n \n // For text type\n maxLength?: number;\n \n // UI configuration\n label?: string;\n description?: string;\n hidden?: boolean;\n \n // Advanced configuration\n precision?: number; // For number display precision\n}\n\n// Parameter object types (returned by helper functions)\nexport interface SliderParameter {\n value: number;\n min: number;\n max: number;\n step: number;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface ColorParameter {\n value: string;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface ToggleParameter {\n value: boolean;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface SelectParameter {\n value: string | number;\n options: string[] | number[];\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface TextParameter {\n value: string;\n maxLength?: number;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface NumberParameter {\n value: number;\n min: number;\n max: number;\n step: number;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\nexport interface ImageParameter {\n value: ImageBitmap | OffscreenCanvas | null;\n label: string;\n description?: string;\n group: string;\n category: ParameterCategory;\n}\n\n// Parameter helper function configurations\nexport interface SliderConfig {\n min?: number;\n max?: number;\n step?: number;\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface ColorConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface ToggleConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface SelectConfig {\n options: string[] | number[];\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface TextConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n maxLength?: number;\n}\n\nexport interface NumberConfig {\n min?: number;\n max?: number;\n step?: number;\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\nexport interface ImageConfig {\n label: string;\n description?: string;\n group?: string;\n category?: ParameterCategory;\n}\n\n// Parameter value types\nexport type ParameterValue = string | number | boolean | ImageBitmap | OffscreenCanvas | null;\n\n// Parameter update message data\nexport interface ParameterUpdateData {\n name: string;\n value: ParameterValue;\n}\n\nexport interface ParameterBatchUpdateData {\n updates: ParameterUpdateData[];\n}\n\n// Parameter definition extraction data\nexport interface ParameterDefinitionData {\n groups: ParameterGroup[];\n}\n\n// Audio analysis configuration\nexport interface AnalysisConfiguration {\n fftSize?: number;\n smoothing?: number;\n frequencyBands?: FrequencyBand[];\n beatDetection?: boolean;\n onsetDetection?: boolean;\n}\n\nexport interface FrequencyBand {\n name: string;\n min: number;\n max: number;\n}\n\n// Frame rate mode types\nexport type FrameRateMode = 'full' | 'half';\n\n// CV frame rate mode types (relative to scene processing rate)\nexport type CVFrameRateMode = 'full' | 'half' | 'quarter' | 'eighth';\n\n// Renderer type for P5.js support\nexport type RendererType = 'native' | 'p5' | 'shader';\n\nexport interface FrameRateInfo {\n mode: FrameRateMode;\n screenRefreshRate: number;\n effectiveRefreshRate: number;\n}\n\n// Performance monitoring\nexport interface PerformanceStats {\n frameTime: number;\n resolution: Resolution;\n scale: number;\n frameRate: FrameRateInfo;\n rendererType: RendererType;\n memoryUsage?: number;\n activeStreams?: number;\n parameterCount?: number;\n // CV Processing Stats (integrated)\n cv?: {\n activeFeatures: CVFeature[];\n processingTime: number; // average processing time in milliseconds\n targetFPS: number; // target CV FPS based on scene rate and CV rate mode\n actualFPS: number; // actual measured CV processing FPS\n isProcessing: boolean;\n };\n}\n\n// Communication message types\nexport interface Message {\n type: string;\n id: string;\n timestamp: number;\n data?: any;\n}\n\nexport interface HostToWorkerMessage extends Message {\n type:\n | 'init'\n | 'parameter-update'\n | 'parameter-batch-update'\n | 'stream-update'\n | 'performance-update'\n | 'capture-frame';\n}\n\nexport interface WorkerToHostMessage extends Message {\n type:\n | 'init-response'\n | 'ready'\n | 'parameters-defined'\n | 'parameter-validation-error'\n | 'error'\n | 'performance-warning'\n | 'capture-frame-result';\n}\n\n// Resource management types\nexport interface ResourceTracker {\n workers: Set<Worker>;\n iframes: Set<HTMLIFrameElement>;\n streams: Set<MediaStream>;\n contexts: Set<AudioContext | CanvasRenderingContext2D | WebGLRenderingContext>;\n}\n\n// Enhanced Artist API types (provided to artist code)\nexport interface VijiAPI {\n // Canvas and rendering\n canvas: OffscreenCanvas;\n ctx?: OffscreenCanvasRenderingContext2D;\n gl?: WebGL2RenderingContext;\n width: number;\n height: number;\n pixelRatio: number;\n \n // Timing\n time: number;\n deltaTime: number;\n frameCount: number;\n fps: number;\n \n // Audio (when available)\n audio: AudioAPI;\n \n // Video (when available) \n video: VideoAPI;\n \n // User interaction\n mouse: MouseAPI;\n keyboard: KeyboardAPI;\n touches: TouchAPI;\n \n // Parameter helper functions (return parameter objects)\n slider: (defaultValue: number, config: SliderConfig) => SliderParameter;\n color: (defaultValue: string, config: ColorConfig) => ColorParameter;\n toggle: (defaultValue: boolean, config: ToggleConfig) => ToggleParameter;\n select: (defaultValue: string | number, config: SelectConfig) => SelectParameter;\n text: (defaultValue: string, config: TextConfig) => TextParameter;\n number: (defaultValue: number, config: NumberConfig) => NumberParameter;\n image: (defaultValue: null, config: ImageConfig) => ImageParameter;\n \n // Utility methods\n useContext(type: '2d' | 'webgl'): OffscreenCanvasRenderingContext2D | WebGLRenderingContext | WebGL2RenderingContext | null;\n}\n\n// Audio API\nexport interface AudioAPI {\n isConnected: boolean;\n volume: {\n rms: number;\n peak: number;\n };\n beat?: {\n isKick: boolean;\n confidence: number;\n };\n bands: Record<string, number>;\n getFrequencyData: () => Uint8Array;\n}\n\n// Video API\nexport interface VideoAPI {\n isConnected: boolean;\n currentFrame: OffscreenCanvas | null;\n frameWidth: number;\n frameHeight: number;\n frameRate: number;\n getFrameData: () => ImageData | null;\n \n // CV Results (automatically cleaned up when features disabled)\n faces: FaceData[];\n hands: HandData[];\n pose: PoseData | null;\n segmentation: SegmentationData | null;\n \n // CV Control Interface (activation only)\n cv: {\n enableFaceDetection(enabled: boolean): Promise<void>;\n enableFaceMesh(enabled: boolean): Promise<void>;\n enableHandTracking(enabled: boolean): Promise<void>;\n enablePoseDetection(enabled: boolean): Promise<void>;\n enableBodySegmentation(enabled: boolean): Promise<void>;\n getActiveFeatures(): CVFeature[];\n isProcessing(): boolean;\n };\n}\n\n// CV Feature Types\nexport type CVFeature = 'faceDetection' | 'faceMesh' | 'handTracking' | 'poseDetection' | 'bodySegmentation';\n\n// Enhanced Face Data with comprehensive landmarks and expressions\nexport interface FaceData {\n id: number;\n bounds: { x: number; y: number; width: number; height: number };\n confidence: number;\n landmarks?: { x: number; y: number; z?: number }[]; // 468 points for mesh, 6 points for basic\n expressions: {\n neutral: number;\n happy: number;\n sad: number;\n angry: number;\n surprised: number;\n disgusted: number;\n fearful: number;\n };\n headPose: {\n pitch: number; // Up/down rotation (-90 to 90 degrees)\n yaw: number; // Left/right rotation (-90 to 90 degrees)\n roll: number; // Tilt rotation (-180 to 180 degrees)\n };\n}\n\n// Enhanced Hand Data with comprehensive landmarks and gesture recognition\nexport interface HandData {\n id: number;\n handedness: 'left' | 'right';\n confidence: number;\n bounds: { x: number; y: number; width: number; height: number };\n landmarks: { x: number; y: number; z: number }[]; // 21 points\n \n // Palm and finger positions\n palm: { x: number; y: number; z: number };\n fingers: {\n thumb: { tip: {x: number; y: number; z: number}; extended: boolean };\n index: { tip: {x: number; y: number; z: number}; extended: boolean };\n middle: { tip: {x: number; y: number; z: number}; extended: boolean };\n ring: { tip: {x: number; y: number; z: number}; extended: boolean };\n pinky: { tip: {x: number; y: number; z: number}; extended: boolean };\n };\n \n // Recognized gestures with confidence scores\n gestures: {\n fist: number; // 0-1 confidence\n openPalm: number; // 0-1 confidence\n peace: number; // 0-1 confidence\n thumbsUp: number; // 0-1 confidence\n pointing: number; // 0-1 confidence\n };\n}\n\n// Body Pose Data with 33-point BlazePose landmarks\nexport interface PoseData {\n confidence: number;\n landmarks: { x: number; y: number; z: number; visibility: number }[]; // 33 points\n \n // Key body parts for easy access\n face: { x: number; y: number }[];\n torso: { x: number; y: number }[];\n leftArm: { x: number; y: number }[];\n rightArm: { x: number; y: number }[];\n leftLeg: { x: number; y: number }[];\n rightLeg: { x: number; y: number }[];\n}\n\n// Body Segmentation Data for background replacement effects\nexport interface SegmentationData {\n mask: Uint8Array; // Per-pixel segmentation mask (0=background, 1=person)\n width: number; // Mask width in pixels\n height: number; // Mask height in pixels\n}\n\n// CV Processing Statistics\nexport interface CVProcessingStats {\n activeFeatures: CVFeature[];\n processingTime: number; // average processing time in milliseconds\n effectiveFPS: number; // target CV FPS based on scene rate and CV rate mode\n actualFPS: number; // actual measured CV processing FPS\n isProcessing: boolean;\n}\n\nexport interface CVWorkerInitMessage {\n type: 'init';\n}\n\nexport interface CVWorkerConfigMessage {\n type: 'config';\n features: CVFeature[];\n}\n\nexport interface CVWorkerProcessMessage {\n type: 'process';\n bitmap: ImageBitmap;\n timestamp: number;\n features: CVFeature[];\n}\n\nexport interface CVWorkerResultPayload {\n faces?: FaceData[];\n hands?: HandData[];\n pose?: PoseData | null;\n segmentation?: SegmentationData | null;\n timestamp: number;\n}\n\nexport interface CVWorkerResultMessage {\n type: 'result';\n success: boolean;\n data?: CVWorkerResultPayload;\n error?: string;\n}\n\n// Input APIs - Phase 7 Implementation\nexport interface MouseAPI {\n // Position (canvas coordinates)\n x: number;\n y: number;\n \n // Canvas bounds\n isInCanvas: boolean;\n \n // Button states\n isPressed: boolean;\n leftButton: boolean;\n rightButton: boolean;\n middleButton: boolean;\n \n // Movement\n velocity: { x: number; y: number };\n deltaX: number;\n deltaY: number;\n \n // Scroll wheel\n wheelDelta: number;\n wheelX: number;\n wheelY: number;\n \n // Events (frame-based)\n wasPressed: boolean;\n wasReleased: boolean;\n wasMoved: boolean;\n}\n\nexport interface KeyboardAPI {\n // Key state queries\n isPressed(key: string): boolean;\n wasPressed(key: string): boolean;\n wasReleased(key: string): boolean;\n \n // Active state\n activeKeys: Set<string>;\n pressedThisFrame: Set<string>;\n releasedThisFrame: Set<string>;\n \n // Recent activity\n lastKeyPressed: string;\n lastKeyReleased: string;\n \n // Modifier keys\n shift: boolean;\n ctrl: boolean;\n alt: boolean;\n meta: boolean;\n}\n\nexport interface TouchPoint {\n id: number;\n x: number;\n y: number;\n pressure: number;\n radius: number;\n radiusX: number;\n radiusY: number;\n rotationAngle: number;\n force: number;\n \n // Movement\n deltaX: number;\n deltaY: number;\n velocity: { x: number; y: number };\n \n // Lifecycle\n isNew: boolean;\n isActive: boolean;\n isEnding: boolean;\n}\n\nexport interface TouchAPI {\n // Current touches\n points: TouchPoint[];\n count: number;\n \n // Touch events\n started: TouchPoint[];\n moved: TouchPoint[];\n ended: TouchPoint[];\n \n // Convenience accessors\n primary: TouchPoint | null;\n \n // Gesture detection\n gestures: TouchGestureAPI;\n}\n\nexport interface TouchGestureAPI {\n // Gesture states\n isPinching: boolean;\n isRotating: boolean;\n isPanning: boolean;\n isTapping: boolean;\n \n // Gesture values\n pinchScale: number;\n pinchDelta: number;\n rotationAngle: number;\n rotationDelta: number;\n panDelta: { x: number; y: number };\n \n // Tap detection\n tapCount: number;\n lastTapTime: number;\n tapPosition: { x: number; y: number } | null;\n}\n\n// Enhanced Parameter API for Phase 2\nexport interface ParameterAPI {\n // Define parameters (called once outside render loop)\n define(groups: ParameterGroup[]): void;\n \n // Proxy access to parameter values (fast render-time access)\n [key: string]: any;\n}\n\n// Error types\nexport class VijiCoreError extends Error {\n constructor(\n message: string,\n public code: string,\n public context?: any\n ) {\n super(message);\n this.name = 'VijiCoreError';\n }\n} ","import { Resolution, VijiCoreError } from '../types/index.js';\n\n/**\n * Manages the secure IFrame that contains the canvas for scene rendering.\n * Provides complete isolation while allowing controlled canvas access.\n * Enhanced with Phase 7 interaction support.\n */\nexport class IFrameManager {\n private iframe: HTMLIFrameElement | null = null;\n private canvas: HTMLCanvasElement | null = null;\n private offscreenCanvas: OffscreenCanvas | null = null;\n private isInitialized = false;\n private scale: number = 1.0;\n \n // Debug logging control\n private debugMode = false;\n\n /**\n * Enable or disable debug logging\n */\n setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n }\n\n /**\n * Debug logging helper\n */\n private debugLog(message: string, ...args: any[]): void {\n if (this.debugMode) {\n console.log(message, ...args);\n }\n }\n\n // Phase 7: Interaction event listeners\n private interactionListeners = new Map<string, (data: any) => void>();\n private isInteractionEnabled = true;\n\n // Mouse canvas tracking\n private isMouseInCanvas = false;\n\n // Touch tracking for gesture recognition\n private activeTouchIds = new Set<number>();\n\n constructor(\n private hostContainer: HTMLElement,\n ) {}\n\n /**\n * Creates a secure IFrame with proper sandbox attributes\n */\n async createSecureIFrame(): Promise<HTMLIFrameElement> {\n try {\n // Create IFrame with security sandbox\n const iframe = document.createElement('iframe');\n \n // Security: Sandbox with controlled permissions\n // Note: allow-same-origin is required for canvas access but limits sandboxing\n // In future phases, consider message-passing for better security\n iframe.sandbox.add('allow-scripts');\n iframe.sandbox.add('allow-same-origin'); // Required for canvas/WebGL access\n \n // Styling: Full container size\n iframe.style.width = '100%';\n iframe.style.height = '100%';\n iframe.style.border = 'none';\n iframe.style.display = 'block';\n \n // Generate secure IFrame content\n const iframeContent = this.generateIFrameHTML();\n const blob = new Blob([iframeContent], { type: 'text/html' });\n iframe.src = URL.createObjectURL(blob);\n \n // Mount to container\n this.hostContainer.appendChild(iframe);\n \n // Wait for IFrame to load and document to be ready\n await new Promise<void>((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(new VijiCoreError('IFrame load timeout', 'IFRAME_TIMEOUT'));\n }, 5000);\n \n const checkReady = () => {\n if (iframe.contentDocument && iframe.contentDocument.readyState === 'complete') {\n clearTimeout(timeout);\n resolve();\n }\n };\n \n iframe.onload = () => {\n // Double-check document is ready\n if (iframe.contentDocument?.readyState === 'complete') {\n clearTimeout(timeout);\n resolve();\n } else {\n // Wait a bit more for document to be ready\n iframe.contentDocument?.addEventListener('DOMContentLoaded', checkReady);\n // Fallback check\n setTimeout(checkReady, 100);\n }\n };\n \n iframe.onerror = () => {\n clearTimeout(timeout);\n reject(new VijiCoreError('IFrame load failed', 'IFRAME_LOAD_ERROR'));\n };\n });\n \n this.iframe = iframe;\n return iframe;\n } catch (error) {\n throw new VijiCoreError(\n `Failed to create secure IFrame: ${error}`,\n 'IFRAME_CREATION_ERROR',\n { error }\n );\n }\n }\n\n /**\n * Creates canvas inside the IFrame and returns OffscreenCanvas for WebWorker\n */\n async createCanvas(): Promise<OffscreenCanvas> {\n if (!this.iframe?.contentWindow) {\n throw new VijiCoreError('IFrame not ready for canvas creation', 'IFRAME_NOT_READY');\n }\n\n try {\n // Wait for iframe document to be accessible with retry logic\n const iframeDoc = await this.waitForIFrameDocument();\n \n // Create canvas in IFrame\n const canvas = iframeDoc.createElement('canvas');\n canvas.id = 'viji-canvas';\n this.canvas = canvas;\n \n // Set canvas size based on resolution\n const { width, height } = this.calculateCanvasSize();\n canvas.width = width * this.scale;\n canvas.height = height * this.scale;\n \n // Styling: Full container size\n canvas.style.width = '100%';\n canvas.style.height = '100%';\n canvas.style.display = 'block';\n \n // Add to IFrame body\n const body = iframeDoc.querySelector('body');\n if (!body) {\n throw new VijiCoreError('IFrame body not found', 'IFRAME_BODY_ERROR');\n }\n \n body.appendChild(canvas);\n \n // Phase 7: Set up interaction event listeners\n this.setupInteractionListeners(canvas, iframeDoc);\n \n // Create OffscreenCanvas for WebWorker\n const offscreenCanvas = canvas.transferControlToOffscreen();\n this.offscreenCanvas = offscreenCanvas;\n this.isInitialized = true;\n \n return offscreenCanvas;\n } catch (error) {\n throw new VijiCoreError(\n `Failed to create canvas: ${error}`,\n 'CANVAS_CREATION_ERROR',\n { error }\n );\n }\n }\n\n /**\n * Waits for iframe document to be accessible with retry logic\n */\n private async waitForIFrameDocument(): Promise<Document> {\n const maxRetries = 15;\n const retryDelay = 150;\n \n for (let i = 0; i < maxRetries; i++) {\n try {\n const iframeDoc = this.iframe?.contentDocument;\n \n // Check multiple readiness indicators\n if (iframeDoc && \n (iframeDoc.readyState === 'complete' || iframeDoc.readyState === 'interactive') &&\n iframeDoc.body &&\n this.iframe?.contentWindow) {\n \n this.debugLog(`IFrame document ready after ${i + 1} attempts`);\n return iframeDoc;\n }\n \n this.debugLog(`IFrame not ready attempt ${i + 1}/${maxRetries}:`, {\n hasDocument: !!iframeDoc,\n readyState: iframeDoc?.readyState,\n hasBody: !!iframeDoc?.body,\n hasWindow: !!this.iframe?.contentWindow\n });\n \n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n } catch (error) {\n this.debugLog(`IFrame access error attempt ${i + 1}/${maxRetries}:`, error);\n // Security or access error - wait and retry\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n }\n }\n \n throw new VijiCoreError('Cannot access IFrame document after retries', 'IFRAME_ACCESS_ERROR');\n }\n\n /**\n * Updates canvas resolution setting (scaling handled in worker)\n */\n updateScale(scale: number): { width: number; height: number } {\n this.scale = scale;\n return this.getEffectiveResolution();\n }\n\n /**\n * Gets current scale\n */\n getScale(): number {\n return this.scale;\n }\n\n /**\n * Destroys the IFrame and cleans up resources\n */\n destroy(): void {\n try {\n if (this.iframe) {\n // Revoke blob URL to prevent memory leaks\n if (this.iframe.src.startsWith('blob:')) {\n URL.revokeObjectURL(this.iframe.src);\n }\n \n // Remove from DOM\n this.iframe.remove();\n this.iframe = null;\n }\n \n this.offscreenCanvas = null;\n this.isInitialized = false;\n } catch (error) {\n console.warn('Error during IFrame cleanup:', error);\n }\n }\n\n /**\n * Checks if IFrame is ready for use\n */\n get ready(): boolean {\n return this.isInitialized && \n this.iframe !== null && \n this.offscreenCanvas !== null;\n }\n\n /**\n * Gets the IFrame element\n */\n get element(): HTMLIFrameElement | null {\n return this.iframe;\n }\n\n /**\n * Generates the HTML content for the secure IFrame\n */\n private generateIFrameHTML(): string {\n return `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>Viji Scene Container</title>\n <style>\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n \n html, body {\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: #000;\n }\n \n canvas {\n display: block;\n width: 100%;\n height: 100%;\n image-rendering: auto;\n }\n </style>\n</head>\n<body>\n <!-- Canvas will be created dynamically -->\n</body>\n</html>\n `.trim();\n }\n\n /**\n * Calculates canvas dimensions based on container size\n * Canvas internal size starts as container size, then worker updates it based on resolution\n */\n private calculateCanvasSize(): { width: number; height: number } {\n // Use full container size for initial canvas resolution\n // Worker will update canvas.width/height based on effective resolution messages\n const containerRect = this.hostContainer.getBoundingClientRect();\n \n return {\n width: Math.round(containerRect.width),\n height: Math.round(containerRect.height)\n };\n }\n\n /**\n * Gets the effective resolution that should be used for rendering\n */\n getEffectiveResolution(): Resolution {\n const containerRect = this.hostContainer.getBoundingClientRect();\n const containerWidth = Math.round(containerRect.width);\n const containerHeight = Math.round(containerRect.height);\n\n const scale = Math.max(0.1, Math.min(1.0, this.scale));\n return {\n width: Math.round(containerWidth * scale),\n height: Math.round(containerHeight * scale),\n };\n }\n\n // Phase 7: Interaction Management Methods\n\n /**\n * Sets up interaction event listeners on the canvas and document\n */\n private setupInteractionListeners(canvas: HTMLCanvasElement, iframeDoc: Document): void {\n if (!this.isInteractionEnabled) return;\n\n // Make canvas focusable for keyboard events\n canvas.tabIndex = 0;\n canvas.style.outline = 'none';\n\n // Mouse events\n canvas.addEventListener('mousedown', this.handleMouseEvent.bind(this), { passive: false });\n canvas.addEventListener('mousemove', this.handleMouseEvent.bind(this), { passive: false });\n canvas.addEventListener('mouseup', this.handleMouseEvent.bind(this), { passive: false });\n canvas.addEventListener('mouseenter', this.handleMouseEnter.bind(this), { passive: false });\n canvas.addEventListener('mouseleave', this.handleMouseLeave.bind(this), { passive: false });\n canvas.addEventListener('wheel', this.handleWheelEvent.bind(this), { passive: false });\n canvas.addEventListener('contextmenu', (e) => e.preventDefault()); // Disable right-click menu\n\n // Keyboard events (on document to capture all keys)\n iframeDoc.addEventListener('keydown', this.handleKeyboardEvent.bind(this), { passive: false });\n iframeDoc.addEventListener('keyup', this.handleKeyboardEvent.bind(this), { passive: false });\n\n // Touch events\n canvas.addEventListener('touchstart', this.handleTouchEvent.bind(this), { passive: false });\n canvas.addEventListener('touchmove', this.handleTouchEvent.bind(this), { passive: false });\n canvas.addEventListener('touchend', this.handleTouchEvent.bind(this), { passive: false });\n canvas.addEventListener('touchcancel', this.handleTouchEvent.bind(this), { passive: false });\n\n // Focus management\n canvas.addEventListener('mousedown', () => canvas.focus());\n canvas.addEventListener('touchstart', () => canvas.focus());\n }\n\n /**\n * Handles mouse events and transforms coordinates\n */\n private handleMouseEvent(event: MouseEvent): void {\n if (!this.canvas || !this.isInteractionEnabled) return;\n\n event.preventDefault();\n\n const rect = this.canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (this.canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (this.canvas.height / rect.height);\n\n // Calculate movement deltas\n const deltaX = event.movementX || 0;\n const deltaY = event.movementY || 0;\n\n const data = {\n x,\n y,\n buttons: event.buttons,\n deltaX,\n deltaY,\n wheelDeltaX: 0,\n wheelDeltaY: 0,\n isInCanvas: this.isMouseInCanvas,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('mouse-update', data);\n }\n\n /**\n * Handles mouse enter events\n */\n private handleMouseEnter(event: MouseEvent): void {\n if (!this.isInteractionEnabled) return;\n \n this.isMouseInCanvas = true;\n \n // Trigger a mouse update to immediately reflect the isInCanvas state\n this.handleMouseEvent(event);\n }\n\n /**\n * Handles mouse leave events\n */\n private handleMouseLeave(event: MouseEvent): void {\n if (!this.isInteractionEnabled) return;\n \n this.isMouseInCanvas = false;\n \n // Trigger a mouse update to immediately reflect the isInCanvas state\n this.handleMouseEvent(event);\n }\n\n /**\n * Handles wheel events\n */\n private handleWheelEvent(event: WheelEvent): void {\n if (!this.canvas || !this.isInteractionEnabled) return;\n\n event.preventDefault();\n\n const rect = this.canvas.getBoundingClientRect();\n const x = (event.clientX - rect.left) * (this.canvas.width / rect.width);\n const y = (event.clientY - rect.top) * (this.canvas.height / rect.height);\n\n const data = {\n x,\n y,\n buttons: event.buttons,\n deltaX: 0,\n deltaY: 0,\n wheelDeltaX: event.deltaX,\n wheelDeltaY: event.deltaY,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('mouse-update', data);\n }\n\n /**\n * Handles keyboard events\n */\n private handleKeyboardEvent(event: KeyboardEvent): void {\n if (!this.isInteractionEnabled) return;\n\n // Allow some default behaviors for accessibility/usability\n const allowedKeys = ['Tab', 'F1', 'F2', 'F3', 'F4', 'F5', 'F11', 'F12'];\n if (!allowedKeys.includes(event.key)) {\n event.preventDefault();\n }\n\n const data = {\n type: event.type as 'keydown' | 'keyup',\n key: event.key,\n code: event.code,\n shiftKey: event.shiftKey,\n ctrlKey: event.ctrlKey,\n altKey: event.altKey,\n metaKey: event.metaKey,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('keyboard-update', data);\n }\n\n /**\n * Handles touch events and tracks multi-touch\n */\n private handleTouchEvent(event: TouchEvent): void {\n if (!this.canvas || !this.isInteractionEnabled) return;\n\n event.preventDefault();\n\n const rect = this.canvas.getBoundingClientRect();\n const scaleX = this.canvas.width / rect.width;\n const scaleY = this.canvas.height / rect.height;\n\n // Convert TouchList to array with transformed coordinates\n const touches = Array.from(event.touches).map(touch => ({\n identifier: touch.identifier,\n clientX: (touch.clientX - rect.left) * scaleX,\n clientY: (touch.clientY - rect.top) * scaleY,\n pressure: (touch as any).pressure || 0,\n radiusX: (touch as any).radiusX || 10,\n radiusY: (touch as any).radiusY || 10,\n rotationAngle: (touch as any).rotationAngle || 0,\n force: (touch as any).force || (touch as any).pressure || 0\n }));\n\n // Track active touch IDs for gesture recognition\n if (event.type === 'touchstart') {\n for (const touch of event.changedTouches) {\n this.activeTouchIds.add(touch.identifier);\n }\n } else if (event.type === 'touchend' || event.type === 'touchcancel') {\n for (const touch of event.changedTouches) {\n this.activeTouchIds.delete(touch.identifier);\n }\n }\n\n const data = {\n type: event.type as 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel',\n touches,\n timestamp: performance.now()\n };\n\n this.emitInteractionEvent('touch-update', data);\n }\n\n /**\n * Emits an interaction event to registered listeners\n */\n private emitInteractionEvent(eventType: string, data: any): void {\n const listener = this.interactionListeners.get(eventType);\n if (listener) {\n listener(data);\n }\n }\n\n /**\n * Registers an interaction event listener\n */\n onInteractionEvent(eventType: string, listener: (data: any) => void): void {\n this.interactionListeners.set(eventType, listener);\n }\n\n /**\n * Removes an interaction event listener\n */\n offInteractionEvent(eventType: string): void {\n this.interactionListeners.delete(eventType);\n }\n\n /**\n * Enables or disables interaction event capture\n */\n setInteractionEnabled(enabled: boolean): void {\n this.isInteractionEnabled = enabled;\n }\n\n /**\n * Gets the canvas element (for coordinate calculations)\n */\n getCanvas(): HTMLCanvasElement | null {\n return this.canvas;\n }\n} ","import { VijiCoreError, HostToWorkerMessage, WorkerToHostMessage } from '../types/index.js';\nimport VijiWorker from './viji.worker.ts?worker&module';\n\n/**\n * Manages the WebWorker that executes artist scene code.\n * Provides secure sandboxed execution with controlled API access.\n */\nexport class WorkerManager {\n private worker: Worker | null = null;\n private messageId = 0;\n private pendingMessages = new Map<string, {\n resolve: (value: any) => void;\n reject: (error: any) => void;\n timeout: ReturnType<typeof setTimeout>;\n }>();\n private messageHandlers = new Map<string, (data: any) => void>();\n private isInitialized = false;\n\n constructor(\n private sceneCode: string,\n private offscreenCanvas: OffscreenCanvas\n ) {}\n\n /**\n * Creates and initializes the WebWorker with artist code\n */\n async createWorker(): Promise<void> {\n try {\n // Create worker using Vite's worker import (hashed asset, correct MIME)\n this.worker = new VijiWorker();\n \n // Setup message handling\n this.setupMessageHandling();\n \n // Transfer OffscreenCanvas to worker and wait for init response\n // IMPORTANT: Canvas must be initialized BEFORE scene code to avoid race conditions\n await this.initializeWorker();\n \n // Send scene code to worker (after canvas is ready)\n this.postMessage('set-scene-code', { sceneCode: this.sceneCode });\n \n this.isInitialized = true;\n } catch (error) {\n throw new VijiCoreError(\n `Failed to create worker: ${error}`,\n 'WORKER_CREATION_ERROR',\n { error }\n );\n }\n }\n\n /**\n * Sends a message to the worker and returns a promise for the response\n */\n async sendMessage(type: string, data?: any, timeout = 5000): Promise<any> {\n if (!this.worker) {\n throw new VijiCoreError('Worker not initialized', 'WORKER_NOT_READY');\n }\n\n const id = `msg_${++this.messageId}`;\n const message: HostToWorkerMessage = {\n type: type as any,\n id,\n timestamp: Date.now(),\n data\n };\n\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingMessages.delete(id);\n reject(new VijiCoreError(`Message timeout: ${type}`, 'MESSAGE_TIMEOUT'));\n }, timeout);\n\n this.pendingMessages.set(id, {\n resolve,\n reject,\n timeout: timeoutId\n });\n\n this.worker!.postMessage(message);\n });\n }\n\n /**\n * Sends a message without waiting for response (fire and forget)\n */\n postMessage(type: string, data?: any): void;\n postMessage(type: string, data: any, transfer: Transferable[]): void;\n postMessage(type: string, data?: any, transfer?: Transferable[]): void {\n if (!this.worker) {\n console.warn('Attempted to post message to uninitialized worker');\n return;\n }\n\n const message: HostToWorkerMessage = {\n type: type as any,\n id: `fire_${++this.messageId}`,\n timestamp: Date.now(),\n data\n };\n\n if (transfer && transfer.length > 0) {\n this.worker.postMessage(message, transfer);\n } else {\n this.worker.postMessage(message);\n }\n }\n\n\n /**\n * Registers a handler for worker messages\n */\n onMessage(type: string, handler: (data: any) => void): void {\n this.messageHandlers.set(type, handler);\n }\n\n /**\n * Removes a message handler\n */\n offMessage(type: string): void {\n this.messageHandlers.delete(type);\n }\n\n /**\n * Terminates the worker and cleans up resources\n */\n destroy(): void {\n try {\n // Clear pending messages\n this.pendingMessages.forEach(({ timeout, reject }) => {\n clearTimeout(timeout);\n reject(new VijiCoreError('Worker destroyed', 'WORKER_DESTROYED'));\n });\n this.pendingMessages.clear();\n\n // Clear message handlers\n this.messageHandlers.clear();\n\n // Terminate worker\n if (this.worker) {\n this.worker.terminate();\n this.worker = null;\n }\n\n this.isInitialized = false;\n } catch (error) {\n console.warn('Error during worker cleanup:', error);\n }\n }\n\n /**\n * Checks if worker is ready for use\n */\n get ready(): boolean {\n return this.isInitialized && this.worker !== null;\n }\n\n /**\n * Gets the worker instance\n */\n get instance(): Worker | null {\n return this.worker;\n }\n\n /**\n * Sets up message handling for worker communication\n */\n private setupMessageHandling(): void {\n if (!this.worker) return;\n\n this.worker.onmessage = (event) => {\n const message: WorkerToHostMessage = event.data;\n \n // Handle pending message responses\n if (this.pendingMessages.has(message.id)) {\n const pending = this.pendingMessages.get(message.id)!;\n clearTimeout(pending.timeout);\n this.pendingMessages.delete(message.id);\n \n if (message.type === 'error') {\n pending.reject(new VijiCoreError(\n message.data?.message || 'Worker error',\n message.data?.code || 'WORKER_ERROR',\n message.data\n ));\n } else {\n pending.resolve(message.data);\n }\n return;\n }\n\n // Handle event messages\n const handler = this.messageHandlers.get(message.type);\n if (handler) {\n try {\n handler(message.data);\n } catch (error) {\n console.error(`Error in message handler for ${message.type}:`, error);\n }\n }\n };\n\n this.worker.onerror = (error) => {\n console.error('Worker error:', error);\n \n // Reject all pending messages\n this.pendingMessages.forEach(({ timeout, reject }) => {\n clearTimeout(timeout);\n reject(new VijiCoreError('Worker error', 'WORKER_ERROR', error));\n });\n this.pendingMessages.clear();\n };\n }\n\n /**\n * Initializes the worker with canvas and basic setup\n * Waits for init-response message (worker will also send separate 'ready' event)\n */\n private async initializeWorker(): Promise<void> {\n if (!this.worker) {\n throw new VijiCoreError('Worker not created', 'WORKER_NOT_CREATED');\n }\n\n // Create message for canvas transfer\n const id = `msg_${++this.messageId}`;\n const message: HostToWorkerMessage = {\n type: 'init',\n id,\n timestamp: Date.now(),\n data: {\n canvas: this.offscreenCanvas\n }\n };\n\n // Transfer OffscreenCanvas (not clone) - this is critical!\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n this.pendingMessages.delete(id);\n reject(new VijiCoreError('Canvas transfer timeout', 'CANVAS_TRANSFER_TIMEOUT'));\n }, 10000);\n\n this.pendingMessages.set(id, {\n resolve,\n reject,\n timeout: timeoutId\n });\n\n // Transfer the canvas using the transferable objects parameter\n this.worker!.postMessage(message, [this.offscreenCanvas]);\n });\n }\n\n\n} ","import { MouseAPI, KeyboardAPI, TouchAPI, TouchPoint } from '../types/index.js';\n\n/**\n * Manages user interaction state and provides APIs for mouse, keyboard, and touch input.\n * Handles event processing, state tracking, and gesture recognition for Phase 7.\n */\nexport class InteractionManager {\n // Mouse state\n private mouseState: MouseAPI = {\n x: 0,\n y: 0,\n isInCanvas: false,\n isPressed: false,\n leftButton: false,\n rightButton: false,\n middleButton: false,\n velocity: { x: 0, y: 0 },\n deltaX: 0,\n deltaY: 0,\n wheelDelta: 0,\n wheelX: 0,\n wheelY: 0,\n wasPressed: false,\n wasReleased: false,\n wasMoved: false\n };\n\n // Mouse velocity tracking\n private mouseVelocityHistory: Array<{ x: number; y: number; time: number }> = [];\n\n // Keyboard state\n private keyboardState: KeyboardAPI = {\n isPressed: (key: string) => this.activeKeys.has(key.toLowerCase()),\n wasPressed: (key: string) => this.pressedThisFrame.has(key.toLowerCase()),\n wasReleased: (key: string) => this.releasedThisFrame.has(key.toLowerCase()),\n activeKeys: new Set<string>(),\n pressedThisFrame: new Set<string>(),\n releasedThisFrame: new Set<string>(),\n lastKeyPressed: '',\n lastKeyReleased: '',\n shift: false,\n ctrl: false,\n alt: false,\n meta: false\n };\n\n private activeKeys = new Set<string>();\n private pressedThisFrame = new Set<string>();\n private releasedThisFrame = new Set<string>();\n\n // Touch state\n private touchState: TouchAPI = {\n points: [],\n count: 0,\n started: [],\n moved: [],\n ended: [],\n primary: null,\n gestures: {\n isPinching: false,\n isRotating: false,\n isPanning: false,\n isTapping: false,\n pinchScale: 1,\n pinchDelta: 0,\n rotationAngle: 0,\n rotationDelta: 0,\n panDelta: { x: 0, y: 0 },\n tapCount: 0,\n lastTapTime: 0,\n tapPosition: null\n }\n };\n\n private activeTouches = new Map<number, TouchPoint>();\n private gestureState = {\n initialDistance: 0,\n initialAngle: 0,\n lastPinchScale: 1,\n lastRotationAngle: 0,\n panStartPosition: { x: 0, y: 0 },\n tapStartTime: 0,\n tapCount: 0,\n lastTapTime: 0\n };\n\n constructor() {}\n\n /**\n * Processes mouse update from the host\n */\n updateMouse(data: {\n x: number;\n y: number;\n buttons: number;\n deltaX: number;\n deltaY: number;\n wheelDeltaX: number;\n wheelDeltaY: number;\n isInCanvas?: boolean;\n timestamp: number;\n }): void {\n // Convert coordinates to canvas space\n const canvasX = data.x;\n const canvasY = data.y;\n\n // Calculate deltas\n const deltaX = canvasX - this.mouseState.x;\n const deltaY = canvasY - this.mouseState.y;\n\n // Update velocity with smoothing\n this.updateMouseVelocity(deltaX, deltaY, data.timestamp);\n\n // Detect button state changes\n const prevPressed = this.mouseState.isPressed;\n const currentPressed = data.buttons > 0;\n\n this.mouseState.wasPressed = !prevPressed && currentPressed;\n this.mouseState.wasReleased = prevPressed && !currentPressed;\n this.mouseState.wasMoved = deltaX !== 0 || deltaY !== 0;\n\n // Update mouse state\n this.mouseState.x = canvasX;\n this.mouseState.y = canvasY;\n this.mouseState.deltaX = deltaX;\n this.mouseState.deltaY = deltaY;\n this.mouseState.isPressed = currentPressed;\n this.mouseState.leftButton = (data.buttons & 1) !== 0;\n this.mouseState.rightButton = (data.buttons & 2) !== 0;\n this.mouseState.middleButton = (data.buttons & 4) !== 0;\n this.mouseState.isInCanvas = data.isInCanvas !== undefined ? data.isInCanvas : true;\n\n // Update wheel\n this.mouseState.wheelDelta = data.wheelDeltaY;\n this.mouseState.wheelX = data.wheelDeltaX;\n this.mouseState.wheelY = data.wheelDeltaY;\n }\n\n /**\n * Updates mouse velocity with smoothing\n */\n private updateMouseVelocity(deltaX: number, deltaY: number, timestamp: number): void {\n // Add current velocity sample\n this.mouseVelocityHistory.push({ x: deltaX, y: deltaY, time: timestamp });\n\n // Keep only recent samples (last 100ms)\n const cutoff = timestamp - 100;\n this.mouseVelocityHistory = this.mouseVelocityHistory.filter(sample => sample.time > cutoff);\n\n // Calculate smoothed velocity\n if (this.mouseVelocityHistory.length > 1) {\n const recent = this.mouseVelocityHistory.slice(-5); // Last 5 samples\n const avgX = recent.reduce((sum, s) => sum + s.x, 0) / recent.length;\n const avgY = recent.reduce((sum, s) => sum + s.y, 0) / recent.length;\n \n this.mouseState.velocity.x = avgX;\n this.mouseState.velocity.y = avgY;\n } else {\n this.mouseState.velocity.x = deltaX;\n this.mouseState.velocity.y = deltaY;\n }\n }\n\n /**\n * Processes keyboard update from the host\n */\n updateKeyboard(data: {\n type: 'keydown' | 'keyup';\n key: string;\n code: string;\n shiftKey: boolean;\n ctrlKey: boolean;\n altKey: boolean;\n metaKey: boolean;\n timestamp: number;\n }): void {\n const key = data.key.toLowerCase();\n\n if (data.type === 'keydown') {\n if (!this.activeKeys.has(key)) {\n this.activeKeys.add(key);\n this.pressedThisFrame.add(key);\n this.keyboardState.lastKeyPressed = data.key;\n }\n } else if (data.type === 'keyup') {\n this.activeKeys.delete(key);\n this.releasedThisFrame.add(key);\n this.keyboardState.lastKeyReleased = data.key;\n }\n\n // Update modifier keys\n this.keyboardState.shift = data.shiftKey;\n this.keyboardState.ctrl = data.ctrlKey;\n this.keyboardState.alt = data.altKey;\n this.keyboardState.meta = data.metaKey;\n }\n\n /**\n * Processes touch update from the host\n */\n updateTouch(data: {\n type: 'touchstart' | 'touchmove' | 'touchend' | 'touchcancel';\n touches: Array<{\n identifier: number;\n clientX: number;\n clientY: number;\n pressure: number;\n radiusX: number;\n radiusY: number;\n rotationAngle: number;\n force: number;\n }>;\n timestamp: number;\n }): void {\n // Clear frame-based touch events\n this.touchState.started = [];\n this.touchState.moved = [];\n this.touchState.ended = [];\n\n // Process touches based on event type\n if (data.type === 'touchstart') {\n this.processTouchStart(data.touches, data.timestamp);\n } else if (data.type === 'touchmove') {\n this.processTouchMove(data.touches, data.timestamp);\n } else if (data.type === 'touchend' || data.type === 'touchcancel') {\n this.processTouchEnd(data.touches, data.timestamp);\n }\n\n // Update touch array and count\n this.touchState.points = Array.from(this.activeTouches.values());\n this.touchState.count = this.touchState.points.length;\n this.touchState.primary = this.touchState.points[0] || null;\n\n // Update gestures\n this.updateGestures();\n }\n\n /**\n * Processes touch start events\n */\n private processTouchStart(touches: any[], timestamp: number): void {\n for (const touch of touches) {\n const touchPoint = this.createTouchPoint(touch, timestamp, true);\n this.activeTouches.set(touch.identifier, touchPoint);\n this.touchState.started.push(touchPoint);\n }\n\n // Handle tap gesture start\n if (this.touchState.count === 1) {\n this.gestureState.tapStartTime = timestamp;\n const touch = this.touchState.points[0];\n this.touchState.gestures.tapPosition = { x: touch.x, y: touch.y };\n }\n }\n\n /**\n * Processes touch move events\n */\n private processTouchMove(touches: any[], timestamp: number): void {\n for (const touch of touches) {\n const existing = this.activeTouches.get(touch.identifier);\n if (existing) {\n const updated = this.createTouchPoint(touch, timestamp, false, existing);\n this.activeTouches.set(touch.identifier, updated);\n this.touchState.moved.push(updated);\n }\n }\n }\n\n /**\n * Processes touch end events\n */\n private processTouchEnd(touches: any[], timestamp: number): void {\n for (const touch of touches) {\n const existing = this.activeTouches.get(touch.identifier);\n if (existing) {\n const ended = { ...existing, isEnding: true, isActive: false };\n this.touchState.ended.push(ended);\n this.activeTouches.delete(touch.identifier);\n }\n }\n\n // Handle tap gesture completion\n if (this.touchState.count === 0 && this.gestureState.tapStartTime > 0) {\n const tapDuration = timestamp - this.gestureState.tapStartTime;\n if (tapDuration < 300) { // Quick tap\n this.handleTap(timestamp);\n }\n this.gestureState.tapStartTime = 0;\n }\n }\n\n /**\n * Creates a touch point from raw touch data\n */\n private createTouchPoint(\n touch: any, \n timestamp: number, \n isNew: boolean, \n previous?: TouchPoint\n ): TouchPoint {\n const x = touch.clientX;\n const y = touch.clientY;\n \n const deltaX = previous ? x - previous.x : 0;\n const deltaY = previous ? y - previous.y : 0;\n \n // Calculate velocity\n const timeDelta = previous ? timestamp - (previous as any).timestamp : 16;\n const velocityX = timeDelta > 0 ? deltaX / timeDelta * 1000 : 0;\n const velocityY = timeDelta > 0 ? deltaY / timeDelta * 1000 : 0;\n\n return {\n id: touch.identifier,\n x,\n y,\n pressure: touch.pressure || 0,\n radius: Math.max(touch.radiusX || 0, touch.radiusY || 0),\n radiusX: touch.radiusX || 0,\n radiusY: touch.radiusY || 0,\n rotationAngle: touch.rotationAngle || 0,\n force: touch.force || touch.pressure || 0,\n deltaX,\n deltaY,\n velocity: { x: velocityX, y: velocityY },\n isNew,\n isActive: true,\n isEnding: false\n };\n }\n\n /**\n * Updates gesture recognition\n */\n private updateGestures(): void {\n const touches = this.touchState.points;\n const gestures = this.touchState.gestures;\n\n if (touches.length === 2) {\n // Two-finger gestures: pinch and rotate\n const touch1 = touches[0];\n const touch2 = touches[1];\n \n const distance = Math.sqrt(\n Math.pow(touch2.x - touch1.x, 2) + Math.pow(touch2.y - touch1.y, 2)\n );\n \n const angle = Math.atan2(touch2.y - touch1.y, touch2.x - touch1.x);\n\n if (this.gestureState.initialDistance === 0) {\n this.gestureState.initialDistance = distance;\n this.gestureState.initialAngle = angle;\n this.gestureState.lastPinchScale = 1;\n this.gestureState.lastRotationAngle = 0;\n }\n\n // Pinch gesture\n const scale = distance / this.gestureState.initialDistance;\n const scaleDelta = scale - this.gestureState.lastPinchScale;\n \n gestures.isPinching = Math.abs(scaleDelta) > 0.01;\n gestures.pinchScale = scale;\n gestures.pinchDelta = scaleDelta;\n this.gestureState.lastPinchScale = scale;\n\n // Rotation gesture\n const rotationAngle = angle - this.gestureState.initialAngle;\n const rotationDelta = rotationAngle - this.gestureState.lastRotationAngle;\n \n gestures.isRotating = Math.abs(rotationDelta) > 0.02;\n gestures.rotationAngle = rotationAngle;\n gestures.rotationDelta = rotationDelta;\n this.gestureState.lastRotationAngle = rotationAngle;\n\n } else {\n // Reset two-finger gesture state\n this.gestureState.initialDistance = 0;\n gestures.isPinching = false;\n gestures.isRotating = false;\n gestures.pinchDelta = 0;\n gestures.rotationDelta = 0;\n }\n\n // Pan gesture (one or more fingers)\n if (touches.length > 0) {\n const primaryTouch = touches[0];\n if (this.gestureState.panStartPosition.x === 0) {\n this.gestureState.panStartPosition = { x: primaryTouch.x, y: primaryTouch.y };\n }\n \n const panDeltaX = primaryTouch.x - this.gestureState.panStartPosition.x;\n const panDeltaY = primaryTouch.y - this.gestureState.panStartPosition.y;\n const panDistance = Math.sqrt(panDeltaX * panDeltaX + panDeltaY * panDeltaY);\n \n gestures.isPanning = panDistance > 10;\n gestures.panDelta = { x: panDeltaX, y: panDeltaY };\n } else {\n // Reset pan gesture\n this.gestureState.panStartPosition = { x: 0, y: 0 };\n gestures.isPanning = false;\n gestures.panDelta = { x: 0, y: 0 };\n }\n }\n\n /**\n * Handles tap gesture detection\n */\n private handleTap(timestamp: number): void {\n const timeSinceLastTap = timestamp - this.gestureState.lastTapTime;\n \n if (timeSinceLastTap < 300) {\n // Multi-tap\n this.gestureState.tapCount++;\n } else {\n // New tap sequence\n this.gestureState.tapCount = 1;\n }\n \n this.touchState.gestures.tapCount = this.gestureState.tapCount;\n this.touchState.gestures.lastTapTime = timestamp;\n this.touchState.gestures.isTapping = true;\n this.gestureState.lastTapTime = timestamp;\n }\n\n /**\n * Called at the start of each frame to reset frame-based events\n */\n frameStart(): void {\n // Reset mouse frame events\n this.mouseState.wasPressed = false;\n this.mouseState.wasReleased = false;\n this.mouseState.wasMoved = false;\n this.mouseState.wheelDelta = 0;\n this.mouseState.wheelX = 0;\n this.mouseState.wheelY = 0;\n\n // Reset keyboard frame events\n this.pressedThisFrame.clear();\n this.releasedThisFrame.clear();\n\n // Reset touch gesture frame events\n this.touchState.gestures.isTapping = false;\n this.touchState.gestures.pinchDelta = 0;\n this.touchState.gestures.rotationDelta = 0;\n }\n\n /**\n * Get current mouse state (read-only)\n */\n getMouseState(): Readonly<MouseAPI> {\n return this.mouseState;\n }\n\n /**\n * Get current keyboard state (read-only)\n */\n getKeyboardState(): Readonly<KeyboardAPI> {\n return this.keyboardState;\n }\n\n /**\n * Get current touch state (read-only)\n */\n getTouchState(): Readonly<TouchAPI> {\n return this.touchState;\n }\n\n /**\n * Cleanup resources\n */\n destroy(): void {\n this.mouseVelocityHistory.length = 0;\n this.activeTouches.clear();\n this.activeKeys.clear();\n this.pressedThisFrame.clear();\n this.releasedThisFrame.clear();\n }\n} ","import { AnalysisConfiguration } from '../types/index.js';\n\n/**\n * Manages audio analysis and processing for the host side.\n * Handles audio stream processing and provides real-time audio analysis for Phase 5.\n * \n * This system provides:\n * - Real-time audio analysis (RMS, peak, frequency bands)\n * - AudioContext management and cleanup\n * - Raw FFT data access for custom analysis\n * - Analysis results sent to worker for artist API\n * - Message handling for audio stream updates\n */\nexport class AudioSystem {\n // Audio context and analysis nodes\n private audioContext: AudioContext | null = null;\n private analyser: AnalyserNode | null = null;\n private mediaStreamSource: MediaStreamAudioSourceNode | null = null;\n private currentStream: MediaStream | null = null;\n \n // Debug logging control\n private debugMode = false;\n\n /**\n * Enable or disable debug logging\n */\n setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n }\n\n /**\n * Debug logging helper\n */\n private debugLog(message: string, ...args: any[]): void {\n if (this.debugMode) {\n console.log(message, ...args);\n }\n }\n \n // Analysis configuration (good balance, leaning towards quality)\n private fftSize = 2048; // Good balance for quality vs performance\n private smoothingTimeConstant = 0.8; // Smooth but responsive\n \n // Analysis data arrays\n private frequencyData: Uint8Array<ArrayBuffer> | null = null;\n private timeDomainData: Uint8Array<ArrayBuffer> | null = null;\n \n // Audio analysis state (host-side state)\n private audioState = {\n isConnected: false,\n volume: {\n rms: 0,\n peak: 0\n },\n bands: {\n bass: 0,\n mid: 0,\n treble: 0,\n subBass: 0,\n lowMid: 0,\n highMid: 0,\n presence: 0,\n brilliance: 0\n }\n };\n \n // Analysis loop\n private analysisLoopId: number | null = null;\n private isAnalysisRunning = false;\n \n // Callback to send results to worker\n private sendAnalysisResults: ((data: any) => void) | null = null;\n\n constructor(sendAnalysisResultsCallback?: (data: any) => void) {\n // Bind methods for proper context\n this.handleAudioStreamUpdate = this.handleAudioStreamUpdate.bind(this);\n this.performAnalysis = this.performAnalysis.bind(this);\n this.sendAnalysisResults = sendAnalysisResultsCallback || null;\n }\n\n /**\n * Get the current audio analysis state (for host-side usage)\n */\n public getAudioState() {\n return { ...this.audioState };\n }\n\n /**\n * Handle audio stream update (called from VijiCore)\n */\n public handleAudioStreamUpdate(data: {\n audioStream?: MediaStream | null;\n analysisConfig?: AnalysisConfiguration;\n timestamp: number;\n }): void {\n try {\n if (data.audioStream) {\n this.setAudioStream(data.audioStream);\n } else {\n // Stream removed or null\n this.disconnectAudioStream();\n }\n \n // Update analysis configuration if provided\n if (data.analysisConfig) {\n this.updateAnalysisConfig(data.analysisConfig);\n }\n } catch (error) {\n console.error('Error handling audio stream update:', error);\n this.audioState.isConnected = false;\n this.sendAnalysisResultsToWorker();\n }\n }\n\n /**\n * Set the audio stream for analysis\n */\n private async setAudioStream(audioStream: MediaStream): Promise<void> {\n // Clean up existing connections\n this.disconnectAudioStream();\n \n // Validate stream has audio tracks\n const audioTracks = audioStream.getAudioTracks();\n if (audioTracks.length === 0) {\n console.warn('No audio tracks in provided stream');\n this.audioState.isConnected = false;\n this.sendAnalysisResultsToWorker();\n return;\n }\n \n try {\n // Create AudioContext if needed\n if (!this.audioContext) {\n this.audioContext = new AudioContext();\n \n // Resume context if suspended (required by browser policies)\n if (this.audioContext.state === 'suspended') {\n await this.audioContext.resume();\n }\n }\n \n // Create analyser node with our configuration\n this.analyser = this.audioContext.createAnalyser();\n this.analyser.fftSize = this.fftSize;\n this.analyser.smoothingTimeConstant = this.smoothingTimeConstant;\n \n // Create media stream source\n this.mediaStreamSource = this.audioContext.createMediaStreamSource(audioStream);\n \n // Connect stream to analyser (no need to connect to destination for analysis)\n this.mediaStreamSource.connect(this.analyser);\n \n // Initialize data arrays\n const bufferLength = this.analyser.frequencyBinCount;\n this.frequencyData = new Uint8Array(bufferLength);\n this.timeDomainData = new Uint8Array(bufferLength);\n \n // Store stream reference\n this.currentStream = audioStream;\n this.audioState.isConnected = true;\n \n // Start analysis loop\n this.startAnalysisLoop();\n \n this.debugLog('Audio stream connected successfully (host-side)', {\n sampleRate: this.audioContext.sampleRate,\n fftSize: this.fftSize,\n bufferLength\n });\n \n } catch (error) {\n console.error('Failed to set up audio analysis:', error);\n this.audioState.isConnected = false;\n this.disconnectAudioStream();\n }\n \n // Send initial state to worker\n this.sendAnalysisResultsToWorker();\n }\n\n /**\n * Disconnect current audio stream and clean up resources\n */\n private disconnectAudioStream(): void {\n // Stop analysis loop\n this.stopAnalysisLoop();\n \n // Disconnect and clean up audio nodes\n if (this.mediaStreamSource) {\n this.mediaStreamSource.disconnect();\n this.mediaStreamSource = null;\n }\n \n if (this.analyser) {\n this.analyser.disconnect();\n this.analyser = null;\n }\n \n // Reset data arrays\n this.frequencyData = null;\n this.timeDomainData = null;\n \n // Clear stream reference\n this.currentStream = null;\n \n // Update state\n this.audioState.isConnected = false;\n this.resetAudioValues();\n \n // Send updated state to worker\n this.sendAnalysisResultsToWorker();\n \n this.debugLog('Audio stream disconnected (host-side)');\n }\n\n /**\n * Update analysis configuration\n */\n private updateAnalysisConfig(config: AnalysisConfiguration): void {\n let needsReconnect = false;\n \n if (config.fftSize && config.fftSize !== this.fftSize) {\n this.fftSize = config.fftSize;\n needsReconnect = true;\n }\n \n if (config.smoothing !== undefined) {\n this.smoothingTimeConstant = config.smoothing;\n if (this.analyser) {\n this.analyser.smoothingTimeConstant = this.smoothingTimeConstant;\n }\n }\n \n // Reconnect if FFT size changed (requires new analyser)\n if (needsReconnect && this.currentStream) {\n const stream = this.currentStream;\n this.setAudioStream(stream);\n }\n }\n\n /**\n * Start the audio analysis loop\n */\n private startAnalysisLoop(): void {\n if (this.isAnalysisRunning) return;\n \n this.isAnalysisRunning = true;\n this.performAnalysis();\n }\n\n /**\n * Stop the audio analysis loop\n */\n private stopAnalysisLoop(): void {\n this.isAnalysisRunning = false;\n if (this.analysisLoopId !== null) {\n cancelAnimationFrame(this.analysisLoopId);\n this.analysisLoopId = null;\n }\n }\n\n /**\n * Perform audio analysis (called every frame)\n */\n private performAnalysis(): void {\n if (!this.isAnalysisRunning || !this.analyser || !this.frequencyData || !this.timeDomainData) {\n return;\n }\n \n // Get current audio data\n this.analyser.getByteFrequencyData(this.frequencyData);\n this.analyser.getByteTimeDomainData(this.timeDomainData);\n \n // Calculate volume metrics\n this.calculateVolumeMetrics();\n \n // Calculate frequency bands\n this.calculateFrequencyBands();\n \n // Send results to worker\n this.sendAnalysisResultsToWorker();\n \n // Schedule next analysis\n this.analysisLoopId = requestAnimationFrame(() => this.performAnalysis());\n }\n\n /**\n * Calculate RMS and peak volume from time domain data\n */\n private calculateVolumeMetrics(): void {\n if (!this.timeDomainData) return;\n \n let rmsSum = 0;\n let peak = 0;\n \n for (let i = 0; i < this.timeDomainData.length; i++) {\n // Convert from 0-255 to -1 to 1\n const sample = (this.timeDomainData[i] - 128) / 128;\n \n // RMS calculation\n rmsSum += sample * sample;\n \n // Peak calculation\n const absValue = Math.abs(sample);\n if (absValue > peak) {\n peak = absValue;\n }\n }\n \n // Calculate RMS (Root Mean Square)\n const rms = Math.sqrt(rmsSum / this.timeDomainData.length);\n \n // Update audio state (values between 0 and 1)\n this.audioState.volume.rms = rms;\n this.audioState.volume.peak = peak;\n }\n\n /**\n * Calculate frequency band values from frequency data\n */\n private calculateFrequencyBands(): void {\n if (!this.frequencyData || !this.audioContext) return;\n \n const nyquist = this.audioContext.sampleRate / 2;\n const binCount = this.frequencyData.length;\n \n // Define frequency bands (in Hz)\n const bands = {\n subBass: { min: 20, max: 60 }, // Sub-bass\n bass: { min: 60, max: 250 }, // Bass\n lowMid: { min: 250, max: 500 }, // Low midrange\n mid: { min: 500, max: 2000 }, // Midrange\n highMid: { min: 2000, max: 4000 }, // High midrange\n presence: { min: 4000, max: 6000 }, // Presence\n brilliance: { min: 6000, max: 20000 }, // Brilliance\n treble: { min: 2000, max: 20000 } // Treble (combined high frequencies)\n };\n \n // Calculate band values\n for (const [bandName, range] of Object.entries(bands)) {\n const startBin = Math.floor((range.min / nyquist) * binCount);\n const endBin = Math.min(Math.floor((range.max / nyquist) * binCount), binCount - 1);\n \n let sum = 0;\n let count = 0;\n \n for (let i = startBin; i <= endBin; i++) {\n sum += this.frequencyData[i];\n count++;\n }\n \n // Average and normalize (0-255 to 0-1)\n const average = count > 0 ? sum / count : 0;\n (this.audioState.bands as any)[bandName] = average / 255;\n }\n }\n\n /**\n * Send analysis results to worker\n */\n private sendAnalysisResultsToWorker(): void {\n if (this.sendAnalysisResults) {\n // Include raw frequency data access\n const frequencyData = this.frequencyData ? new Uint8Array(this.frequencyData) : new Uint8Array(0);\n \n this.sendAnalysisResults({\n type: 'audio-analysis-update',\n data: {\n ...this.audioState,\n frequencyData, // For getFrequencyData() access\n timestamp: performance.now()\n }\n });\n }\n }\n\n /**\n * Reset audio values to defaults\n */\n private resetAudioValues(): void {\n this.audioState.volume.rms = 0;\n this.audioState.volume.peak = 0;\n \n for (const band in this.audioState.bands) {\n (this.audioState.bands as any)[band] = 0;\n }\n }\n\n /**\n * Reset all audio state (called when destroying)\n */\n public resetAudioState(): void {\n this.disconnectAudioStream();\n \n // Close AudioContext if it exists\n if (this.audioContext && this.audioContext.state !== 'closed') {\n this.audioContext.close();\n this.audioContext = null;\n }\n \n this.resetAudioValues();\n }\n\n /**\n * Get current analysis configuration\n */\n public getAnalysisConfig(): { fftSize: number; smoothing: number } {\n return {\n fftSize: this.fftSize,\n smoothing: this.smoothingTimeConstant\n };\n }\n} ","/**\r\n * Lightweight Video Coordinator for the host side.\r\n * Handles MediaStream management and coordinates with worker-side VideoSystem.\r\n * \r\n * CORRECT OffscreenCanvas Approach:\r\n * - Create OffscreenCanvas on host (no context!)\r\n * - Transfer to worker immediately \r\n * - Worker gets context and handles all processing\r\n * - Send video frames as ImageBitmap for worker to draw\r\n */\r\nexport class VideoCoordinator {\r\n // Video elements for MediaStream processing\r\n private videoElement: HTMLVideoElement | null = null;\r\n private canvas: HTMLCanvasElement | null = null;\r\n private ctx: CanvasRenderingContext2D | null = null;\r\n // Note: currentStream was removed as it was unused\r\n \r\n // Transfer coordination\r\n private transferLoopId: number | null = null;\r\n private isTransferRunning = false;\r\n private lastTransferTime = 0;\r\n private transferInterval = 1000 / 30; // Transfer at 30 FPS\r\n \r\n // Video state (lightweight - main state is in worker)\r\n private coordinatorState = {\r\n isConnected: false,\r\n sourceType: '',\r\n frameWidth: 0,\r\n frameHeight: 0\r\n };\r\n \r\n // Track if OffscreenCanvas has been sent to worker\r\n private hasTransferredCanvas = false;\r\n \r\n // Callback to send data to worker\r\n private sendToWorker: ((data: any, transfer?: Transferable[]) => void) | null = null;\r\n \r\n // Debug logging control\r\n private debugMode = false;\r\n\r\n /**\r\n * Enable or disable debug logging\r\n */\r\n setDebugMode(enabled: boolean): void {\r\n this.debugMode = enabled;\r\n }\r\n\r\n /**\r\n * Debug logging helper\r\n */\r\n private debugLog(message: string, ...args: any[]): void {\r\n if (this.debugMode) {\r\n console.log(message, ...args);\r\n }\r\n }\r\n\r\n constructor(sendToWorkerCallback?: (data: any, transfer?: Transferable[]) => void) {\r\n // Bind methods for proper context\r\n this.handleVideoStreamUpdate = this.handleVideoStreamUpdate.bind(this);\r\n this.transferVideoFrame = this.transferVideoFrame.bind(this);\r\n this.sendToWorker = sendToWorkerCallback || null;\r\n }\r\n\r\n /**\r\n * Get the current video coordinator state (for host-side usage)\r\n */\r\n public getCoordinatorState() {\r\n return { ...this.coordinatorState };\r\n }\r\n\r\n /**\r\n * Handle video stream update (called from VijiCore)\r\n */\r\n public handleVideoStreamUpdate(data: {\r\n videoStream?: MediaStream | null;\r\n targetFrameRate?: number;\r\n cvConfig?: any; // Phase 11 preparation\r\n timestamp: number;\r\n }): void {\r\n try {\r\n if (data.videoStream) {\r\n this.setVideoStream(data.videoStream);\r\n } else {\r\n // Stream removed or null\r\n this.disconnectVideoStream();\r\n }\r\n \r\n // Forward configuration to worker\r\n if (data.targetFrameRate || data.cvConfig) {\r\n this.sendConfigurationToWorker({\r\n ...(data.targetFrameRate && { targetFrameRate: data.targetFrameRate }),\r\n ...(data.cvConfig && { cvConfig: data.cvConfig }),\r\n timestamp: data.timestamp\r\n });\r\n }\r\n } catch (error) {\r\n console.error('Error handling video stream update:', error);\r\n this.coordinatorState.isConnected = false;\r\n this.sendDisconnectionToWorker();\r\n }\r\n }\r\n\r\n /**\r\n * Set the video stream for processing\r\n */\r\n private async setVideoStream(videoStream: MediaStream): Promise<void> {\r\n // Clean up existing connections\r\n this.disconnectVideoStream();\r\n \r\n // Check if stream has video tracks\r\n const videoTracks = videoStream.getVideoTracks();\r\n if (videoTracks.length === 0) {\r\n console.warn('No video tracks in provided stream');\r\n this.coordinatorState.isConnected = false;\r\n this.sendDisconnectionToWorker();\r\n return;\r\n }\r\n \r\n try {\r\n // Create video element for stream playback\r\n this.videoElement = document.createElement('video');\r\n this.videoElement.autoplay = true;\r\n this.videoElement.muted = true; // Prevent audio from playing\r\n this.videoElement.playsInline = true; // Important for mobile\r\n \r\n // Create canvas for frame capture\r\n this.canvas = document.createElement('canvas');\r\n this.ctx = this.canvas.getContext('2d');\r\n \r\n if (!this.ctx) {\r\n throw new Error('Failed to get 2D context from canvas');\r\n }\r\n \r\n // Set up video element\r\n this.videoElement.srcObject = videoStream;\r\n \r\n // Wait for video metadata to load and ensure video is playing\r\n await new Promise<void>((resolve, reject) => {\r\n const timeout = setTimeout(() => reject(new Error('Video metadata load timeout')), 5000);\r\n \r\n this.videoElement!.addEventListener('loadedmetadata', async () => {\r\n clearTimeout(timeout);\r\n \r\n try {\r\n // Ensure video starts playing\r\n await this.videoElement!.play();\r\n this.debugLog('✅ Video element is now playing:', {\r\n videoWidth: this.videoElement!.videoWidth,\r\n videoHeight: this.videoElement!.videoHeight,\r\n readyState: this.videoElement!.readyState,\r\n paused: this.videoElement!.paused\r\n });\r\n resolve();\r\n } catch (playError) {\r\n console.error('🔴 Failed to start video playback:', playError);\r\n reject(playError);\r\n }\r\n }, { once: true });\r\n \r\n this.videoElement!.addEventListener('error', (e) => {\r\n clearTimeout(timeout);\r\n reject(new Error(`Video load error: ${e}`));\r\n }, { once: true });\r\n });\r\n \r\n // Set canvas dimensions to match video\r\n this.canvas.width = this.videoElement.videoWidth;\r\n this.canvas.height = this.videoElement.videoHeight;\r\n \r\n // Update state (stream reference stored in coordinatorState)\r\n this.coordinatorState.isConnected = true;\r\n this.coordinatorState.frameWidth = this.videoElement.videoWidth;\r\n this.coordinatorState.frameHeight = this.videoElement.videoHeight;\r\n this.coordinatorState.sourceType = 'MediaStream';\r\n \r\n // ✅ CORRECT OffscreenCanvas approach: Transfer canvas to worker FIRST\r\n await this.transferOffscreenCanvasToWorker(this.videoElement.videoWidth, this.videoElement.videoHeight);\r\n \r\n // Start frame transfer loop\r\n this.startTransferLoop();\r\n \r\n this.debugLog('Video stream connected successfully (host-side coordinator)', {\r\n width: this.videoElement.videoWidth,\r\n height: this.videoElement.videoHeight\r\n });\r\n \r\n } catch (error) {\r\n console.error('Failed to set up video coordination:', error);\r\n this.coordinatorState.isConnected = false;\r\n this.disconnectVideoStream();\r\n }\r\n }\r\n\r\n /**\r\n * ✅ CORRECT: Transfer OffscreenCanvas to worker BEFORE getting context\r\n */\r\n private async transferOffscreenCanvasToWorker(width: number, height: number): Promise<void> {\r\n if (this.hasTransferredCanvas) {\r\n // Canvas already transferred, just update dimensions\r\n this.sendConfigurationToWorker({\r\n width: width,\r\n height: height,\r\n timestamp: performance.now()\r\n });\r\n return;\r\n }\r\n\r\n try {\r\n // Create OffscreenCanvas - NO CONTEXT on host side!\r\n const offscreenCanvas = new OffscreenCanvas(width, height);\r\n \r\n // Transfer immediately to worker (before any context creation)\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-canvas-setup',\r\n data: {\r\n offscreenCanvas,\r\n width,\r\n height,\r\n timestamp: performance.now()\r\n }\r\n }, [offscreenCanvas]); // ✅ Transfer ownership to worker\r\n \r\n this.hasTransferredCanvas = true;\r\n this.debugLog('✅ OffscreenCanvas transferred to worker (correct approach)', {\r\n width,\r\n height\r\n });\r\n }\r\n } catch (error) {\r\n console.error('Failed to transfer OffscreenCanvas to worker:', error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Disconnect current video stream and clean up resources\r\n */\r\n private disconnectVideoStream(): void {\r\n // Stop transfer loop\r\n this.stopTransferLoop();\r\n \r\n // Clean up video element\r\n if (this.videoElement) {\r\n this.videoElement.pause();\r\n this.videoElement.srcObject = null;\r\n this.videoElement = null;\r\n }\r\n \r\n // Clean up canvas\r\n if (this.canvas) {\r\n this.canvas = null;\r\n this.ctx = null;\r\n }\r\n \r\n // Clear stream reference\r\n // Stream cleanup handled by MediaStream track stopping\r\n \r\n // Update state\r\n this.coordinatorState.isConnected = false;\r\n this.coordinatorState.frameWidth = 0;\r\n this.coordinatorState.frameHeight = 0;\r\n this.coordinatorState.sourceType = '';\r\n this.hasTransferredCanvas = false;\r\n \r\n // Notify worker of disconnection\r\n this.sendDisconnectionToWorker();\r\n \r\n this.debugLog('Video stream disconnected (host-side coordinator)');\r\n }\r\n\r\n /**\r\n * Start the video frame transfer loop\r\n */\r\n private startTransferLoop(): void {\r\n if (this.isTransferRunning) return;\r\n \r\n this.isTransferRunning = true;\r\n this.lastTransferTime = performance.now();\r\n this.transferVideoFrame();\r\n }\r\n\r\n /**\r\n * Stop the video frame transfer loop\r\n */\r\n private stopTransferLoop(): void {\r\n this.isTransferRunning = false;\r\n if (this.transferLoopId !== null) {\r\n cancelAnimationFrame(this.transferLoopId);\r\n this.transferLoopId = null;\r\n }\r\n }\r\n\r\n /**\r\n * Transfer video frame to worker using ImageBitmap (for worker to draw on its OffscreenCanvas)\r\n */\r\n private transferVideoFrame(): void {\r\n if (!this.isTransferRunning || !this.videoElement || !this.canvas || !this.ctx) {\r\n if (!this.isTransferRunning) {\r\n this.debugLog('🔴 Transfer loop stopped');\r\n }\r\n return;\r\n }\r\n \r\n const currentTime = performance.now();\r\n const deltaTime = currentTime - this.lastTransferTime;\r\n \r\n // Only transfer frame if enough time has passed (FPS-based transfer)\r\n if (deltaTime >= this.transferInterval) {\r\n // Log occasionally to avoid spam (very rarely now that it's working)\r\n if (Math.random() < 0.01) { // Log ~1% of frames\r\n this.debugLog(`🔄 Transfer loop tick: ${deltaTime.toFixed(1)}ms since last frame`);\r\n }\r\n \r\n this.transferFrameToWorker().catch(error => {\r\n console.error('🔴 Error transferring video frame to worker:', error);\r\n });\r\n \r\n this.lastTransferTime = currentTime;\r\n }\r\n \r\n // Schedule next transfer check\r\n this.transferLoopId = requestAnimationFrame(() => this.transferVideoFrame());\r\n }\r\n\r\n /**\r\n * Async frame transfer using ImageBitmap (for worker to draw)\r\n */\r\n private async transferFrameToWorker(): Promise<void> {\r\n if (!this.videoElement || !this.canvas || !this.ctx) {\r\n console.warn('🔴 Frame transfer called but missing elements:', {\r\n hasVideo: !!this.videoElement,\r\n hasCanvas: !!this.canvas,\r\n hasCtx: !!this.ctx\r\n });\r\n return;\r\n }\r\n\r\n try {\r\n // Check if video is actually playing\r\n if (this.videoElement.readyState < 2) {\r\n console.warn('🔴 Video not ready for frame capture, readyState:', this.videoElement.readyState);\r\n return;\r\n }\r\n \r\n if (this.videoElement.videoWidth === 0 || this.videoElement.videoHeight === 0) {\r\n console.warn('🔴 Video has no dimensions:', {\r\n width: this.videoElement.videoWidth,\r\n height: this.videoElement.videoHeight\r\n });\r\n return;\r\n }\r\n \r\n // Draw current video frame to canvas\r\n this.ctx.drawImage(this.videoElement, 0, 0, this.canvas.width, this.canvas.height);\r\n \r\n // Create ImageBitmap from canvas (for worker to draw onto its OffscreenCanvas)\r\n const imageBitmap = await createImageBitmap(this.canvas);\r\n \r\n // Log occasionally to avoid spam (very rarely now that it's working)\r\n if (Math.random() < 0.01) { // Log ~1% of frames\r\n this.debugLog('✅ Frame captured and ImageBitmap created:', {\r\n videoDimensions: `${this.videoElement.videoWidth}x${this.videoElement.videoHeight}`,\r\n canvasDimensions: `${this.canvas.width}x${this.canvas.height}`,\r\n bitmapDimensions: `${imageBitmap.width}x${imageBitmap.height}`\r\n });\r\n }\r\n \r\n // Send ImageBitmap to worker (worker will draw it on its OffscreenCanvas)\r\n this.sendFrameToWorker(imageBitmap);\r\n \r\n } catch (error) {\r\n console.error('🔴 Failed to create ImageBitmap:', error);\r\n }\r\n }\r\n\r\n /**\r\n * Send ImageBitmap frame to worker (for worker to draw on its OffscreenCanvas)\r\n */\r\n private sendFrameToWorker(imageBitmap: ImageBitmap): void {\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-frame-update',\r\n data: {\r\n imageBitmap,\r\n timestamp: performance.now()\r\n }\r\n }, [imageBitmap]); // Transfer the ImageBitmap\r\n }\r\n }\r\n\r\n /**\r\n * Send configuration updates to worker\r\n */\r\n private sendConfigurationToWorker(config: {\r\n targetFrameRate?: number;\r\n cvConfig?: any;\r\n width?: number;\r\n height?: number;\r\n timestamp: number;\r\n }): void {\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-config-update',\r\n data: config\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Send disconnection notification to worker\r\n */\r\n private sendDisconnectionToWorker(): void {\r\n if (this.sendToWorker) {\r\n this.sendToWorker({\r\n type: 'video-config-update',\r\n data: {\r\n disconnect: true,\r\n timestamp: performance.now()\r\n }\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Handle image file as video source\r\n */\r\n public async setImageSource(imageFile: File): Promise<void> {\r\n try {\r\n // Create image element\r\n const img = new Image();\r\n const url = URL.createObjectURL(imageFile);\r\n \r\n // Load image\r\n await new Promise<void>((resolve, reject) => {\r\n img.onload = () => {\r\n URL.revokeObjectURL(url);\r\n resolve();\r\n };\r\n img.onerror = () => {\r\n URL.revokeObjectURL(url);\r\n reject(new Error('Failed to load image'));\r\n };\r\n img.src = url;\r\n });\r\n \r\n // Clean up existing connections\r\n this.disconnectVideoStream();\r\n \r\n // Update state for static image\r\n this.coordinatorState.isConnected = true;\r\n this.coordinatorState.frameWidth = img.width;\r\n this.coordinatorState.frameHeight = img.height;\r\n this.coordinatorState.sourceType = 'Image';\r\n \r\n // Transfer OffscreenCanvas to worker first\r\n await this.transferOffscreenCanvasToWorker(img.width, img.height);\r\n \r\n // Create ImageBitmap and send to worker for drawing\r\n const imageBitmap = await createImageBitmap(img);\r\n this.sendFrameToWorker(imageBitmap);\r\n \r\n this.debugLog('Image source set successfully (host-side coordinator)', {\r\n width: img.width,\r\n height: img.height\r\n });\r\n \r\n } catch (error) {\r\n console.error('Failed to set image source:', error);\r\n this.coordinatorState.isConnected = false;\r\n this.sendDisconnectionToWorker();\r\n }\r\n }\r\n\r\n /**\r\n * Reset all video coordinator state (called when destroying)\r\n */\r\n public resetVideoState(): void {\r\n this.disconnectVideoStream();\r\n }\r\n\r\n /**\r\n * Get current coordinator configuration\r\n */\r\n public getCoordinatorConfig(): { transferInterval: number } {\r\n return {\r\n transferInterval: this.transferInterval\r\n };\r\n }\r\n} ","import { IFrameManager } from './iframe/IFrameManager.js';\nimport { WorkerManager } from './worker/WorkerManager.js';\nimport { InteractionManager } from './interaction/InteractionManager.js';\nimport { AudioSystem } from './audio/AudioSystem.js';\nimport { VideoCoordinator } from './video/VideoCoordinator.js';\nimport { \n VijiCoreConfig, \n VijiCoreError, \n PerformanceStats, \n ParameterGroup,\n ParameterDefinition,\n FrameRateMode,\n CVFrameRateMode,\n ParameterValue,\n ParameterDefinitionData,\n ParameterUpdateData,\n CoreCapabilities,\n ParameterCategory,\n CaptureFrameOptions\n} from './types/index.js';\n\n/**\n * Main VijiCore class - Universal execution engine for creative scenes.\n * \n * Orchestrates secure IFrame + WebWorker execution with controlled communication.\n * Provides the foundation for scene execution across platform and SDK contexts.\n */\nexport class VijiCore {\n private iframeManager: IFrameManager | null = null;\n private workerManager: WorkerManager | null = null;\n private interactionManager: InteractionManager | null = null;\n private audioSystem: AudioSystem | null = null;\n private videoCoordinator: VideoCoordinator | null = null;\n private isInitialized = false;\n private isDestroyed = false;\n private isInitializing = false;\n private instanceId: string;\n private screenRefreshRate = 60; // Will be detected\n private debugMode = false; // Debug logging control\n\n /**\n * Debug logging helper\n */\n private debugLog(message: string, ...args: any[]): void {\n if (this.debugMode) {\n console.log(message, ...args);\n }\n }\n \n // Configuration\n private config: VijiCoreConfig & { \n frameRateMode: FrameRateMode;\n autoOptimize: boolean;\n parameters: ParameterGroup[];\n noInputs: boolean;\n allowUserInteraction: boolean;\n };\n\n // Audio stream management\n private currentAudioStream: MediaStream | null = null;\n\n // Video stream management\n private currentVideoStream: MediaStream | null = null;\n\n // Interaction state management\n private currentInteractionEnabled: boolean;\n\n // Parameter system for Phase 2\n private parameterGroups = new Map<string, ParameterGroup>();\n private parameterValues = new Map<string, ParameterValue>();\n private parametersInitialized = false;\n \n // Event listeners for parameter system\n private parameterListeners = new Map<string, Set<(value: ParameterValue) => void>>();\n private parameterDefinedListeners = new Set<(groups: ParameterGroup[]) => void>();\n private parameterErrorListeners = new Set<(error: { message: string; code: string }) => void>();\n private capabilitiesChangeListeners = new Set<(capabilities: CoreCapabilities) => void>();\n \n // Performance tracking (basic for Phase 1)\n private stats: PerformanceStats = {\n frameTime: 0,\n resolution: { width: 0, height: 0 },\n scale: 1.0,\n frameRate: {\n mode: 'full',\n screenRefreshRate: 60,\n effectiveRefreshRate: 60\n },\n rendererType: 'native',\n parameterCount: 0\n };\n\n constructor(config: VijiCoreConfig) {\n // Validate required configuration\n this.validateConfig(config);\n \n // Generate unique instance ID for debugging\n this.instanceId = `viji-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n \n // Set default configuration values\n this.config = {\n ...config,\n frameRateMode: config.frameRateMode || 'full',\n autoOptimize: config.autoOptimize ?? true,\n parameters: config.parameters || [],\n noInputs: config.noInputs ?? false,\n allowUserInteraction: config.allowUserInteraction ?? true\n };\n \n // Initialize interaction state from config\n this.currentInteractionEnabled = this.config.allowUserInteraction;\n \n this.debugLog(`VijiCore instance created: ${this.instanceId}`);\n }\n\n /**\n * Capture current scene frame as an image Blob.\n * Resolution can be a scale (0-1+) or explicit width/height with center-crop.\n */\n async captureFrame(options: CaptureFrameOptions = {}): Promise<Blob> {\n if (!this.workerManager || !this.workerManager.ready) {\n throw new VijiCoreError('Core not initialized', 'NOT_INITIALIZED');\n }\n\n const response = await this.workerManager.sendMessage('capture-frame', {\n type: options.type,\n resolution: options.resolution\n }, 10000);\n\n // response contains { mimeType, buffer, width, height }\n const buffer: ArrayBuffer = response.buffer;\n const mimeType: string = response.mimeType || options.type || 'image/jpeg';\n return new Blob([buffer], { type: mimeType });\n }\n\n /**\n * Enable or disable debug logging\n */\n setDebugMode(enabled: boolean): void {\n this.debugMode = enabled;\n // Propagate debug mode to child components when they exist\n if (this.iframeManager && 'setDebugMode' in this.iframeManager) {\n (this.iframeManager as any).setDebugMode(enabled);\n }\n if (this.workerManager && 'setDebugMode' in this.workerManager) {\n (this.workerManager as any).setDebugMode(enabled);\n }\n if (this.interactionManager && 'setDebugMode' in this.interactionManager) {\n (this.interactionManager as any).setDebugMode(enabled);\n }\n if (this.audioSystem && 'setDebugMode' in this.audioSystem) {\n (this.audioSystem as any).setDebugMode(enabled);\n }\n if (this.videoCoordinator && 'setDebugMode' in this.videoCoordinator) {\n (this.videoCoordinator as any).setDebugMode(enabled);\n }\n \n // Also propagate to worker runtime if available\n if (this.workerManager) {\n this.workerManager.postMessage('debug-mode', { enabled });\n }\n }\n\n /**\n * Get current debug mode status\n */\n getDebugMode(): boolean {\n return this.debugMode;\n }\n\n /**\n * Initializes the core components in sequence\n */\n async initialize(): Promise<void> {\n try {\n if (this.isDestroyed) {\n throw new VijiCoreError('Cannot initialize destroyed instance', 'INSTANCE_DESTROYED');\n }\n\n if (this.isInitializing) {\n throw new VijiCoreError('Initialization already in progress', 'CONCURRENT_INITIALIZATION');\n }\n\n if (this.isInitialized) {\n throw new VijiCoreError('Core already initialized', 'ALREADY_INITIALIZED');\n }\n\n this.isInitializing = true;\n this.debugLog(`Starting VijiCore initialization... (${this.instanceId})`);\n\n // Clear any existing content in the container\n this.config.hostContainer.innerHTML = '';\n\n // 1. Create secure IFrame\n this.iframeManager = new IFrameManager(\n this.config.hostContainer,\n );\n \n await this.iframeManager.createSecureIFrame();\n \n // 2. Create canvas inside IFrame with retry logic\n const offscreenCanvas = await this.createCanvasWithRetry();\n \n // 3. Phase 7: Always setup interaction system for runtime control\n // DOM event listeners are still conditionally created based on enabled state\n this.interactionManager = new InteractionManager();\n this.setupInteractionSystem();\n \n // 4. Create and initialize WebWorker\n this.workerManager = new WorkerManager(\n this.config.sceneCode,\n offscreenCanvas\n );\n \n // 5. Setup communication handlers BEFORE creating worker\n this.setupCommunication();\n \n await this.workerManager.createWorker();\n \n // 6. Initialize AudioSystem (host-side) with callback to send results to worker\n this.audioSystem = new AudioSystem((message) => {\n if (this.workerManager) {\n this.workerManager.postMessage(message.type, message.data);\n }\n });\n\n // 7. Initialize VideoCoordinator (host-side) with callback to send results to worker\n this.videoCoordinator = new VideoCoordinator((message, transfer) => {\n if (this.workerManager) {\n if (transfer && transfer.length > 0) {\n this.workerManager.postMessage(message.type, message.data, transfer);\n } else {\n this.workerManager.postMessage(message.type, message.data);\n }\n }\n });\n \n // 5. Send initial resolution info to worker\n const effectiveResolution = this.iframeManager.getEffectiveResolution();\n this.workerManager.postMessage('resolution-update', {\n effectiveWidth: effectiveResolution.width,\n effectiveHeight: effectiveResolution.height\n });\n \n // 6. Detect screen refresh rate and update stats\n await this.detectScreenRefreshRate();\n \n // Send detected refresh rate to worker\n this.workerManager.postMessage('refresh-rate-update', {\n screenRefreshRate: this.screenRefreshRate\n });\n \n // 8. Phase 5: Setup audio stream if provided\n if (this.config.audioStream) {\n await this.setAudioStream(this.config.audioStream);\n }\n \n // 9. Phase 10: Setup video stream if provided\n if (this.config.videoStream) {\n await this.setVideoStream(this.config.videoStream);\n }\n \n this.stats.resolution = effectiveResolution;\n this.stats.scale = this.iframeManager.getScale();\n this.updateFrameRateStats();\n \n this.isInitialized = true;\n this.isInitializing = false;\n \n this.debugLog(`VijiCore initialized successfully (${this.instanceId}):`, {\n resolution: `${effectiveResolution.width}x${effectiveResolution.height}`,\n frameRateMode: this.config.frameRateMode,\n hasAudio: !!this.config.audioStream,\n hasVideo: !!this.config.videoStream\n });\n } catch (error) {\n // Clean up on initialization failure\n this.isInitializing = false;\n await this.cleanup();\n \n throw new VijiCoreError(\n `Failed to initialize VijiCore: ${error}`,\n 'INITIALIZATION_ERROR',\n { error, config: this.config }\n );\n }\n }\n\n /**\n * Creates canvas with retry logic to handle timing issues\n */\n private async createCanvasWithRetry(): Promise<OffscreenCanvas> {\n const maxRetries = 3; // Reduced retries since we have better error handling\n const retryDelay = 200;\n \n for (let i = 0; i < maxRetries; i++) {\n // Check if we should continue (not destroyed/destroyed during retry)\n if (this.isDestroyed || !this.isInitializing) {\n throw new VijiCoreError('Initialization cancelled', 'INITIALIZATION_CANCELLED');\n }\n \n if (!this.iframeManager) {\n throw new VijiCoreError('IFrameManager not available', 'MANAGER_NOT_READY');\n }\n \n try {\n return await this.iframeManager.createCanvas();\n } catch (error) {\n console.warn(`Canvas creation attempt ${i + 1}/${maxRetries} failed:`, error);\n \n if (i === maxRetries - 1) {\n // Last attempt failed\n throw error;\n }\n \n // Wait before retry\n await new Promise(resolve => setTimeout(resolve, retryDelay));\n }\n }\n \n throw new VijiCoreError('Canvas creation failed after all retries', 'CANVAS_CREATION_TIMEOUT');\n }\n\n /**\n * Sets up the interaction system for Phase 7\n */\n private setupInteractionSystem(): void {\n if (!this.iframeManager || !this.interactionManager) return;\n\n // Set up event forwarding from iframe to interaction manager\n this.iframeManager.onInteractionEvent('mouse-update', (data) => {\n this.interactionManager?.updateMouse(data);\n \n // Forward to worker if available\n if (this.workerManager) {\n this.workerManager.postMessage('mouse-update', data);\n }\n });\n\n this.iframeManager.onInteractionEvent('keyboard-update', (data) => {\n this.interactionManager?.updateKeyboard(data);\n \n // Forward to worker if available\n if (this.workerManager) {\n this.workerManager.postMessage('keyboard-update', data);\n }\n });\n\n this.iframeManager.onInteractionEvent('touch-update', (data) => {\n this.interactionManager?.updateTouch(data);\n \n // Forward to worker if available\n if (this.workerManager) {\n this.workerManager.postMessage('touch-update', data);\n }\n });\n\n // Enable interaction events on the iframe based on current state\n this.iframeManager.setInteractionEnabled(this.currentInteractionEnabled);\n }\n\n /**\n * Sets up communication between components\n */\n private setupCommunication(): void {\n if (!this.workerManager) return;\n\n // Handle worker ready event (separate from init response)\n this.workerManager.onMessage('ready', (data) => {\n this.debugLog('Worker ready:', data);\n // Capture rendererType from ready event\n if (data.rendererType !== undefined) {\n this.stats.rendererType = data.rendererType;\n }\n });\n\n this.workerManager.onMessage('error', (data) => {\n console.error('Worker error:', data);\n });\n\n this.workerManager.onMessage('performance-warning', (data) => {\n console.warn('Performance warning:', data);\n // TODO: Handle performance optimization in Phase 8\n });\n\n this.workerManager.onMessage('performance-update', (data) => {\n // Update stats with real-time performance data from worker\n if (data.effectiveRefreshRate !== undefined) {\n this.stats.frameRate.effectiveRefreshRate = data.effectiveRefreshRate;\n this.stats.frameRate.mode = data.frameRateMode;\n this.stats.frameRate.screenRefreshRate = data.screenRefreshRate;\n }\n if (data.rendererType !== undefined) {\n this.stats.rendererType = data.rendererType;\n }\n if (data.parameterCount !== undefined) {\n this.stats.parameterCount = data.parameterCount;\n }\n // Update CV stats if available\n if (data.cv !== undefined) {\n this.stats.cv = data.cv;\n }\n });\n\n // Parameter system message handlers for Phase 2\n this.workerManager.onMessage('parameters-defined', (data: ParameterDefinitionData) => {\n this.handleParametersDefined(data);\n });\n\n this.workerManager.onMessage('parameter-validation-error', (data) => {\n this.handleParameterError(data);\n });\n }\n\n // Parameter system implementation for Phase 2\n\n /**\n * Handle parameter definitions received from worker\n */\n private handleParametersDefined(data: ParameterDefinitionData): void {\n try {\n // Store parameter groups\n this.parameterGroups.clear();\n this.parameterValues.clear();\n\n for (const group of data.groups) {\n this.parameterGroups.set(group.groupName, group);\n \n // Initialize parameter values with defaults\n for (const [paramName, paramDef] of Object.entries(group.parameters)) {\n this.parameterValues.set(paramName, paramDef.defaultValue);\n }\n }\n\n this.parametersInitialized = true;\n \n this.debugLog(`Parameters initialized: ${this.parameterValues.size} parameters in ${this.parameterGroups.size} groups`);\n\n // Send initial parameter values to worker\n this.syncAllParametersToWorker();\n\n // Notify listeners that parameters are defined\n for (const listener of this.parameterDefinedListeners) {\n try {\n listener(Array.from(this.parameterGroups.values()));\n } catch (error) {\n console.error('Error in parameter defined listener:', error);\n }\n }\n } catch (error) {\n console.error('Error handling parameters defined:', error);\n this.handleParameterError({\n message: `Failed to process parameter definitions: ${(error as Error).message}`,\n code: 'PARAMETER_PROCESSING_ERROR'\n });\n }\n }\n\n /**\n * Handle parameter validation errors\n */\n private handleParameterError(error: { message: string; code: string }): void {\n console.error('Parameter error:', error);\n \n // Notify error listeners\n for (const listener of this.parameterErrorListeners) {\n try {\n listener(error);\n } catch (listenerError) {\n console.error('Error in parameter error listener:', listenerError);\n }\n }\n }\n\n /**\n * Get parameter definition by name\n */\n private getParameterDefinition(name: string): ParameterDefinition | undefined {\n for (const group of this.parameterGroups.values()) {\n if (group.parameters[name]) {\n return group.parameters[name];\n }\n }\n return undefined;\n }\n\n /**\n * Set a single parameter value\n * Handles all parameter types including images intelligently\n */\n async setParameter(name: string, value: ParameterValue | File | Blob): Promise<void> {\n this.validateReady();\n \n if (!this.parametersInitialized) {\n throw new VijiCoreError('Parameters not yet initialized', 'PARAMETERS_NOT_INITIALIZED');\n }\n\n if (!this.parameterValues.has(name)) {\n throw new VijiCoreError(`Unknown parameter: ${name}`, 'UNKNOWN_PARAMETER');\n }\n\n // Get parameter definition to check type\n const paramDef = this.getParameterDefinition(name);\n \n // Handle image parameters specially\n if (paramDef?.type === 'image') {\n await this.handleImageParameter(name, value);\n return;\n }\n\n // Handle standard parameters (number, boolean, string, color, etc.)\n const oldValue = this.parameterValues.get(name);\n this.parameterValues.set(name, value as ParameterValue);\n\n // Send to worker\n if (this.workerManager) {\n this.workerManager.postMessage('parameter-update', {\n name,\n value\n });\n }\n\n // Notify listeners if value changed\n if (oldValue !== value) {\n this.notifyParameterListeners(name, value as ParameterValue);\n }\n }\n\n /**\n * Internal method to handle image parameter loading and transfer\n * Loads the image on the host side and creates TWO ImageBitmaps:\n * - One for the host (listeners, previews)\n * - One to transfer to the worker\n */\n private async handleImageParameter(name: string, value: ParameterValue | File | Blob): Promise<void> {\n try {\n let hostImageBitmap: ImageBitmap | null = null;\n let workerImageBitmap: ImageBitmap | null = null;\n\n if (value === null || value === undefined) {\n // Clear the image parameter\n hostImageBitmap = null;\n workerImageBitmap = null;\n } else if (typeof value === 'string') {\n // Load from URL - create two ImageBitmaps from the same source\n const response = await fetch(value);\n const blob = await response.blob();\n // Create both bitmaps from the blob\n [hostImageBitmap, workerImageBitmap] = await Promise.all([\n createImageBitmap(blob),\n createImageBitmap(blob)\n ]);\n } else if (value instanceof File || value instanceof Blob) {\n // Load from File or Blob - create two ImageBitmaps from the same source\n [hostImageBitmap, workerImageBitmap] = await Promise.all([\n createImageBitmap(value),\n createImageBitmap(value)\n ]);\n } else if (value instanceof ImageBitmap) {\n // Already an ImageBitmap - need to clone it by drawing to canvas\n const canvas = document.createElement('canvas');\n canvas.width = value.width;\n canvas.height = value.height;\n const ctx = canvas.getContext('2d')!;\n ctx.drawImage(value, 0, 0);\n \n // Keep original for host, create new one from canvas for worker\n hostImageBitmap = value;\n workerImageBitmap = await createImageBitmap(canvas);\n } else {\n throw new Error(`Invalid value type for image parameter. Expected File, Blob, string (URL), or null.`);\n }\n\n // Update local value (store host copy)\n const oldValue = this.parameterValues.get(name);\n this.parameterValues.set(name, hostImageBitmap);\n\n // Send worker copy to worker using unified parameter-update message\n // Transfer worker ImageBitmap (host copy remains intact for listeners)\n if (this.workerManager) {\n const messageData = {\n name,\n value: workerImageBitmap\n };\n \n // Transfer worker ImageBitmap if present (more efficient than cloning)\n const transferList = workerImageBitmap ? [workerImageBitmap] : [];\n this.workerManager.postMessage('parameter-update', messageData, transferList);\n }\n\n // Notify listeners with host copy (not transferred, still usable)\n if (oldValue !== hostImageBitmap) {\n this.notifyParameterListeners(name, hostImageBitmap);\n }\n\n this.debugLog(`Image parameter '${name}' ${hostImageBitmap ? 'loaded' : 'cleared'} (${this.instanceId})`);\n } catch (error) {\n throw new VijiCoreError(\n `Failed to load image for parameter '${name}': ${error}`,\n 'IMAGE_LOAD_ERROR',\n { error, name }\n );\n }\n }\n\n /**\n * Set multiple parameter values efficiently\n */\n async setParameters(values: Record<string, ParameterValue>): Promise<void> {\n this.validateReady();\n \n if (!this.parametersInitialized) {\n throw new VijiCoreError('Parameters not yet initialized', 'PARAMETERS_NOT_INITIALIZED');\n }\n\n const updates: ParameterUpdateData[] = [];\n const changedParams: Array<{ name: string; value: ParameterValue }> = [];\n\n // Prepare updates\n for (const [name, value] of Object.entries(values)) {\n if (!this.parameterValues.has(name)) {\n console.warn(`Unknown parameter: ${name}`);\n continue;\n }\n\n const oldValue = this.parameterValues.get(name);\n this.parameterValues.set(name, value);\n \n updates.push({\n name,\n value\n });\n\n if (oldValue !== value) {\n changedParams.push({ name, value });\n }\n }\n\n // Send batch update to worker\n if (updates.length > 0 && this.workerManager) {\n this.workerManager.postMessage('parameter-batch-update', {\n updates\n });\n }\n\n // Notify listeners for changed parameters\n for (const { name, value } of changedParams) {\n this.notifyParameterListeners(name, value);\n }\n }\n\n /**\n * Get current parameter value\n */\n getParameter(name: string): ParameterValue | undefined {\n return this.parameterValues.get(name);\n }\n\n /**\n * Get all current parameter values\n */\n getParameterValues(): Record<string, ParameterValue> {\n const values: Record<string, ParameterValue> = {};\n for (const [name, value] of this.parameterValues) {\n values[name] = value;\n }\n return values;\n }\n\n /**\n * Get parameter groups (for UI generation)\n */\n getParameterGroups(): ParameterGroup[] {\n return Array.from(this.parameterGroups.values());\n }\n\n /**\n * Get current core capabilities (what's currently active)\n */\n getCapabilities(): CoreCapabilities {\n return {\n hasAudio: this.currentAudioStream !== null,\n hasVideo: this.currentVideoStream !== null,\n hasInteraction: this.currentInteractionEnabled,\n hasGeneral: true // General parameters are always available\n };\n }\n\n /**\n * Get parameter groups filtered by active capabilities\n */\n getVisibleParameterGroups(): ParameterGroup[] {\n const capabilities = this.getCapabilities();\n const allGroups = this.getParameterGroups();\n \n return allGroups.filter(group => {\n // Filter based on group category\n switch (group.category) {\n case 'audio':\n return capabilities.hasAudio;\n case 'video':\n return capabilities.hasVideo;\n case 'interaction':\n return capabilities.hasInteraction;\n case 'general':\n default:\n return capabilities.hasGeneral;\n }\n }).map(group => ({\n ...group,\n // Also filter individual parameters within groups\n parameters: Object.fromEntries(\n Object.entries(group.parameters).filter(([_, paramDef]) => {\n switch (paramDef.category) {\n case 'audio':\n return capabilities.hasAudio;\n case 'video':\n return capabilities.hasVideo;\n case 'interaction':\n return capabilities.hasInteraction;\n case 'general':\n default:\n return capabilities.hasGeneral;\n }\n })\n )\n }));\n }\n\n /**\n * Get all parameter groups without capability filtering.\n * Returns a deep-cloned structure to prevent external mutation.\n */\n getAllParameterGroups(): ParameterGroup[] {\n const allGroups = this.getParameterGroups();\n return allGroups.map(group => ({\n ...group,\n parameters: Object.fromEntries(\n Object.entries(group.parameters).map(([name, def]) => {\n const clonedDef: any = { ...def };\n if (def.config) {\n clonedDef.config = { ...def.config };\n }\n return [name, clonedDef];\n })\n )\n }));\n }\n\n /**\n * Check if a specific parameter category is currently active\n */\n isCategoryActive(category: ParameterCategory): boolean {\n const capabilities = this.getCapabilities();\n switch (category) {\n case 'audio':\n return capabilities.hasAudio;\n case 'video':\n return capabilities.hasVideo;\n case 'interaction':\n return capabilities.hasInteraction;\n case 'general':\n default:\n return capabilities.hasGeneral;\n }\n }\n\n /**\n * Check if parameters have been initialized\n */\n get parametersReady(): boolean {\n return this.parametersInitialized;\n }\n\n /**\n * Send all current parameter values to worker (used for initial sync)\n */\n private syncAllParametersToWorker(): void {\n if (!this.workerManager || this.parameterValues.size === 0) {\n return;\n }\n\n const updates: ParameterUpdateData[] = [];\n for (const [name, value] of this.parameterValues) {\n updates.push({\n name,\n value\n });\n }\n\n this.workerManager.postMessage('parameter-batch-update', {\n updates\n });\n\n this.debugLog(`Synced ${updates.length} parameter values to worker`);\n }\n\n /**\n * Add listener for when parameters are defined\n */\n onParametersDefined(listener: (groups: ParameterGroup[]) => void): void {\n this.parameterDefinedListeners.add(listener);\n }\n\n /**\n * Remove parameter defined listener\n */\n offParametersDefined(listener: (groups: ParameterGroup[]) => void): void {\n this.parameterDefinedListeners.delete(listener);\n }\n\n /**\n * Add listener for parameter value changes\n */\n onParameterChange(parameterName: string, listener: (value: ParameterValue) => void): void {\n if (!this.parameterListeners.has(parameterName)) {\n this.parameterListeners.set(parameterName, new Set());\n }\n this.parameterListeners.get(parameterName)!.add(listener);\n }\n\n /**\n * Remove parameter change listener\n */\n offParameterChange(parameterName: string, listener: (value: ParameterValue) => void): void {\n const listeners = this.parameterListeners.get(parameterName);\n if (listeners) {\n listeners.delete(listener);\n if (listeners.size === 0) {\n this.parameterListeners.delete(parameterName);\n }\n }\n }\n\n /**\n * Add listener for parameter errors\n */\n onParameterError(listener: (error: { message: string; code: string }) => void): void {\n this.parameterErrorListeners.add(listener);\n }\n\n /**\n * Add listener for when core capabilities change (audio/video/interaction state)\n */\n onCapabilitiesChange(listener: (capabilities: CoreCapabilities) => void): void {\n this.capabilitiesChangeListeners.add(listener);\n }\n\n /**\n * Remove capabilities change listener\n */\n removeCapabilitiesListener(listener: (capabilities: CoreCapabilities) => void): void {\n this.capabilitiesChangeListeners.delete(listener);\n }\n\n /**\n * Notify capability change listeners\n */\n private notifyCapabilitiesChange(): void {\n const capabilities = this.getCapabilities();\n for (const listener of this.capabilitiesChangeListeners) {\n try {\n listener(capabilities);\n } catch (error) {\n console.error('Error in capabilities change listener:', error);\n }\n }\n }\n\n /**\n * Remove parameter error listener\n */\n offParameterError(listener: (error: { message: string; code: string }) => void): void {\n this.parameterErrorListeners.delete(listener);\n }\n\n /**\n * Notify parameter change listeners\n */\n private notifyParameterListeners(name: string, value: ParameterValue): void {\n const listeners = this.parameterListeners.get(name);\n if (listeners) {\n for (const listener of listeners) {\n try {\n listener(value);\n } catch (error) {\n console.error(`Error in parameter listener for '${name}':`, error);\n }\n }\n }\n }\n\n /**\n * Sets the scene frame rate mode\n * @param mode - 'full' for every animation frame, 'half' for every second frame\n */\n async setFrameRate(mode: FrameRateMode): Promise<void> {\n this.validateReady();\n \n this.config.frameRateMode = mode;\n \n // Send frame rate update to worker\n if (this.workerManager) {\n this.workerManager.postMessage('frame-rate-update', { mode });\n }\n \n // Update stats\n this.updateFrameRateStats();\n \n this.debugLog(`Scene frame rate set to ${mode} (${this.instanceId})`);\n }\n\n /**\n * Sets the CV processing frame rate mode (relative to scene frame rate)\n * @param mode - CV processing rate: 'full', 'half', 'quarter', or 'eighth' of scene rate\n */\n async setCVFrameRate(mode: CVFrameRateMode): Promise<void> {\n this.validateReady();\n \n // Send CV frame rate update to worker\n if (this.workerManager) {\n this.workerManager.postMessage('cv-frame-rate-update', { mode });\n }\n \n this.debugLog(`CV frame rate set to ${mode} of scene rate (${this.instanceId})`);\n }\n\n\n /**\n * Updates the canvas resolution by sending effective dimensions to the worker\n */\n updateResolution() {\n this.validateReady();\n \n if (!this.iframeManager || !this.workerManager) {\n throw new VijiCoreError('Managers not available', 'MANAGERS_NOT_READY');\n }\n\n const effectiveResolution = this.iframeManager.getEffectiveResolution();\n this.workerManager.postMessage('resolution-update', {\n effectiveWidth: effectiveResolution.width,\n effectiveHeight: effectiveResolution.height\n });\n\n // Update stats\n this.stats.resolution = effectiveResolution;\n this.stats.scale = this.iframeManager.getScale();\n \n this.debugLog(`Resolution updated successfully (${this.instanceId})`, effectiveResolution);\n }\n\n /**\n * Sets the audio stream for analysis\n */\n async setAudioStream(audioStream: MediaStream | null): Promise<void> {\n // Don't validate ready during initialization\n if (this.isInitialized && !this.isInitializing) {\n this.validateReady();\n }\n \n // Store current stream and track capability change\n const previouslyHadAudio = this.currentAudioStream !== null;\n this.currentAudioStream = audioStream;\n const nowHasAudio = this.currentAudioStream !== null;\n \n // Process audio on host side using AudioSystem\n if (this.audioSystem) {\n this.audioSystem.handleAudioStreamUpdate({\n audioStream: audioStream,\n ...(this.config.analysisConfig && { analysisConfig: this.config.analysisConfig }),\n timestamp: performance.now()\n });\n }\n \n // Notify capabilities change if audio state changed\n if (previouslyHadAudio !== nowHasAudio) {\n this.notifyCapabilitiesChange();\n }\n \n this.debugLog(`Audio stream ${audioStream ? 'connected' : 'disconnected'} (${this.instanceId})`);\n }\n\n /**\n * Sets the video stream for processing\n */\n async setVideoStream(videoStream: MediaStream | null): Promise<void> {\n // Don't validate ready during initialization\n if (this.isInitialized && !this.isInitializing) {\n this.validateReady();\n }\n \n // Store current stream and track capability change\n const previouslyHadVideo = this.currentVideoStream !== null;\n this.currentVideoStream = videoStream;\n const nowHasVideo = this.currentVideoStream !== null;\n \n // Process video on host side using VideoCoordinator\n if (this.videoCoordinator) {\n this.videoCoordinator.handleVideoStreamUpdate({\n videoStream: videoStream,\n targetFrameRate: 30, // Default target FPS\n timestamp: performance.now()\n });\n }\n \n // Notify capabilities change if video state changed\n if (previouslyHadVideo !== nowHasVideo) {\n this.notifyCapabilitiesChange();\n }\n \n this.debugLog(`Video stream ${videoStream ? 'connected' : 'disconnected'} (${this.instanceId})`);\n }\n\n /**\n * Gets the current audio stream\n */\n getAudioStream(): MediaStream | null {\n return this.currentAudioStream;\n }\n\n /**\n * Gets the current video stream\n */\n getVideoStream(): MediaStream | null {\n return this.currentVideoStream;\n }\n\n /**\n * Enables or disables user interactions (mouse, keyboard, touch) at runtime\n */\n async setInteractionEnabled(enabled: boolean): Promise<void> {\n // Don't validate ready during initialization\n if (this.isInitialized && !this.isInitializing) {\n this.validateReady();\n }\n \n // Track capability change\n const previouslyHadInteraction = this.currentInteractionEnabled;\n this.currentInteractionEnabled = enabled;\n \n // Enable/disable interaction capture in IFrameManager\n if (this.iframeManager) {\n this.iframeManager.setInteractionEnabled(enabled);\n }\n \n // Notify worker about interaction state change\n if (this.workerManager) {\n this.workerManager.postMessage('interaction-enabled', { enabled });\n }\n \n // Notify capabilities change if interaction state changed\n if (previouslyHadInteraction !== enabled) {\n this.notifyCapabilitiesChange();\n }\n \n this.debugLog(`Interaction ${enabled ? 'enabled' : 'disabled'} (${this.instanceId})`);\n }\n\n /**\n * Gets the current interaction enabled state\n */\n getInteractionEnabled(): boolean {\n return this.currentInteractionEnabled;\n }\n\n /**\n * Updates audio analysis configuration\n */\n async setAudioAnalysisConfig(config: { fftSize?: number; smoothing?: number }): Promise<void> {\n this.validateReady();\n \n // Update config\n this.config.analysisConfig = { ...this.config.analysisConfig, ...config };\n \n // Update config in host-side AudioSystem\n if (this.audioSystem) {\n this.audioSystem.handleAudioStreamUpdate({\n audioStream: this.currentAudioStream,\n ...(this.config.analysisConfig && { analysisConfig: this.config.analysisConfig }),\n timestamp: performance.now()\n });\n }\n \n this.debugLog(`Audio analysis config updated (${this.instanceId})`, config);\n }\n\n /**\n * Updates the canvas resolution by scale\n */\n setResolution(scale: number) {\n this.validateReady();\n \n if (!this.iframeManager || !this.workerManager) {\n throw new VijiCoreError('Managers not available', 'MANAGERS_NOT_READY');\n }\n \n this.debugLog(`Updating resolution scale to:`, scale, `(${this.instanceId})`);\n \n // Update resolution setting\n const effectiveResolution = this.iframeManager.updateScale(scale);\n \n // Send resolution update to worker\n this.workerManager.postMessage('resolution-update', {\n effectiveWidth: effectiveResolution.width,\n effectiveHeight: effectiveResolution.height\n });\n \n // Update stats\n this.stats.resolution = effectiveResolution;\n this.stats.scale = scale;\n \n this.debugLog(`Resolution updated successfully (${this.instanceId})`, effectiveResolution);\n }\n\n /**\n * Detects the screen refresh rate\n */\n private async detectScreenRefreshRate(): Promise<void> {\n return new Promise((resolve) => {\n let frameCount = 0;\n let startTime = performance.now();\n \n const measureFrames = () => {\n frameCount++;\n if (frameCount === 60) { // Measure for 60 frames\n const elapsed = performance.now() - startTime;\n this.screenRefreshRate = Math.round(60000 / elapsed); // Convert to FPS\n this.debugLog('Detected screen refresh rate:', this.screenRefreshRate + 'Hz');\n resolve();\n } else if (frameCount < 60) {\n requestAnimationFrame(measureFrames);\n }\n };\n \n requestAnimationFrame(measureFrames);\n });\n }\n\n /**\n * Updates frame rate statistics\n */\n private updateFrameRateStats(): void {\n this.stats.frameRate = {\n mode: this.config.frameRateMode,\n screenRefreshRate: this.screenRefreshRate,\n effectiveRefreshRate: 0 // Will be updated by worker during execution\n };\n }\n\n /**\n * Gets current performance statistics\n */\n getStats(): PerformanceStats {\n this.validateReady();\n \n if (!this.iframeManager) {\n throw new VijiCoreError('IFrame manager not available', 'MANAGER_NOT_READY');\n }\n \n return this.stats;\n }\n\n\n /**\n * Checks if the core is ready for use\n */\n get ready(): boolean {\n return this.isInitialized && \n !this.isDestroyed && \n this.iframeManager?.ready === true && \n this.workerManager?.ready === true;\n }\n\n /**\n * Gets the current configuration\n */\n get configuration(): Readonly<VijiCoreConfig> {\n return { ...this.config };\n }\n\n /**\n * Destroys the core instance and cleans up all resources\n */\n async destroy(): Promise<void> {\n if (this.isDestroyed) {\n return; // Already destroyed\n }\n \n this.isDestroyed = true;\n \n // Clear parameter system\n this.parameterGroups.clear();\n this.parameterValues.clear();\n this.parameterListeners.clear();\n this.parameterDefinedListeners.clear();\n this.parameterErrorListeners.clear();\n this.capabilitiesChangeListeners.clear();\n \n // Clean up audio system\n if (this.audioSystem) {\n this.audioSystem.resetAudioState();\n this.audioSystem = null;\n }\n this.currentAudioStream = null;\n \n // Clean up video coordinator\n if (this.videoCoordinator) {\n this.videoCoordinator.resetVideoState();\n this.videoCoordinator = null;\n }\n this.currentVideoStream = null;\n \n await this.cleanup();\n \n this.debugLog(`VijiCore destroyed (${this.instanceId})`);\n }\n\n /**\n * Validates that the core is ready for operations\n */\n private validateReady(): void {\n if (this.isDestroyed) {\n throw new VijiCoreError('Core instance has been destroyed', 'INSTANCE_DESTROYED');\n }\n \n if (!this.ready) {\n throw new VijiCoreError('Core is not ready', 'CORE_NOT_READY');\n }\n }\n\n /**\n * Validates the provided configuration\n */\n private validateConfig(config: VijiCoreConfig): void {\n if (!config.hostContainer) {\n throw new VijiCoreError('hostContainer is required', 'INVALID_CONFIG');\n }\n \n if (!config.sceneCode || typeof config.sceneCode !== 'string') {\n throw new VijiCoreError('sceneCode must be a non-empty string', 'INVALID_CONFIG');\n }\n \n if (config.frameRateMode !== undefined && config.frameRateMode !== 'full' && config.frameRateMode !== 'half') {\n throw new VijiCoreError('frameRateMode must be either \"full\" or \"half\"', 'INVALID_CONFIG');\n }\n }\n\n /**\n * Cleans up all resources\n */\n private async cleanup(): Promise<void> {\n try {\n // Destroy worker first to stop rendering\n if (this.workerManager) {\n this.workerManager.destroy();\n this.workerManager = null;\n }\n \n // Destroy IFrame\n if (this.iframeManager) {\n this.iframeManager.destroy();\n this.iframeManager = null;\n }\n \n this.isInitialized = false;\n this.isInitializing = false;\n } catch (error) {\n console.warn('Error during cleanup:', error);\n }\n }\n} ","// Main VijiCore class\r\nexport { VijiCore } from './VijiCore.js';\r\n\r\n// Public types and interfaces\r\nexport type {\r\n VijiCoreConfig,\r\n Resolution,\r\n CaptureFrameOptions,\r\n ParameterGroup,\r\n ParameterDefinition,\r\n ParameterConfig,\r\n AnalysisConfiguration,\r\n FrequencyBand,\r\n PerformanceStats,\r\n VijiAPI,\r\n AudioAPI,\r\n VideoAPI,\r\n FaceData,\r\n HandData,\r\n MouseAPI,\r\n KeyboardAPI,\r\n TouchAPI,\r\n ParameterAPI\r\n} from './types/index.js';\r\n\r\n// Error class\r\nexport { VijiCoreError } from './types/index.js';\r\n\r\n// Version information\r\nexport const VERSION = '0.2.14'; "],"names":["VijiWorker"],"mappings":"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"}
|