BM-Camera-Control-WebUI/index.html
2024-07-02 14:53:25 -07:00

343 lines
No EOL
21 KiB
HTML

<!-- (c) 2024 Dylan Speiser -->
<!DOCTYPE html>
<html>
<head>
<!-- Page title and metadata -->
<title>Blackmagic Camera Control WebUI</title>
<meta charset="UTF-8">
<meta name="description" content="JS-based web interface for controlling Blackmagic Design cameras via the official REST API">
<meta name="author" content="Dylan Speiser">
<!-- Linking the stylesheet -->
<link rel="stylesheet" href="style.css">
</head>
<body onload="bodyOnLoad()">
<!-- JavaScript Linking -->
<script src="BMDevice.js"></script>
<script src="web-ui.js"></script>
<!------ Page Content ------>
<!-- Header Div -->
<div class="flexContainerH" id="headerContainer">
<h1>Blackmagic Camera Control WebUI</h1>
</div>
<!-- Camera Select Bar -->
<div class="flexContainerH" id="cameraSelectContainer">
<span class="cameraSwitchLabel selectedCam"><a href="#" onclick="switchCamera(0)">CAM1</a></span>
<span class="camSelectSeparator">|</span>
<span class="cameraSwitchLabel"><a href="#" onclick="switchCamera(1)">CAM2</a></span>
<span class="camSelectSeparator">|</span>
<span class="cameraSwitchLabel"><a href="#" onclick="switchCamera(2)">CAM3</a></span>
<span class="camSelectSeparator">|</span>
<span class="cameraSwitchLabel"><a href="#" onclick="switchCamera(3)">CAM4</a></span>
<span class="camSelectSeparator">|</span>
<span class="cameraSwitchLabel"><a href="#" onclick="switchCamera(4)">CAM5</a></span>
<span class="camSelectSeparator">|</span>
<span class="cameraSwitchLabel"><a href="#" onclick="switchCamera(5)">CAM6</a></span>
<span class="camSelectSeparator">|</span>
<span class="cameraSwitchLabel"><a href="#" onclick="switchCamera(6)">CAM7</a></span>
<span class="camSelectSeparator">|</span>
<span class="cameraSwitchLabel"><a href="#" onclick="switchCamera(7)">CAM8</a></span>
</div>
<!-- Camera Controls Box -->
<div class="flexContainerH" id="allCamerasContainer">
<div class="flexContainerV" id="cameraControlsContainer">
<div class="flexContainerH" id="cameraControlHeadContainer">
<h2 id="cameraNumberLabel">CAM1</h2>
</div>
<div class="flexContainerH" id="cameraControlColorCorrectionContainer">
<!-- <div class="flexContainerH" id="cameraControlLGGTabs">
<a href="#" class="ccTabLabel selectedTab" onclick="">Lift</a>
<a href="#" class="ccTabLabel" onclick="">Gamma</a>
<a href="#" class="ccTabLabel" onclick="">Gain</a>
</div> -->
<span style="margin-top: 0.5em;">Lift</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button class="CCResetButton circleButton" onclick="" title="Reset Lift">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" onkeydown="">0.00</span>
</div>
<button id="CCHamburgerButton" class="circleButton" onclick="" title="Set Lift">&#10138</button>
</div>
<span>Gamma</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button class="CCResetButton circleButton" onclick="" title="Reset Gamma">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" onkeydown="">0.00</span>
</div>
<button id="CCHamburgerButton" class="circleButton" onclick="" title="Set Gamma">&#10138</button>
</div>
<span>Gain</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button class="CCResetButton circleButton" onclick="" title="Reset Gain">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" onkeydown="">0.00</span>
</div>
<button id="CCHamburgerButton" class="circleButton" onclick="" title="Set Gain">&#10138</button>
</div>
<span>Offset</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button class="CCResetButton circleButton" onclick="" title="Reset Offset">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" onkeydown="">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" onkeydown="">0.00</span>
</div>
<button id="CCHamburgerButton" class="circleButton" onclick="" title="Set Offset">&#10138</button>
</div>
</div>
<div class="flexContainerH" id="cameraControlExposureContainer">
<div class="ccExposureSettingContainer">
<span class="exposureControlLabel">FILTER</span>
<div class="ccExposureSettingValueContainer">
<a class="expAdjArr" href="#" onclick="" id="NDL">&#9664</a>
<span id="ndFilterSpan" contenteditable="plaintext-only" onkeydown="">0</span>
<a class="expAdjArr" href="#" onclick="" id="NDR">&#9654</a>
</div>
</div>
<div class="ccExposureSettingContainer">
<span class="exposureControlLabel">GAIN</span>
<div class="ccExposureSettingValueContainer">
<a class="expAdjArr" href="#" onclick="" id="GAL">&#9664</a>
<span id="gainSpan" contenteditable="plaintext-only" onkeydown="">+0db</span>
<a class="expAdjArr" href="#" onclick="" id="GAR">&#9654</a>
</div>
</div>
<div class="ccExposureSettingContainer">
<span class="exposureControlLabel">SHUTTER</span>
<div class="ccExposureSettingValueContainer">
<a class="expAdjArr" href="#" onclick="" id="SHL">&#9664</a>
<span id="shutterSpan" contenteditable="plaintext-only" onkeydown="">1/50</span>
<a class="expAdjArr" href="#" onclick="" id="SHR">&#9654</a>
</div>
</div>
<div class="ccExposureSettingContainer">
<span class="exposureControlLabel" onclick="swapWBMode()" title="Click here to swap between WB and Tint" id="WBLabel">BALANCE</span>
<div class="ccExposureSettingValueContainer" id="WBValueContainer">
<a class="expAdjArr" href="#" onclick="" id="WBL">&#9664</a>
<span id="whiteBalanceSpan" contenteditable="plaintext-only" onkeydown="">5600K</span>
<a class="expAdjArr" href="#" onclick="" id="WBR">&#9654</a>
</div>
<div class="ccExposureSettingValueContainer dNone" id="WBTintValueContainer">
<a class="expAdjArr" href="#" onclick="" id="WBTL">&#9664</a>
<span id="whiteBalanceTintSpan" contenteditable="plaintext-only" onkeydown="">0</span>
<a class="expAdjArr" href="#" onclick="" id="WBLR">&#9654</a>
</div>
</div>
</div>
<div class="flexContainerH" id="cameraControlLensContainer">
<div class="lensSliderContainer">
<span>FOCUS</span>
<input type="range" orient="vertical" max="1" min="0" step="0.001" id="focusRange" onmouseup="">
<button id="AFButton" class="circleButton" onclick="">AF</button>
</div>
<div class="lensSliderContainer">
<span>IRIS</span>
<input type="range" orient="vertical" max="1" min="0" step="0.001" id="irisRange" onmouseup="">
<span id="apertureStopsLabel">X.X</span>
</div>
<div class="lensSliderContainer">
<span>ZOOM</span>
<input type="range" orient="vertical" max="1" min="0" step="0.001" id="zoomRange" onmouseup="">
<span id="zoomMMLabel">XXmm</span>
</div>
</div>
</div>
<div class="flexContainerV" id="cameraControlsContainerExpanded">
<div class="flexContainerH" id="cameraControlExpandedHeadContainer">
<h2 id="cameraName">CAMERA NAME</h2>
<div id="formatDisplay">
<span id="formatCodec">CODEC</span>
<span id="formatResolution">RESOLUTION</span>
<span id="formatFPS">FPS</span>
</div>
<div id="transportControls">
<!-- These will be sticky buttons for loop, single clip, record -->
<button class="circleButton" onclick="" title="Loop">&#8635</button>
<button class="circleButton" onclick="" title="Single Clip">S</button>
<button class="circleButton" onclick="" title="Back">&#9204</button>
<button class="circleButton" onclick="" title="Forward">&#9205</button>
<button class="circleButton" onclick="cameras[ci].toggleRecord()" title="Record">&#9210</button>
<button class="circleButton" onclick="cameras[ci].play()" title="Play">&#9654</button>
<button class="circleButton" onclick="cameras[ci].stop()" title="Stop">&#9209</button>
</div>
<h2 id="timecodeLabel">TIMECODE</h2>
</div>
<div class="flexContainerV" id="cameraControlExpandedBodyContainer">
<div class="tableControl">
<h3>Connection</h3>
<table>
<tr>
<td>Hostname</td>
<td>
<input type="text" placeholder="Studio-Camera-6K-Pro.local" id="hostnameInput">
<button onclick="initCamera()">Connect</button>
<span id="connectionErrorSpan"></span>
</td>
</tr>
<tr>
<td>Send API Call</td>
<td>
<input type="radio" id="requestTypeGET" value="GET" name="manualRequestType" checked>
<label for="requestTypeGET">GET</label>
<input type="radio" id="requestTypePUT" value="PUT" name="manualRequestType">
<label for="requestTypePUT">PUT</label>
<input type="text" id="manualRequestEndpointLabel" placeholder="request endpoint">
<input type="text" id="manualRequestBodyLabel" placeholder="request body">
<button onclick="manualAPICall()">Send API Request</button>
</td>
</tr>
<tr>
<td colspan="2">
<p id="manualRequestResponseP">Send manual API requests using the above controls. See <a href="https://documents.blackmagicdesign.com/DeveloperManuals/RESTAPIforBlackmagicCameras.pdf?_v=1696143610000" target="_blank" style="color: #6e6e6e;">documentation</a> for details.</p>
</td>
</tr>
</table>
</div>
<div class="tableControl">
<h3>Presets</h3>
<table>
<tr>
<td>Preset Select</td>
<td>
<select id="presetsDropDown" onchange="">
<!-- Auto-populated by updateUIPresets() -->
</select>
</td>
<td>
<button onclick="">Restore from Preset</button>
</td>
</tr>
</table>
</div>
<div class="tableControl">
<h3>Exposure</h3>
<table>
<tr>
<td>ISO</td>
<td><input type="number" id="ISOInput" step="100" onkeydown=""></td>
</tr>
<tr>
<td>AE Mode</td>
<td>
<select id="AEmodeDropDown">
<option value="Off">Off</option>
<option value="Continuous">Continuous</option>
<option value="OneShot">One-Shot</option>
</select>
</td>
</tr>
<tr>
<td>AE Type</td>
<td>
<select id="AEtypeDropDown">
<option value="">None</option>
<option value="Iris">Iris Only</option>
<option value="Shutter">Shutter Only</option>
<option value="Shutter,Iris">Shutter + Iris</option>
<option value="Iris,Shutter">Iris + Shutter</option>
</select>
</td>
</tr>
</table>
<button style="margin: 2vh 0 0 3.5vw;" onclick="">Set AE Mode</button>
</div>
<div class="tableControl">
<h3>Contrast</h3>
<table>
<tr>
<td>Pivot</td>
<td><input type="range" max="0" min="1" step="0.001" id="CCcontrastPivotRange" onmouseup=""></td>
<td>
<span id="CCcontrastPivotLabel" contenteditable="plaintext-only" onkeydown="">0</span>
</td>
<td rowspan="2">
<button class="CCResetButton circleButton" onclick="" title="Reset Contrast">&#10227</button>
</td>
</tr>
<tr>
<td>Adjust</td>
<td><input type="range" max="0" min="2" step="0.001" id="CCcontrastAdjustRange" onmouseup=""></td>
<td>
<span id="CCcontrastAdjustLabel" contenteditable="plaintext-only" onkeydown="">0</span>
</td>
</tr>
</table>
</div>
<div class="tableControl">
<h3>Color</h3>
<table>
<tr>
<td>Hue</td>
<td><input type="range" max="1" min="-1" step="0.001" id="CChueRange" onmouseup=""></td>
<td>
<span id="CCcolorHueLabel" contenteditable="plaintext-only" onkeydown="">0</span>
</td>
<td rowspan="3">
<button class="CCResetButton circleButton" onclick="" title="Reset Color">&#10227</button>
</td>
</tr>
<tr>
<td>Saturation</td>
<td><input type="range" max="2" min="0" step="0.001" id="CCsaturationRange" onmouseup=""></td>
<td>
<span id="CCcolorSatLabel" contenteditable="plaintext-only" onkeydown="">0</span>
</td>
</tr>
<tr>
<td>Luma Contribution</td>
<td><input type="range" max="1" min="0" step="0.001" id="CClumaContributionRange" onmouseup=""></td>
<td>
<span id="CCcolorLCLabel" contenteditable="plaintext-only" onkeydown="">0</span>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<!-- Footer Div -->
<div class="flexContainerH" id="footerContainer">
<div id="footerLeft">
<span class="">(v 1.1)</span>
</div>
<div id="footerLinks">
<span><a id="documentationLink" href="#" target="_blank">YAML Documentation</a></span>
<span><a id="mediaManagerLink" href="#" target="_blank">Web Media Manager</a></span>
<span><a id="githubLink" href="#" target="https://github.com/DylanSpeiser/BM-Camera-Control-WebUI">GitHub</a></span>
</div>
</div>
</body>
</html>