Almost there?

This commit is contained in:
DylanSpeiser-BMD 2024-06-13 14:46:46 -07:00
parent 3a5d570add
commit 8b7b191c74
4 changed files with 287 additions and 132 deletions

View file

@ -7,15 +7,8 @@ class BMDCamera {
// Camera index, used for muticam support // Camera index, used for muticam support
index; index;
// == TODO: Having trouble with the codec and video formats on the SC 6K Pro == // Codec and Video Formats (JSON object)
// Codec and Video Formats (JSON objects) format;
codecFormat;
videoFormat;
// Supported Codecs/Videos (arrays)
supportedCodecFormats;
supportedVideoFormats;
// ============================================================================
// Current Transport Mode (string) // Current Transport Mode (string)
transportMode; transportMode;
@ -92,15 +85,33 @@ class BMDCamera {
// Important refreshing function // Important refreshing function
refresh() { refresh() {
document.getElementById("refreshingText").classList.add("refreshing");
this.getAllInfo(); this.getAllInfo();
sleep(500).then(() => sleep(200).then(() => {
this.updateUIAll() this.updateUIAll();
document.getElementById("refreshingText").classList.remove("refreshing");
}
); );
} }
// Wrapper for API call, returns the JSON object from the camera // Wrapper for API call, returns the JSON object from the camera
async pullData(endpoint) { async pullData(endpoint) {
return await sendRequest("GET",this.APIAddress+endpoint,""); // Ask the camera a question
let response;
if (this.UnimplementedFunctionality.indexOf(endpoint) < 0) {
response = await sendRequest("GET",this.APIAddress+endpoint,"");
} else {
response = "Unimplemented";
}
// Check for unimplemented features
if (response.status == 501) {
this.UnimplementedFunctionality.push(endpoint);
response = "Unimplemented";
}
return response
} }
// Wrapper for API call, returns whatever the camera sent back in response // Wrapper for API call, returns whatever the camera sent back in response
@ -112,10 +123,7 @@ class BMDCamera {
updateUIAll() { updateUIAll() {
this.updateUIname(); this.updateUIname();
this.updateUIhostname(); this.updateUIhostname();
this.updateUICodecFormat(); this.updateUIFormat();
this.updateUIVideoFormat();
this.updateUISupportedCodecFormats();
this.updateUISupportedVideoFormats();
this.updateUITransportMode(); this.updateUITransportMode();
this.updateUIPlaybackState(); this.updateUIPlaybackState();
this.updateUIRecordState(); this.updateUIRecordState();
@ -143,20 +151,12 @@ class BMDCamera {
document.getElementById("hostnameInput").value = this.hostname; document.getElementById("hostnameInput").value = this.hostname;
} }
updateUICodecFormat() { updateUIFormat() {
//TBD document.getElementById("formatCodec").innerHTML = this.format.codec.toUpperCase().replace(":"," ").replace("_",":");
}
updateUIVideoFormat() { let resObj = this.format.recordResolution;
//TBD document.getElementById("formatResolution").innerHTML = resObj.width + "x" + resObj.height;
} document.getElementById("formatFPS").innerHTML = this.format.frameRate+" fps";
updateUISupportedCodecFormats() {
//TBD
}
updateUISupportedVideoFormats() {
//TBD
} }
updateUITransportMode() { updateUITransportMode() {
@ -178,18 +178,37 @@ class BMDCamera {
} }
updateUITimecode() { updateUITimecode() {
// Redo this to work with no leading 0 var tcString = parseInt(this.timecode.timecode.toString(16),10).toString().padStart(8,'0').match(/.{1,2}/g).join(':');
var tcString = parseInt(this.timecode.timecode.toString(16),10).toString().match(/.{1,2}/g).join(':');
document.getElementById("timecodeLabel").innerHTML = tcString; document.getElementById("timecodeLabel").innerHTML = tcString;
} }
updateUIPresets() { updateUIPresets() {
//TBD var presetsList = document.getElementById("presetsDropDown");
this.presets.forEach((presetItem) => {
let presetName = presetItem.split('.', 1);
if (!presetsList.contains(document.getElementsByName("presetOption"+presetName)[0])) {
let textNode = document.createTextNode(presetName);
let optionNode = document.createElement("option");
optionNode.setAttribute("name", "presetOption"+presetName);
optionNode.appendChild(textNode);
document.getElementById("presetsDropDown").appendChild(optionNode);
}
});
} }
updateUIActivePreset() { updateUIActivePreset() {
//TBD var presetsList = document.getElementById("presetsDropDown");
presetsList.childNodes.forEach((child) => {
if (child.nodeName == 'OPTION' && child.value == cameras[ci].activePreset) {
child.selected=true
} else {
child.selected=false
}
})
} }
updateUIAperture() { updateUIAperture() {
@ -224,6 +243,7 @@ class BMDCamera {
updateUIWhiteBalance() { updateUIWhiteBalance() {
document.getElementById("whiteBalanceSpan").innerHTML = this.WhiteBalance+"K"; document.getElementById("whiteBalanceSpan").innerHTML = this.WhiteBalance+"K";
document.getElementById("whiteBalanceTintSpan").innerHTML = this.WhiteBalanceTint;
} }
updateUINDStop() { updateUINDStop() {
@ -248,7 +268,11 @@ class BMDCamera {
} }
updateUIAutoExposureMode() { updateUIAutoExposureMode() {
//TBD let AEmodeSelect = document.getElementById("AEmodeDropDown");
let AEtypeSelect = document.getElementById("AEtypeDropDown");
AEmodeSelect.value = cameras[ci].AutoExposureMode.mode;
AEtypeSelect.value = cameras[ci].AutoExposureMode.type;
} }
updateUIColorCorrection() { updateUIColorCorrection() {
@ -275,6 +299,22 @@ class BMDCamera {
document.getElementsByClassName("CCredLabel")[3].innerHTML = this.CCoffset.red.toFixed(2); document.getElementsByClassName("CCredLabel")[3].innerHTML = this.CCoffset.red.toFixed(2);
document.getElementsByClassName("CCgreenLabel")[3].innerHTML = this.CCoffset.green.toFixed(2); document.getElementsByClassName("CCgreenLabel")[3].innerHTML = this.CCoffset.green.toFixed(2);
document.getElementsByClassName("CCblueLabel")[3].innerHTML = this.CCoffset.blue.toFixed(2); document.getElementsByClassName("CCblueLabel")[3].innerHTML = this.CCoffset.blue.toFixed(2);
// Contrast
document.getElementById("CCcontrastPivotRange").value = this.CCcontrast.pivot;
document.getElementById("CCcontrastPivotLabel").innerHTML = this.CCcontrast.pivot.toFixed(2);
document.getElementById("CCcontrastAdjustRange").value = this.CCcontrast.adjust;
document.getElementById("CCcontrastAdjustLabel").innerHTML = this.CCcontrast.adjust.toFixed(2);
// Color
document.getElementById("CChueRange").value = this.CCcolor.hue;
document.getElementById("CCcolorHueLabel").innerHTML = this.CCcolor.hue.toFixed(2);
document.getElementById("CCsaturationRange").value = this.CCcolor.saturation;
document.getElementById("CCcolorSatLabel").innerHTML = this.CCcolor.saturation.toFixed(2);
document.getElementById("CClumaContributionRange").value = this.CClumacontribution.lumaContribution;
document.getElementById("CCcolorLCLabel").innerHTML = this.CClumacontribution.lumaContribution.toFixed(2);
} }
updateUILinks() { updateUILinks() {
@ -286,20 +326,8 @@ class BMDCamera {
// name, hostname, APIaddress, index handled by constructor // name, hostname, APIaddress, index handled by constructor
getCodecFormat() { getFormat() {
this.pullData("/system/codecFormat").then((value) => {this.codecFormat = value; this.updateUICodecFormat()}); this.pullData("/system/format").then((value) => {this.format = value; this.updateUIFormat()});
}
getVideoFormat() {
this.pullData("/system/videoFormat").then((value) => {this.videoFormat = value; this.updateUIVideoFormat()});
}
getSupportedCodecFormats() {
this.pullData("/system/supportedCodecFormats").then((value) => {this.supportedCodecFormats = value; this.updateUISupportedCodecFormats()});
}
getSupportedVideoFormats() {
this.pullData("/system/supportedVideoFormats").then((value) => {this.supportedVideoFormats = value; this.updateUISupportedVideoFormats()});
} }
getTransportMode() { getTransportMode() {
@ -376,10 +404,7 @@ class BMDCamera {
} }
getAllInfo() { getAllInfo() {
this.getCodecFormat(); this.getFormat();
this.getVideoFormat();
this.getSupportedCodecFormats();
this.getSupportedVideoFormats();
this.getTransportMode(); this.getTransportMode();
this.getPlaybackState(); this.getPlaybackState();
this.getRecordState(); this.getRecordState();
@ -423,7 +448,11 @@ class BMDCamera {
} }
setActivePreset(presetString) { setActivePreset(presetString) {
this.pushData("/presets/active",{"preset": presetString}).then(() => sleep(1000).then(() => this.getActivePreset())); this.pushData("/presets/active",{"preset": presetString}).then(() => sleep(1000).then(() => this.refresh()));
}
updatePreset(presetString) {
this.pushData("/presets/active",{"preset": presetString}).then(() => sleep(1000).then(() => this.getPresets()));
} }
setAperture(apertureNormalisedFloat) { setAperture(apertureNormalisedFloat) {
@ -530,36 +559,18 @@ async function sendRequest(method, url, data) {
const xhttp = new XMLHttpRequest(); const xhttp = new XMLHttpRequest();
var responseObject; var responseObject;
// TODO: Add error code handling
xhttp.onload = function() { xhttp.onload = function() {
if (this.responseText) { if (this.status == 200) {
// Success w/ Data
responseObject = JSON.parse(this.responseText); responseObject = JSON.parse(this.responseText);
} else { } else {
responseObject = {"status": this.statusText}; // Pass along response data and stuff
responseObject = this;
} }
} }
// Don't keep making API calls for unimplemented features xhttp.open(method, url, false);
if (cameras[ci]) { xhttp.send(JSON.stringify(data));
// First check if the camera exists.
if (cameras[ci].UnimplementedFunctionality.indexOf(url) < 0) {
// If everything is honky dory
xhttp.open(method, url, false);
xhttp.send(JSON.stringify(data));
} else {
// If everything is not honky dory
// do nothing
}
if ((!responseObject) || (Object.hasOwn(responseObject,'error') && responseObject.error == "Not implemented for this device")) {
cameras[ci].UnimplementedFunctionality.push(url);
}
} else {
xhttp.open(method, url, false);
xhttp.send(JSON.stringify(data));
}
return responseObject; return responseObject;
} }

View file

@ -56,36 +56,36 @@
</div> --> </div> -->
<span style="margin-top: 0.5em;">Lift</span> <span style="margin-top: 0.5em;">Lift</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button id="CCResetButton" class="circleButton" onclick="resetCC(0)" title="Reset Lift">&#10227</button> <button class="CCResetButton circleButton" onclick="resetCC(0)" title="Reset Lift">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" oninput="setCCFromUI(0)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" oninput="setCCFromUI(0)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" oninput="setCCFromUI(0)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" oninput="setCCFromUI(0)">0.00</span>
</div> </div>
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(0)" title="Set Lift">&#10138</button> <button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(0)" title="Set Lift">&#10138</button>
</div> </div>
<span>Gamma</span> <span>Gamma</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button id="CCResetButton" class="circleButton" onclick="resetCC(1)" title="Reset Gamma">&#10227</button> <button class="CCResetButton circleButton" onclick="resetCC(1)" title="Reset Gamma">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" oninput="setCCFromUI(1)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" oninput="setCCFromUI(1)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" oninput="setCCFromUI(1)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" oninput="setCCFromUI(1)">0.00</span>
</div> </div>
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(1)" title="Set Gamma">&#10138</button> <button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(1)" title="Set Gamma">&#10138</button>
</div> </div>
<span>Gain</span> <span>Gain</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button id="CCResetButton" class="circleButton" onclick="resetCC(2)" title="Reset Gain">&#10227</button> <button class="CCResetButton circleButton" onclick="resetCC(2)" title="Reset Gain">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" oninput="setCCFromUI(2)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" oninput="setCCFromUI(2)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" oninput="setCCFromUI(2)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" oninput="setCCFromUI(2)">0.00</span>
</div> </div>
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(2)" title="Set Gain">&#10138</button> <button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(2)" title="Set Gain">&#10138</button>
</div> </div>
@ -93,12 +93,12 @@
<span>Offset</span> <span>Offset</span>
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
<button id="CCResetButton" class="circleButton" onclick="resetCC(3)" title="Reset Offset">&#10227</button> <button class="CCResetButton circleButton" onclick="resetCC(3)" title="Reset Offset">&#10227</button>
<div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer"> <div class="flexContainerH" id="cameraControlColorCorrectionNumbersContainer">
<span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #dbdbdb;" class="CClumaLabel" oninput="setCCFromUI(3)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #e64b3d;" class="CCredLabel" oninput="setCCFromUI(3)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #00a841;" class="CCgreenLabel" oninput="setCCFromUI(3)">0.00</span>
<span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel">0.00</span> <span contenteditable="plaintext-only" style="text-decoration-color: #2a78c8;" class="CCblueLabel" oninput="setCCFromUI(3)">0.00</span>
</div> </div>
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(3)" title="Set Offset">&#10138</button> <button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(3)" title="Set Offset">&#10138</button>
</div> </div>
@ -109,7 +109,7 @@
<span class="exposureControlLabel">FILTER</span> <span class="exposureControlLabel">FILTER</span>
<div class="ccExposureSettingValueContainer"> <div class="ccExposureSettingValueContainer">
<a class="expAdjArr" href="#" onclick="decreaseND()" id="NDL">&#9664</a> <a class="expAdjArr" href="#" onclick="decreaseND()" id="NDL">&#9664</a>
<span id="ndFilterSpan">0</span> <span id="ndFilterSpan" contenteditable="plaintext-only" oninput="cameras[ci].setND(parseInt(this.innerHTML))">0</span>
<a class="expAdjArr" href="#" onclick="increaseND()" id="NDR">&#9654</a> <a class="expAdjArr" href="#" onclick="increaseND()" id="NDR">&#9654</a>
</div> </div>
</div> </div>
@ -117,7 +117,7 @@
<span class="exposureControlLabel">GAIN</span> <span class="exposureControlLabel">GAIN</span>
<div class="ccExposureSettingValueContainer"> <div class="ccExposureSettingValueContainer">
<a class="expAdjArr" href="#" onclick="decreaseGain()" id="GAL">&#9664</a> <a class="expAdjArr" href="#" onclick="decreaseGain()" id="GAL">&#9664</a>
<span id="gainSpan">+0db</span> <span id="gainSpan" contenteditable="plaintext-only" oninput="cameras[ci].setGain(parseInt(this.innerHTML))">+0db</span>
<a class="expAdjArr" href="#" onclick="increaseGain()" id="GAR">&#9654</a> <a class="expAdjArr" href="#" onclick="increaseGain()" id="GAR">&#9654</a>
</div> </div>
</div> </div>
@ -125,17 +125,22 @@
<span class="exposureControlLabel">SHUTTER</span> <span class="exposureControlLabel">SHUTTER</span>
<div class="ccExposureSettingValueContainer"> <div class="ccExposureSettingValueContainer">
<a class="expAdjArr" href="#" onclick="decreaseShutter()" id="SHL">&#9664</a> <a class="expAdjArr" href="#" onclick="decreaseShutter()" id="SHL">&#9664</a>
<span id="shutterSpan">1/50</span> <span id="shutterSpan" contenteditable="plaintext-only" oninput="handleShutterInput(this.innerHTML)">1/50</span>
<a class="expAdjArr" href="#" onclick="increaseShutter()" id="SHR">&#9654</a> <a class="expAdjArr" href="#" onclick="increaseShutter()" id="SHR">&#9654</a>
</div> </div>
</div> </div>
<div class="ccExposureSettingContainer"> <div class="ccExposureSettingContainer">
<span class="exposureControlLabel">BALANCE</span> <span class="exposureControlLabel" onclick="swapWBMode()" id="WBLabel">BALANCE</span>
<div class="ccExposureSettingValueContainer"> <div class="ccExposureSettingValueContainer" id="WBValueContainer">
<a class="expAdjArr" href="#" onclick="decreaseWhiteBalance()" id="WBL">&#9664</a> <a class="expAdjArr" href="#" onclick="decreaseWhiteBalance()" id="WBL">&#9664</a>
<span id="whiteBalanceSpan">5600K</span> <span id="whiteBalanceSpan" contenteditable="plaintext-only" oninput="cameras[ci].setWhiteBalance(parseInt(this.innerHTML),cameras[ci].whiteBalanceTint)">5600K</span>
<a class="expAdjArr" href="#" onclick="increaseWhiteBalance()" id="WBR">&#9654</a> <a class="expAdjArr" href="#" onclick="increaseWhiteBalance()" id="WBR">&#9654</a>
</div> </div>
<div class="ccExposureSettingValueContainer dNone" id="WBTintValueContainer">
<a class="expAdjArr" href="#" onclick="decreaseWhiteBalanceTint()" id="WBTL">&#9664</a>
<span id="whiteBalanceTintSpan" contenteditable="plaintext-only" oninput="cameras[ci].setWhiteBalance(cameras[ci].whiteBalance,parseInt(this.innerHTML))">0</span>
<a class="expAdjArr" href="#" onclick="increaseWhiteBalanceTint()" id="WBLR">&#9654</a>
</div>
</div> </div>
</div> </div>
@ -162,14 +167,19 @@
<div class="flexContainerV" id="cameraControlsContainerExpanded"> <div class="flexContainerV" id="cameraControlsContainerExpanded">
<div class="flexContainerH" id="cameraControlExpandedHeadContainer"> <div class="flexContainerH" id="cameraControlExpandedHeadContainer">
<h2 id="cameraName">CAMERA NAME</h2> <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"> <div id="transportControls">
<!-- These will be sticky buttons for loop, single clip, record --> <!-- These will be sticky buttons for loop, single clip, record -->
<button class="circleButton" onclick="" title="Loop">&#8635</button> <!--<button class="circleButton" onclick="" title="Loop">&#8635</button>
<button class="circleButton" onclick="" title="Single Clip">S</button> <button class="circleButton" onclick="" title="Single Clip">S</button>
<button class="circleButton" onclick="" title="Back">&#9204</button> <button class="circleButton" onclick="" title="Back">&#9204</button>
<button class="circleButton" onclick="" title="Forward">&#9205</button> <button class="circleButton" onclick="" title="Forward">&#9205</button> -->
<button class="circleButton" onclick="cameras[ci].record()" title="Record">&#9210</button> <button class="circleButton" onclick="cameras[ci].record()" title="Record">&#9210</button>
<button class="circleButton" onclick="cameras[ci].play()" title="Play">&#9654</button> <!-- <button class="circleButton" onclick="cameras[ci].play()" title="Play">&#9654</button> -->
<button class="circleButton" onclick="cameras[ci].stopTransport(); cameras[ci].stopRecord();" title="Stop">&#9209</button> <button class="circleButton" onclick="cameras[ci].stopTransport(); cameras[ci].stopRecord();" title="Stop">&#9209</button>
</div> </div>
<h2 id="timecodeLabel">TIMECODE</h2> <h2 id="timecodeLabel">TIMECODE</h2>
@ -182,8 +192,9 @@
<tr> <tr>
<td>Hostname</td> <td>Hostname</td>
<td> <td>
<input type="text" value="Studio-Camera-6K-Pro.local" id="hostnameInput" onkeydown="textInputTrigger(this)"> <input type="text" value="Studio-Camera-6K-Pro.local" id="hostnameInput">
<button onclick='cameras[ci] = new BMDCamera(document.getElementById("hostnameInput").value,ci);'>Connect</button> <button onclick='initCamera(document.getElementById("hostnameInput").value, ci)'>Connect</button>
<span id="connectionErrorSpan"></span>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -200,6 +211,11 @@
<button onclick="manualAPICall()">Send API Request</button> <button onclick="manualAPICall()">Send API Request</button>
</td> </td>
</tr> </tr>
<tr>
<td colspan="2">
<p id="manualRequestResponseP">Send manual API requests using the above controls. See documentation for details.</p>
</td>
</tr>
</table> </table>
</div> </div>
@ -209,15 +225,13 @@
<tr> <tr>
<td>Preset Select</td> <td>Preset Select</td>
<td> <td>
<select id="presetsDropDown" onchange="console.log('Preset selected: '+this.value)"> <select id="presetsDropDown" onchange="cameras[ci].setActivePreset(this.value+'.cset')">
<option value="default">Default</option> <!-- Auto-populated by updateUIPresets() -->
<option value="other">other</option>
</select> </select>
</td> </td>
</tr> <td>
<tr> <button onclick="cameras[ci].setActivePreset(document.getElementById('presetsDropDown').value+'.cset')">Restore from Preset</button>
<td style="color: #727272;">Upload a preset file</td> </td>
<td><input type="file" id="presetFileInput"></td>
</tr> </tr>
</table> </table>
</div> </div>
@ -260,11 +274,20 @@
<table> <table>
<tr> <tr>
<td>Pivot</td> <td>Pivot</td>
<td><input type="range" max="1" min="0" step="0.001" id="CCcontrastPivotRange"></td> <td><input type="range" max="5" min="-5" step="0.001" id="CCcontrastPivotRange" onmouseup="cameras[ci].setCCContrast({'pivot': parseFloat(this.value)})"></td>
<td>
<span id="CCcontrastPivotLabel" contenteditable="plaintext-only" oninput="cameras[ci].setCCContrast({'pivot': parseFloat(this.innerHTML)})">0</span>
</td>
<td rowspan="2">
<button class="CCResetButton circleButton" onclick="resetCC(4)" title="Reset Contrast">&#10227</button>
</td>
</tr> </tr>
<tr> <tr>
<td>Adjust</td> <td>Adjust</td>
<td><input type="range" max="1" min="0" step="0.001" id="CCcontrastAdjustRange"></td> <td><input type="range" max="5" min="-5" step="0.001" id="CCcontrastAdjustRange" onmouseup="cameras[ci].setCCContrast({'adjust': parseFloat(this.value)})"></td>
<td>
<span id="CCcontrastAdjustLabel" contenteditable="plaintext-only" oninput="cameras[ci].setCCContrast({'adjust': parseFloat(this.innerHTML)})">0</span>
</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -274,15 +297,27 @@
<table> <table>
<tr> <tr>
<td>Hue</td> <td>Hue</td>
<td><input type="range" max="1" min="0" step="0.001" id="CChueRange"></td> <td><input type="range" max="1" min="-1" step="0.001" id="CChueRange" onmouseup="cameras[ci].setCCColor({'hue': parseFloat(this.value)})"></td>
<td>
<span id="CCcolorHueLabel" contenteditable="plaintext-only" oninput="cameras[ci].setCCColor({'hue': parseFloat(this.innerHTML)})">0</span>
</td>
<td rowspan="3">
<button class="CCResetButton circleButton" onclick="resetCC(5)" title="Reset Color">&#10227</button>
</td>
</tr> </tr>
<tr> <tr>
<td>Saturation</td> <td>Saturation</td>
<td><input type="range" max="1" min="0" step="0.001" id="CCsaturationRange"></td> <td><input type="range" max="2" min="0" step="0.001" id="CCsaturationRange" onmouseup="cameras[ci].setCCColor({'saturation': parseFloat(this.value)})"></td>
<td>
<span id="CCcolorSatLabel" contenteditable="plaintext-only" oninput="cameras[ci].setCCColor({'saturation': parseFloat(this.innerHTML)})">0</span>
</td>
</tr> </tr>
<tr> <tr>
<td>Luma Contribution</td> <td>Luma Contribution</td>
<td><input type="range" max="1" min="0" step="0.001" id="CClumaContributionRange"></td> <td><input type="range" max="1" min="0" step="0.001" id="CClumaContributionRange" onmouseup="cameras[ci].setCCLumaContribuion({'lumaContribution': parseFloat(this.value)})"></td>
<td>
<span id="CCcolorLCLabel" contenteditable="plaintext-only" oninput="cameras[ci].setCCLumaContribuion({'lumaContribution': parseFloat(this.innerHTML)})">0</span>
</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -293,7 +328,10 @@
<!-- Footer Div --> <!-- Footer Div -->
<div class="flexContainerH" id="footerContainer"> <div class="flexContainerH" id="footerContainer">
<button onclick="cameras.forEach((element) => {element.refresh()});">Refresh</button> <div id="footerLeft">
<button onclick="cameras.forEach((element) => {element.refresh()});">Refresh</button>
<span id="refreshingText" class="refreshing">Refreshing...</span>
</div>
<div id="footerLinks"> <div id="footerLinks">
<span><a id="documentationLink" href="#" target="_blank">YAML Documentation</a></span> <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="mediaManagerLink" href="#" target="_blank">Web Media Manager</a></span>

View file

@ -7,6 +7,10 @@
url('resources/NotoSansDisplay-VariableFont_wdth\,wght.ttf') format('truetype'); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */ url('resources/NotoSansDisplay-VariableFont_wdth\,wght.ttf') format('truetype'); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */
} }
.dNone {
display: none;
}
body { body {
font-family: 'NotoSansDisplay', sans-serif; font-family: 'NotoSansDisplay', sans-serif;
font-weight: 100; font-weight: 100;
@ -165,6 +169,10 @@ input[type=file]:focus {
scrollbar-color: #202020 #151515; scrollbar-color: #202020 #151515;
} }
#formatDisplay span {
margin: 0px 1em;
}
#footerContainer { #footerContainer {
background: #181818; background: #181818;
background: linear-gradient(0deg, #181818 0%, #303030 100%); background: linear-gradient(0deg, #181818 0%, #303030 100%);
@ -182,6 +190,14 @@ input[type=file]:focus {
font-size: x-small; font-size: x-small;
} }
#refreshingText.refreshing {
color: #606060ff;
}
#refreshingText {
color: #60606000;
}
#footerLinks span { #footerLinks span {
margin-right: 1.25vw; margin-right: 1.25vw;
} }
@ -379,6 +395,14 @@ h2 {
} }
#connectionErrorSpan {
color: #e64b3d;
}
#manualRequestResponseP {
color: #6e6e6e;
}
/* Table Controls */ /* Table Controls */
.tableControl { .tableControl {

View file

@ -1,7 +1,7 @@
/* Global variables */ /* Global variables */
var cameras = []; var cameras = [];
var ci = 0; var ci = 0;
var ccMode = 0; var WBMode = 0; // 0: balance, 1: tint
function bodyOnLoad() { function bodyOnLoad() {
let intervalIDOne = setInterval(timerCallFunction1, 1000); // Tem second timer for refreshing everything let intervalIDOne = setInterval(timerCallFunction1, 1000); // Tem second timer for refreshing everything
@ -10,10 +10,24 @@ function bodyOnLoad() {
let newCamHostname = document.getElementById("hostnameInput").value; let newCamHostname = document.getElementById("hostnameInput").value;
if (newCamHostname) { if (newCamHostname) {
cameras[ci] = new BMDCamera(newCamHostname,ci); initCamera(newCamHostname, ci);
} }
} }
function initCamera(hostname, ind) {
sendRequest("GET", "http://"+hostname+"/control/api/v1/system","").then((response) => {
if (response.status < 300) {
cameras[ci] = new BMDCamera(hostname, ind);
} else {
document.getElementById("connectionErrorSpan").innerHTML = response.statusText;
}
}).catch(error => {
document.getElementById("connectionErrorSpan").title = error;
document.getElementById("connectionErrorSpan").innerHTML = "Error "+error.code+": "+error.name+" (Your hostname is probably incorrect, hover for more details)";
});
}
// One Second Timer Call // One Second Timer Call
function timerCallFunction1() { function timerCallFunction1() {
if (cameras[ci]) { if (cameras[ci]) {
@ -34,12 +48,6 @@ function timerCallFunction10() {
} }
} }
function textInputTrigger(element) {
if (event.key === 'Enter') {
cameras[ci] = new BMDCamera(element.value, ci);
}
}
function switchCamera(index) { function switchCamera(index) {
ci = index; ci = index;
@ -79,6 +87,50 @@ function setCCMode(mode) {
} }
} }
function swapWBMode() {
if (WBMode == 0) {
// Balance
document.getElementById("WBLabel").innerHTML = "TINT";
document.getElementById("WBValueContainer").classList.add("dNone");
document.getElementById("WBTintValueContainer").classList.remove("dNone");
WBMode = 1;
} else {
//Tint
document.getElementById("WBLabel").innerHTML = "BALANCE";
document.getElementById("WBValueContainer").classList.remove("dNone");
document.getElementById("WBTintValueContainer").classList.add("dNone");
WBMode = 0;
}
}
function manualAPICall() {
const requestRadioGET = document.getElementById("requestTypeGET");
const requestEndpointText = document.getElementById("manualRequestEndpointLabel").value;
let requestData = "";
try {
requestData = JSON.parse(document.getElementById("manualRequestBodyLabel").value);
} catch (err) {
document.getElementById("manualRequestResponseP").innerHTML = err;
}
const requestMethod = (requestRadioGET.checked ? "GET" : "PUT");
const requestURL = cameras[ci].APIAddress+requestEndpointText;
sendRequest(requestMethod,requestURL,requestData).then((response) => {
// console.log("Manual API Call Response: ", response);
if (!response.status) {
document.getElementById("manualRequestResponseP").innerHTML = JSON.stringify(response);
} else {
document.getElementById("manualRequestResponseP").innerHTML = response.status+": "+response.statusText;
}
});
}
/* Control Calling Functions */ /* Control Calling Functions */
function decreaseND() { function decreaseND() {
@ -117,6 +169,16 @@ function increaseShutter() {
} }
} }
function handleShutterInput(inputString) {
let cam = cameras[ci];
if ('shutterSpeed' in cam.shutter) {
cam.setShutter({"shutterSpeed" :parseInt(inputString)});
} else {
cam.setShutter({"shutterAngle": parseInt(parseFloat(inputString)*100)});
}
}
function decreaseWhiteBalance() { function decreaseWhiteBalance() {
cameras[ci].setWhiteBalance(cameras[ci].WhiteBalance-50,cameras[ci].WhiteBalanceTint); cameras[ci].setWhiteBalance(cameras[ci].WhiteBalance-50,cameras[ci].WhiteBalanceTint);
} }
@ -125,6 +187,21 @@ function increaseWhiteBalance() {
cameras[ci].setWhiteBalance(cameras[ci].WhiteBalance+50,cameras[ci].WhiteBalanceTint); cameras[ci].setWhiteBalance(cameras[ci].WhiteBalance+50,cameras[ci].WhiteBalanceTint);
} }
function decreaseWhiteBalanceTint() {
cameras[ci].setWhiteBalance(cameras[ci].WhiteBalance,cameras[ci].WhiteBalanceTint-1);
}
function increaseWhiteBalanceTint() {
cameras[ci].setWhiteBalance(cameras[ci].WhiteBalance,cameras[ci].WhiteBalanceTint+1);
}
function AEmodeInputHandler() {
let AEmode = document.getElementById("AEmodeDropDown").value;
let AEtype = document.getElementById("AEtypeDropDown").value;
cameras[ci].setAutoExposureMode({mode: AEmode, type: AEtype});
}
// 0: lift, 1: gamma, 2: gain, 3: offset // 0: lift, 1: gamma, 2: gain, 3: offset
function setCCFromUI(which) { function setCCFromUI(which) {
let lumaFloat = parseFloat(document.getElementsByClassName("CClumaLabel")[which].innerHTML); let lumaFloat = parseFloat(document.getElementsByClassName("CClumaLabel")[which].innerHTML);
@ -145,7 +222,7 @@ function setCCFromUI(which) {
} }
} }
// 0: lift, 1: gamma, 2: gain, 3: offset // 0: lift, 1: gamma, 2: gain, 3: offset, 4: contrast, 5: color & LC
function resetCC(which) { function resetCC(which) {
if (which == 0) { if (which == 0) {
cameras[ci].setCCLift({"red": 0.0, "green": 0.0, "blue": 0.0, "luma": 0.0}); cameras[ci].setCCLift({"red": 0.0, "green": 0.0, "blue": 0.0, "luma": 0.0});
@ -153,8 +230,13 @@ function resetCC(which) {
cameras[ci].setCCGamma({"red": 0.0, "green": 0.0, "blue": 0.0, "luma": 0.0}); cameras[ci].setCCGamma({"red": 0.0, "green": 0.0, "blue": 0.0, "luma": 0.0});
} else if (which == 2) { } else if (which == 2) {
cameras[ci].setCCGain({"red": 1.0, "green": 1.0, "blue": 1.0, "luma": 1.0}); cameras[ci].setCCGain({"red": 1.0, "green": 1.0, "blue": 1.0, "luma": 1.0});
} else { } else if (which == 3) {
cameras[ci].setCCOffset({"red": 0.0, "green": 0.0, "blue": 0.0, "luma": 0.0}); cameras[ci].setCCOffset({"red": 0.0, "green": 0.0, "blue": 0.0, "luma": 0.0});
} else if (which == 4) {
cameras[ci].setCCContrast({"pivot": 0.0, "adjust": 1.0});
} else if (which == 5) {
cameras[ci].setCCColor({"hue": 0.0, "saturation": 1.0});
cameras[ci].setCCLumaContribuion({"lumaContribution": 1.0});
} }
} }