diff --git a/index.html b/index.html index 92b0fac..45cbd04 100644 --- a/index.html +++ b/index.html @@ -191,6 +191,14 @@

TIMECODE

+
+ + +

Connection

@@ -346,4 +354,4 @@

Color

- \ No newline at end of file + diff --git a/style.css b/style.css index e71a457..f1c75b1 100644 --- a/style.css +++ b/style.css @@ -467,4 +467,25 @@ table, td { td, tr { align-items: center; -} \ No newline at end of file +} + +/* video preview */ + +#videocontainer { + width: 400px; + height: 250px; + background: white; + position: absolute; + left: 800px; +} + +#videopreview { + +} + + +#webcamSelect { + top: -160px; + position: relative; + left: -300px; +} diff --git a/web-ui.js b/web-ui.js index dc7b71e..038857a 100644 --- a/web-ui.js +++ b/web-ui.js @@ -11,14 +11,36 @@ var ci = 0; // Index into this array for the currently selected came // cameras[ci] is used to reference the currently selected camera object var WBMode = 0; // 0: balance, 1: tint +let PreviewCam = -1; // which camera to use for preview. -1: none +let currentStream; // current preview USB webcam stream + var defaultControlsHTML; var unsavedChanges = []; // Set everything up -function bodyOnLoad() { +async function bodyOnLoad() { defaultControlsHTML = document.getElementById("allCamerasContainer").innerHTML; + try { + await navigator.mediaDevices.getUserMedia({ video: true }); + } catch (err) { + console.error("Error acessing video devices:", err); + } + try { + const devices = await navigator.mediaDevices.enumerateDevices(); + const videoDevices = devices.filter(device => device.kind === 'videoinput'); + const select = document.getElementById('webcamSelect'); + videoDevices.forEach((device, index) => { + const option = document.createElement('option'); + // Use the device label if available; if not, fallback to a generic name. + option.text = device.label || `Camera ${index + 1}`; + option.value = device.deviceId; + select.appendChild(option); + }); + } catch (err) { + console.error("Error enumerating devices:", err); + } } // Checks the hostname, if it replies successfully then a new BMCamera object @@ -633,6 +655,27 @@ function loopHandler(callerString) { cameras[ci].PUTdata("/transports/0/playback", playbackState); } +async function SelectPreviewCamera() { + let previewcam = document.getElementById('webcamSelect').value; + if (currentStream) { + currentStream.getTracks().forEach(track => track.stop()); + } + + const constraints = { + video: { + deviceId: previewcam ? { exact: previewcam } : undefined + } + }; + try { + currentStream = await navigator.mediaDevices.getUserMedia(constraints); + const video = document.getElementById('videopreview'); + video.srcObject = currentStream; + } catch (err) { + console.error("Error starting video stream:", err); + } +} + + /* Helper Functions */ function parseTimecode(timecodeBCD) { let noDropFrame = timecodeBCD & 0b01111111111111111111111111111111; // The first bit of the timecode is 1 if "Drop Frame Timecode" is on. We don't want to include that in the display. @@ -640,4 +683,5 @@ function parseTimecode(timecodeBCD) { let decimalTCString = decimalTCInt.toString().padStart(8, '0'); // Convert the base ten number to a string eight characters long let finalTCString = decimalTCString.match(/.{1,2}/g).join(':'); // Put colons between every two characters return finalTCString; -} \ No newline at end of file +} +