Almost there?
This commit is contained in:
parent
3a5d570add
commit
8b7b191c74
4 changed files with 287 additions and 132 deletions
|
|
@ -7,15 +7,8 @@ class BMDCamera {
|
|||
// Camera index, used for muticam support
|
||||
index;
|
||||
|
||||
// == TODO: Having trouble with the codec and video formats on the SC 6K Pro ==
|
||||
// Codec and Video Formats (JSON objects)
|
||||
codecFormat;
|
||||
videoFormat;
|
||||
|
||||
// Supported Codecs/Videos (arrays)
|
||||
supportedCodecFormats;
|
||||
supportedVideoFormats;
|
||||
// ============================================================================
|
||||
// Codec and Video Formats (JSON object)
|
||||
format;
|
||||
|
||||
// Current Transport Mode (string)
|
||||
transportMode;
|
||||
|
|
@ -92,15 +85,33 @@ class BMDCamera {
|
|||
|
||||
// Important refreshing function
|
||||
refresh() {
|
||||
document.getElementById("refreshingText").classList.add("refreshing");
|
||||
this.getAllInfo();
|
||||
sleep(500).then(() =>
|
||||
this.updateUIAll()
|
||||
sleep(200).then(() => {
|
||||
this.updateUIAll();
|
||||
document.getElementById("refreshingText").classList.remove("refreshing");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Wrapper for API call, returns the JSON object from the camera
|
||||
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
|
||||
|
|
@ -112,10 +123,7 @@ class BMDCamera {
|
|||
updateUIAll() {
|
||||
this.updateUIname();
|
||||
this.updateUIhostname();
|
||||
this.updateUICodecFormat();
|
||||
this.updateUIVideoFormat();
|
||||
this.updateUISupportedCodecFormats();
|
||||
this.updateUISupportedVideoFormats();
|
||||
this.updateUIFormat();
|
||||
this.updateUITransportMode();
|
||||
this.updateUIPlaybackState();
|
||||
this.updateUIRecordState();
|
||||
|
|
@ -143,20 +151,12 @@ class BMDCamera {
|
|||
document.getElementById("hostnameInput").value = this.hostname;
|
||||
}
|
||||
|
||||
updateUICodecFormat() {
|
||||
//TBD
|
||||
}
|
||||
|
||||
updateUIVideoFormat() {
|
||||
//TBD
|
||||
}
|
||||
|
||||
updateUISupportedCodecFormats() {
|
||||
//TBD
|
||||
}
|
||||
|
||||
updateUISupportedVideoFormats() {
|
||||
//TBD
|
||||
updateUIFormat() {
|
||||
document.getElementById("formatCodec").innerHTML = this.format.codec.toUpperCase().replace(":"," ").replace("_",":");
|
||||
|
||||
let resObj = this.format.recordResolution;
|
||||
document.getElementById("formatResolution").innerHTML = resObj.width + "x" + resObj.height;
|
||||
document.getElementById("formatFPS").innerHTML = this.format.frameRate+" fps";
|
||||
}
|
||||
|
||||
updateUITransportMode() {
|
||||
|
|
@ -178,18 +178,37 @@ class BMDCamera {
|
|||
}
|
||||
|
||||
updateUITimecode() {
|
||||
// Redo this to work with no leading 0
|
||||
var tcString = parseInt(this.timecode.timecode.toString(16),10).toString().match(/.{1,2}/g).join(':');
|
||||
var tcString = parseInt(this.timecode.timecode.toString(16),10).toString().padStart(8,'0').match(/.{1,2}/g).join(':');
|
||||
|
||||
document.getElementById("timecodeLabel").innerHTML = tcString;
|
||||
}
|
||||
|
||||
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() {
|
||||
//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() {
|
||||
|
|
@ -224,6 +243,7 @@ class BMDCamera {
|
|||
|
||||
updateUIWhiteBalance() {
|
||||
document.getElementById("whiteBalanceSpan").innerHTML = this.WhiteBalance+"K";
|
||||
document.getElementById("whiteBalanceTintSpan").innerHTML = this.WhiteBalanceTint;
|
||||
}
|
||||
|
||||
updateUINDStop() {
|
||||
|
|
@ -248,7 +268,11 @@ class BMDCamera {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
|
@ -275,6 +299,22 @@ class BMDCamera {
|
|||
document.getElementsByClassName("CCredLabel")[3].innerHTML = this.CCoffset.red.toFixed(2);
|
||||
document.getElementsByClassName("CCgreenLabel")[3].innerHTML = this.CCoffset.green.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() {
|
||||
|
|
@ -286,20 +326,8 @@ class BMDCamera {
|
|||
|
||||
// name, hostname, APIaddress, index handled by constructor
|
||||
|
||||
getCodecFormat() {
|
||||
this.pullData("/system/codecFormat").then((value) => {this.codecFormat = value; this.updateUICodecFormat()});
|
||||
}
|
||||
|
||||
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()});
|
||||
getFormat() {
|
||||
this.pullData("/system/format").then((value) => {this.format = value; this.updateUIFormat()});
|
||||
}
|
||||
|
||||
getTransportMode() {
|
||||
|
|
@ -376,10 +404,7 @@ class BMDCamera {
|
|||
}
|
||||
|
||||
getAllInfo() {
|
||||
this.getCodecFormat();
|
||||
this.getVideoFormat();
|
||||
this.getSupportedCodecFormats();
|
||||
this.getSupportedVideoFormats();
|
||||
this.getFormat();
|
||||
this.getTransportMode();
|
||||
this.getPlaybackState();
|
||||
this.getRecordState();
|
||||
|
|
@ -423,7 +448,11 @@ class BMDCamera {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
@ -530,36 +559,18 @@ async function sendRequest(method, url, data) {
|
|||
const xhttp = new XMLHttpRequest();
|
||||
var responseObject;
|
||||
|
||||
// TODO: Add error code handling
|
||||
xhttp.onload = function() {
|
||||
if (this.responseText) {
|
||||
if (this.status == 200) {
|
||||
// Success w/ Data
|
||||
responseObject = JSON.parse(this.responseText);
|
||||
} else {
|
||||
responseObject = {"status": this.statusText};
|
||||
// Pass along response data and stuff
|
||||
responseObject = this;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't keep making API calls for unimplemented features
|
||||
if (cameras[ci]) {
|
||||
// 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));
|
||||
}
|
||||
xhttp.open(method, url, false);
|
||||
xhttp.send(JSON.stringify(data));
|
||||
|
||||
return responseObject;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,36 +56,36 @@
|
|||
</div> -->
|
||||
<span style="margin-top: 0.5em;">Lift</span>
|
||||
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
|
||||
<button id="CCResetButton" class="circleButton" onclick="resetCC(0)" title="Reset Lift">⟳</button>
|
||||
<button class="CCResetButton circleButton" onclick="resetCC(0)" title="Reset Lift">⟳</button>
|
||||
<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: #e64b3d;" class="CCredLabel">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: #2a78c8;" class="CCblueLabel">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" oninput="setCCFromUI(0)">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" oninput="setCCFromUI(0)">0.00</span>
|
||||
</div>
|
||||
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(0)" title="Set Lift">➚</button>
|
||||
</div>
|
||||
|
||||
<span>Gamma</span>
|
||||
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
|
||||
<button id="CCResetButton" class="circleButton" onclick="resetCC(1)" title="Reset Gamma">⟳</button>
|
||||
<button class="CCResetButton circleButton" onclick="resetCC(1)" title="Reset Gamma">⟳</button>
|
||||
<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: #e64b3d;" class="CCredLabel">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: #2a78c8;" class="CCblueLabel">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" oninput="setCCFromUI(1)">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" oninput="setCCFromUI(1)">0.00</span>
|
||||
</div>
|
||||
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(1)" title="Set Gamma">➚</button>
|
||||
</div>
|
||||
|
||||
<span>Gain</span>
|
||||
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
|
||||
<button id="CCResetButton" class="circleButton" onclick="resetCC(2)" title="Reset Gain">⟳</button>
|
||||
<button class="CCResetButton circleButton" onclick="resetCC(2)" title="Reset Gain">⟳</button>
|
||||
<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: #e64b3d;" class="CCredLabel">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: #2a78c8;" class="CCblueLabel">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" oninput="setCCFromUI(2)">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" oninput="setCCFromUI(2)">0.00</span>
|
||||
</div>
|
||||
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(2)" title="Set Gain">➚</button>
|
||||
</div>
|
||||
|
|
@ -93,12 +93,12 @@
|
|||
|
||||
<span>Offset</span>
|
||||
<div class="flexContainerH" id="cameraControlColorCorrectionBottomContainer">
|
||||
<button id="CCResetButton" class="circleButton" onclick="resetCC(3)" title="Reset Offset">⟳</button>
|
||||
<button class="CCResetButton circleButton" onclick="resetCC(3)" title="Reset Offset">⟳</button>
|
||||
<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: #e64b3d;" class="CCredLabel">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: #2a78c8;" class="CCblueLabel">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" oninput="setCCFromUI(3)">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" oninput="setCCFromUI(3)">0.00</span>
|
||||
</div>
|
||||
<button id="CCHamburgerButton" class="circleButton" onclick="setCCFromUI(3)" title="Set Offset">➚</button>
|
||||
</div>
|
||||
|
|
@ -109,7 +109,7 @@
|
|||
<span class="exposureControlLabel">FILTER</span>
|
||||
<div class="ccExposureSettingValueContainer">
|
||||
<a class="expAdjArr" href="#" onclick="decreaseND()" id="NDL">◀</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">▶</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -117,7 +117,7 @@
|
|||
<span class="exposureControlLabel">GAIN</span>
|
||||
<div class="ccExposureSettingValueContainer">
|
||||
<a class="expAdjArr" href="#" onclick="decreaseGain()" id="GAL">◀</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">▶</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -125,17 +125,22 @@
|
|||
<span class="exposureControlLabel">SHUTTER</span>
|
||||
<div class="ccExposureSettingValueContainer">
|
||||
<a class="expAdjArr" href="#" onclick="decreaseShutter()" id="SHL">◀</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">▶</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ccExposureSettingContainer">
|
||||
<span class="exposureControlLabel">BALANCE</span>
|
||||
<div class="ccExposureSettingValueContainer">
|
||||
<span class="exposureControlLabel" onclick="swapWBMode()" id="WBLabel">BALANCE</span>
|
||||
<div class="ccExposureSettingValueContainer" id="WBValueContainer">
|
||||
<a class="expAdjArr" href="#" onclick="decreaseWhiteBalance()" id="WBL">◀</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">▶</a>
|
||||
</div>
|
||||
<div class="ccExposureSettingValueContainer dNone" id="WBTintValueContainer">
|
||||
<a class="expAdjArr" href="#" onclick="decreaseWhiteBalanceTint()" id="WBTL">◀</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">▶</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -162,14 +167,19 @@
|
|||
<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">↻</button>
|
||||
<!--<button class="circleButton" onclick="" title="Loop">↻</button>
|
||||
<button class="circleButton" onclick="" title="Single Clip">S</button>
|
||||
<button class="circleButton" onclick="" title="Back">⏴</button>
|
||||
<button class="circleButton" onclick="" title="Forward">⏵</button>
|
||||
<button class="circleButton" onclick="" title="Forward">⏵</button> -->
|
||||
<button class="circleButton" onclick="cameras[ci].record()" title="Record">⏺</button>
|
||||
<button class="circleButton" onclick="cameras[ci].play()" title="Play">▶</button>
|
||||
<!-- <button class="circleButton" onclick="cameras[ci].play()" title="Play">▶</button> -->
|
||||
<button class="circleButton" onclick="cameras[ci].stopTransport(); cameras[ci].stopRecord();" title="Stop">⏹</button>
|
||||
</div>
|
||||
<h2 id="timecodeLabel">TIMECODE</h2>
|
||||
|
|
@ -182,8 +192,9 @@
|
|||
<tr>
|
||||
<td>Hostname</td>
|
||||
<td>
|
||||
<input type="text" value="Studio-Camera-6K-Pro.local" id="hostnameInput" onkeydown="textInputTrigger(this)">
|
||||
<button onclick='cameras[ci] = new BMDCamera(document.getElementById("hostnameInput").value,ci);'>Connect</button>
|
||||
<input type="text" value="Studio-Camera-6K-Pro.local" id="hostnameInput">
|
||||
<button onclick='initCamera(document.getElementById("hostnameInput").value, ci)'>Connect</button>
|
||||
<span id="connectionErrorSpan"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
@ -200,6 +211,11 @@
|
|||
<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 documentation for details.</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
|
@ -209,15 +225,13 @@
|
|||
<tr>
|
||||
<td>Preset Select</td>
|
||||
<td>
|
||||
<select id="presetsDropDown" onchange="console.log('Preset selected: '+this.value)">
|
||||
<option value="default">Default</option>
|
||||
<option value="other">other</option>
|
||||
<select id="presetsDropDown" onchange="cameras[ci].setActivePreset(this.value+'.cset')">
|
||||
<!-- Auto-populated by updateUIPresets() -->
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="color: #727272;">Upload a preset file</td>
|
||||
<td><input type="file" id="presetFileInput"></td>
|
||||
<td>
|
||||
<button onclick="cameras[ci].setActivePreset(document.getElementById('presetsDropDown').value+'.cset')">Restore from Preset</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -260,11 +274,20 @@
|
|||
<table>
|
||||
<tr>
|
||||
<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">⟳</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -274,15 +297,27 @@
|
|||
<table>
|
||||
<tr>
|
||||
<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">⟳</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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>
|
||||
<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>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -293,7 +328,10 @@
|
|||
|
||||
<!-- Footer Div -->
|
||||
<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">
|
||||
<span><a id="documentationLink" href="#" target="_blank">YAML Documentation</a></span>
|
||||
<span><a id="mediaManagerLink" href="#" target="_blank">Web Media Manager</a></span>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
url('resources/NotoSansDisplay-VariableFont_wdth\,wght.ttf') format('truetype'); /* Chrome 4+, Firefox 3.5, Opera 10+, Safari 3—5 */
|
||||
}
|
||||
|
||||
.dNone {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'NotoSansDisplay', sans-serif;
|
||||
font-weight: 100;
|
||||
|
|
@ -165,6 +169,10 @@ input[type=file]:focus {
|
|||
scrollbar-color: #202020 #151515;
|
||||
}
|
||||
|
||||
#formatDisplay span {
|
||||
margin: 0px 1em;
|
||||
}
|
||||
|
||||
#footerContainer {
|
||||
background: #181818;
|
||||
background: linear-gradient(0deg, #181818 0%, #303030 100%);
|
||||
|
|
@ -182,6 +190,14 @@ input[type=file]:focus {
|
|||
font-size: x-small;
|
||||
}
|
||||
|
||||
#refreshingText.refreshing {
|
||||
color: #606060ff;
|
||||
}
|
||||
|
||||
#refreshingText {
|
||||
color: #60606000;
|
||||
}
|
||||
|
||||
#footerLinks span {
|
||||
margin-right: 1.25vw;
|
||||
}
|
||||
|
|
@ -379,6 +395,14 @@ h2 {
|
|||
|
||||
}
|
||||
|
||||
#connectionErrorSpan {
|
||||
color: #e64b3d;
|
||||
}
|
||||
|
||||
#manualRequestResponseP {
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
/* Table Controls */
|
||||
|
||||
.tableControl {
|
||||
|
|
|
|||
102
web-ui/web-ui.js
102
web-ui/web-ui.js
|
|
@ -1,7 +1,7 @@
|
|||
/* Global variables */
|
||||
var cameras = [];
|
||||
var ci = 0;
|
||||
var ccMode = 0;
|
||||
var WBMode = 0; // 0: balance, 1: tint
|
||||
|
||||
function bodyOnLoad() {
|
||||
let intervalIDOne = setInterval(timerCallFunction1, 1000); // Tem second timer for refreshing everything
|
||||
|
|
@ -10,10 +10,24 @@ function bodyOnLoad() {
|
|||
let newCamHostname = document.getElementById("hostnameInput").value;
|
||||
|
||||
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
|
||||
function timerCallFunction1() {
|
||||
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) {
|
||||
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 */
|
||||
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
function setCCFromUI(which) {
|
||||
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) {
|
||||
if (which == 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});
|
||||
} else if (which == 2) {
|
||||
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});
|
||||
} 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});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue