diff --git a/web-ui/BMD-Camera-Control.js b/web-ui/BMD-Camera-Control.js
index 2493558..33aabc7 100644
--- a/web-ui/BMD-Camera-Control.js
+++ b/web-ui/BMD-Camera-Control.js
@@ -19,9 +19,6 @@ class BMDCamera {
// Current Transport Mode (string)
transportMode;
-
- // Whether the transport is playing or not (boolean)
- isPlaying;
// Playback state (JSON object)
playbackState;
@@ -80,6 +77,9 @@ class BMDCamera {
CCcolor;
CClumacontribution;
+ // Keep track of unimplemented functions on the camera (array of strings)
+ UnimplementedFunctionality = [];
+
// ============= CONSTRUCTOR ================
constructor(hostname, index) {
this.hostname = hostname;
@@ -117,7 +117,6 @@ class BMDCamera {
this.updateUISupportedCodecFormats();
this.updateUISupportedVideoFormats();
this.updateUITransportMode();
- this.updateUIisPlaying();
this.updateUIPlaybackState();
this.updateUIRecordState();
this.updateUITimecode();
@@ -133,14 +132,15 @@ class BMDCamera {
this.updateUIshutter();
this.updateUIAutoExposureMode();
this.updateUIColorCorrection();
+ this.updateUILinks();
}
updateUIname() {
- document.getElementsByClassName("cameraName")[this.index].innerHTML = this.name;
+ document.getElementById("cameraName").innerHTML = this.name;
}
updateUIhostname() {
- //TBD
+ document.getElementById("hostnameInput").value = this.hostname;
}
updateUICodecFormat() {
@@ -163,26 +163,25 @@ class BMDCamera {
//TBD
}
- updateUIisPlaying() {
- //TBD
- }
-
updateUIPlaybackState() {
//TBD
}
updateUIRecordState() {
if (this.recordState.recording) {
- document.getElementsByClassName("cameraControlsContainer")[this.index].classList.add("liveCam");
+ document.getElementById("cameraControlHeadContainer").classList.add("liveCam");
+ document.getElementById("cameraControlExpandedHeadContainer").classList.add("liveCam");
} else {
- document.getElementsByClassName("cameraControlsContainer")[this.index].classList.remove("liveCam");
+ document.getElementById("cameraControlHeadContainer").classList.remove("liveCam");
+ document.getElementById("cameraControlExpandedHeadContainer").classList.remove("liveCam");
}
}
updateUITimecode() {
+ // Redo this to work with no leading 0
var tcString = parseInt(this.timecode.timecode.toString(16),10).toString().match(/.{1,2}/g).join(':');
- document.getElementsByClassName("timecodeLabel")[this.index].innerHTML = tcString;
+ document.getElementById("timecodeLabel").innerHTML = tcString;
}
updateUIPresets() {
@@ -194,21 +193,21 @@ class BMDCamera {
}
updateUIAperture() {
- document.getElementsByClassName("irisRange")[this.index].value = this.apertureNormalised;
- document.getElementsByClassName("apertureStopsLabel")[this.index].innerHTML = this.apertureStop.toFixed(1);
+ document.getElementById("irisRange").value = this.apertureNormalised;
+ document.getElementById("apertureStopsLabel").innerHTML = this.apertureStop.toFixed(1);
}
updateUIZoom() {
- document.getElementsByClassName("zoomRange")[this.index].value = this.zoomNormalised;
- document.getElementsByClassName("zoomMMLabel")[this.index].innerHTML = this.zoomMM;
+ document.getElementById("zoomRange").value = this.zoomNormalised;
+ document.getElementById("zoomMMLabel").innerHTML = this.zoomMM;
}
updateUIFocus() {
- document.getElementsByClassName("focusRange")[this.index].value = this.focusNormalised;
+ document.getElementById("focusRange").value = this.focusNormalised;
}
updateUIISO() {
- // TBD
+ document.getElementById("ISOInput").value = this.ISO;
}
updateUIgain() {
@@ -220,15 +219,15 @@ class BMDCamera {
gainString = this.gain+"db"
}
- document.getElementsByClassName("gainSpan")[this.index].innerHTML = gainString;
+ document.getElementById("gainSpan").innerHTML = gainString;
}
updateUIWhiteBalance() {
- document.getElementsByClassName("whiteBalanceSpan")[this.index].innerHTML = this.WhiteBalance+"K";
+ document.getElementById("whiteBalanceSpan").innerHTML = this.WhiteBalance+"K";
}
updateUINDStop() {
- document.getElementsByClassName("ndFilterSpan")[this.index].innerHTML = this.NDStop;
+ document.getElementById("ndFilterSpan").innerHTML = this.NDStop;
}
updateUIshutter() {
@@ -237,11 +236,15 @@ class BMDCamera {
if ('shutterSpeed' in this.shutter) {
shutterString = "1/"+this.shutter.shutterSpeed
} else {
- var shangleString = this.shutter.shutterAngle.toString();
- shutterString = shangleString.slice(0,3)+(shangleString.slice(3,4) == '0' ? '' : "."+shangleString.slice(3,4))+"°"
+ var shangleString = (this.shutter.shutterAngle / 100).toFixed(1).toString()
+ if (shangleString.indexOf(".0") > 0) {
+ shutterString = parseFloat(shangleString).toFixed(0)+"°";
+ } else {
+ shutterString = shangleString+"°";
+ }
}
- document.getElementsByClassName("shutterSpan")[this.index].innerHTML = shutterString;
+ document.getElementById("shutterSpan").innerHTML = shutterString;
}
updateUIAutoExposureMode() {
@@ -249,7 +252,34 @@ class BMDCamera {
}
updateUIColorCorrection() {
- //TBD
+ // Lift
+ document.getElementsByClassName("CClumaLabel")[0].innerHTML = this.CClift.luma.toFixed(2);
+ document.getElementsByClassName("CCredLabel")[0].innerHTML = this.CClift.red.toFixed(2);
+ document.getElementsByClassName("CCgreenLabel")[0].innerHTML = this.CClift.green.toFixed(2);
+ document.getElementsByClassName("CCblueLabel")[0].innerHTML = this.CClift.blue.toFixed(2);
+
+ // Gamma
+ document.getElementsByClassName("CClumaLabel")[1].innerHTML = this.CCgamma.luma.toFixed(2);
+ document.getElementsByClassName("CCredLabel")[1].innerHTML = this.CCgamma.red.toFixed(2);
+ document.getElementsByClassName("CCgreenLabel")[1].innerHTML = this.CCgamma.green.toFixed(2);
+ document.getElementsByClassName("CCblueLabel")[1].innerHTML = this.CCgamma.blue.toFixed(2);
+
+ // Gain
+ document.getElementsByClassName("CClumaLabel")[2].innerHTML = this.CCgain.luma.toFixed(2);
+ document.getElementsByClassName("CCredLabel")[2].innerHTML = this.CCgain.red.toFixed(2);
+ document.getElementsByClassName("CCgreenLabel")[2].innerHTML = this.CCgain.green.toFixed(2);
+ document.getElementsByClassName("CCblueLabel")[2].innerHTML = this.CCgain.blue.toFixed(2);
+
+ // Offset
+ document.getElementsByClassName("CClumaLabel")[3].innerHTML = this.CCoffset.luma.toFixed(2);
+ 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);
+ }
+
+ updateUILinks() {
+ document.getElementById("documentationLink").href = "http://"+this.hostname+"/control/documentation.html";
+ document.getElementById("mediaManagerLink").href = "http://"+this.hostname;
}
// =============== GETTERS ==================
@@ -257,86 +287,82 @@ class BMDCamera {
// name, hostname, APIaddress, index handled by constructor
getCodecFormat() {
- this.pullData("/system/codecFormat").then((value) => {this.codecFormat = value});
+ this.pullData("/system/codecFormat").then((value) => {this.codecFormat = value; this.updateUICodecFormat()});
}
getVideoFormat() {
- this.pullData("/system/videoFormat").then((value) => {this.videoFormat = value});
+ this.pullData("/system/videoFormat").then((value) => {this.videoFormat = value; this.updateUIVideoFormat()});
}
getSupportedCodecFormats() {
- this.pullData("/system/supportedCodecFormats").then((value) => {this.supportedCodecFormats = value});
+ this.pullData("/system/supportedCodecFormats").then((value) => {this.supportedCodecFormats = value; this.updateUISupportedCodecFormats()});
}
getSupportedVideoFormats() {
- this.pullData("/system/supportedVideoFormats").then((value) => {this.supportedVideoFormats = value});
+ this.pullData("/system/supportedVideoFormats").then((value) => {this.supportedVideoFormats = value; this.updateUISupportedVideoFormats()});
}
getTransportMode() {
- this.pullData("/transports/0").then((value) => {this.transportMode = value});
- }
-
- getIsPlaying() {
- this.pullData("/transports/0/play").then((value) => {this.isPlaying = value});
+ this.pullData("/transports/0").then((value) => {this.transportMode = value; this.updateUITransportMode()});
}
getPlaybackState() {
- this.pullData("/transports/0/playback").then((value) => {this.playbackState = value});
+ this.pullData("/transports/0/playback").then((value) => {this.playbackState = value; this.updateUIPlaybackState()});
}
getRecordState() {
- this.pullData("/transports/0/record").then((value) => {this.recordState = value});
+ this.pullData("/transports/0/record").then((value) => {this.recordState = value; this.updateUIRecordState()});
}
getTimecode() {
- this.pullData("/transports/0/timecode").then((value) => {this.timecode = value});
+ this.pullData("/transports/0/timecode").then((value) => {this.timecode = value; this.updateUITimecode()});
this.pullData("/transports/0/timecode/source").then((value) => {this.timecode.source = value.source});
}
getPresets() {
- this.pullData("/presets").then((value) => {this.presets = value.presets});
+ this.pullData("/presets").then((value) => {this.presets = value.presets; this.updateUIPresets()});
}
getActivePreset() {
- this.pullData("/presets/active").then((value) => {this.activePreset = value});
+ this.pullData("/presets/active").then((value) => {this.activePreset = value; this.updateUIActivePreset()});
}
getAperture() {
- this.pullData("/lens/iris").then((value) => {this.apertureStop = value.apertureStop; this.apertureNormalised = value.normalised});
+ this.pullData("/lens/iris").then((value) => {this.apertureStop = value.apertureStop; this.apertureNormalised = value.normalised; this.updateUIAperture()});
}
getZoom() {
- this.pullData("/lens/zoom").then((value) => {this.zoomMM = value.focalLength; this.zoomNormalised = value.normalised});
+ this.pullData("/lens/zoom").then((value) => {this.zoomMM = value.focalLength; this.zoomNormalised = value.normalised; this.updateUIZoom()});
}
getFocus() {
- this.pullData("/lens/focus").then((value) => {this.focusNormalised = value.normalised});
+ this.pullData("/lens/focus").then((value) => {this.focusNormalised = value.normalised; this.updateUIFocus()});
}
getISO() {
- this.pullData("/video/iso").then((value) => {this.ISO = value.iso});
+ this.pullData("/video/iso").then((value) => {this.ISO = value.iso; this.updateUIISO()});
}
getGain() {
- this.pullData("/video/gain").then((value) => {this.gain = value.gain});
+ this.pullData("/video/gain").then((value) => {this.gain = value.gain; this.updateUIgain()});
}
getWhiteBalance() {
this.pullData("/video/whiteBalance").then((value) => {this.WhiteBalance = value.whiteBalance});
- this.pullData("/video/whiteBalanceTint").then((value) => {this.WhiteBalanceTint = value.whiteBalanceTint});
+ this.pullData("/video/whiteBalanceTint").then((value) => {this.WhiteBalanceTint = value.whiteBalanceTint; this.updateUIWhiteBalance()});
}
getND() {
- this.pullData("/video/ndFilter").then((value) => {this.NDStop = value.stop});
+ this.pullData("/video/ndFilter").then((value) => {this.NDStop = value.stop; this.updateUINDStop()});
this.pullData("/video/ndFilter/displayMode").then((value) => {this.NDMode = value.displayMode});
}
getShutter() {
- this.pullData("/video/shutter").then((value) => {this.shutter = value});
+ this.pullData("/video/shutter").then((value) => {this.shutter = value; this.updateUIshutter()});
}
getAutoExposureMode() {
- this.pullData("/video/autoExposure").then((value) => {this.AutoExposureMode = value});
+ this.pullData("/video/autoExposure").then((value) => {this.AutoExposureMode = value; this.updateUIAutoExposureMode()});
}
getColorCorrection() {
@@ -346,7 +372,7 @@ class BMDCamera {
this.pullData("/colorCorrection/offset").then((value) => {this.CCoffset = value});
this.pullData("/colorCorrection/contrast").then((value) => {this.CCcontrast = value});
this.pullData("/colorCorrection/color").then((value) => {this.CCcolor = value});
- this.pullData("/colorCorrection/lumaContribution").then((value) => {this.CClumacontribution = value});
+ this.pullData("/colorCorrection/lumaContribution").then((value) => {this.CClumacontribution = value; this.updateUIColorCorrection()});
}
getAllInfo() {
@@ -355,7 +381,6 @@ class BMDCamera {
this.getSupportedCodecFormats();
this.getSupportedVideoFormats();
this.getTransportMode();
- this.getIsPlaying();
this.getPlaybackState();
this.getRecordState();
this.getTimecode();
@@ -373,14 +398,130 @@ class BMDCamera {
this.getColorCorrection();
}
- // =============== Other Commands =======================
- doAutoFocus() {
- this.pushData("/lens/focus/doAutoFocus")
+ // =============== SETTERS ==================
+
+ // name, hostname, APIaddress, index should never have to be set
+
+ setCodecFormat(newCodecFormatObject) {
+ this.pushData("/system/codecFormat",newCodecFormatObject).then(() => sleep(1000).then(() => this.getCodecFormat()));
}
- /* Timer Stuff */
- everySecond() {
- this.refresh();
+ setVideoFormat(newVideoFormatObject) {
+ this.pushData("/system/videoFormat",newVideoFormatObject).then(() => sleep(1000).then(() => this.getCodecFormat()));
+ }
+
+ setTransportMode(newTransportModeString) {
+ this.pushData("/transports/0",{"mode": newTransportModeString}).then(() => sleep(1000).then(() => this.getTransportMode()));
+ }
+
+ setPlaybackState(playbackStateObject) {
+ this.pushData("/transports/0/playback",playbackStateObject).then(() => sleep(1000).then(() => this.getPlaybackState()));
+ }
+
+ sendPresetFile(file) {
+ sendRequest("POST",this.APIAddress+"/presets",file)
+ }
+
+ setActivePreset(presetString) {
+ this.pushData("/presets/active",{"preset": presetString}).then(() => sleep(1000).then(() => this.getActivePreset()));
+ }
+
+ setAperture(apertureNormalisedFloat) {
+ this.pushData("/lens/iris",{"normalised": apertureNormalisedFloat}).then(() => sleep(1000).then(() => this.getAperture()));
+ }
+
+ setZoom(zoomNormalisedFloat) {
+ this.pushData("/lens/zoom",{"normalised": zoomNormalisedFloat}).then(() => sleep(1000).then(() => this.getZoom()));
+ }
+
+ setFocus(focusNormalisedFloat) {
+ this.pushData("/lens/focus",{"normalised": focusNormalisedFloat}).then(() => sleep(1000).then(() => this.getFocus()));
+ }
+
+ setISO(ISOint) {
+ this.pushData("/video/iso",{"iso":ISOint}).then(() => sleep(1000).then(() => this.getISO()));
+ }
+
+ setGain(gainInt) {
+ this.pushData("/video/gain",{"gain":gainInt}).then(() => sleep(1000).then(() => this.getGain()));
+ }
+
+ setWhiteBalance(whiteBalanceInt, whiteBalanceTintInt) {
+ this.pushData("/video/whiteBalance",{"whiteBalance": whiteBalanceInt});
+ this.pushData("/video/whiteBalanceTint",{"whiteBalanceTint": whiteBalanceTintInt}).then(() => sleep(1000).then(() => this.getWhiteBalance()));
+ }
+
+ setND(NDstopInt) {
+ this.pushData("/video/ndFilter",{"stop": NDstopInt}).then(() => sleep(1000).then(() => this.getND()));
+ }
+
+ setNDDisplayMode(displayModeString) {
+ this.pushData("/video/ndFilter/displayMode",{"displayMode": displayModeString}).then(() => sleep(1000).then(() => this.getND()));
+ }
+
+ // Accepts JSON obejcts with either shutterSpeed or shutterAngle properties
+ // Note that shutterAngle is 100x the displayed value
+ setShutter(shutterObject) {
+ this.pushData("/video/shutter",shutterObject).then(() => sleep(1000).then(() => this.getShutter()));
+ }
+
+ setAutoExposureMode(AEmodeObject) {
+ this.pushData("/video/autoExposure",AEmodeObject).then(() => sleep(1000).then(() => this.getAutoExposureMode()));
+ }
+
+ setCCLift(CCliftObject) {
+ this.pushData("/colorCorrection/lift",CCliftObject).then(() => sleep(1000).then(() => this.getColorCorrection()));
+ }
+
+ setCCGamma(CCgammaObject) {
+ this.pushData("/colorCorrection/gamma",CCgammaObject).then(() => sleep(1000).then(() => this.getColorCorrection()));
+ }
+
+ setCCGain(CCgainObject) {
+ this.pushData("/colorCorrection/gain",CCgainObject).then(() => sleep(1000).then(() => this.getColorCorrection()));
+ }
+
+ setCCOffset(CCoffsetObject) {
+ this.pushData("/colorCorrection/offset",CCoffsetObject).then(() => sleep(1000).then(() => this.getColorCorrection()));
+ }
+
+ setCCContrast(CCcontrastObject) {
+ this.pushData("/colorCorrection/contrast",CCcontrastObject).then(() => sleep(1000).then(() => this.getColorCorrection()));
+ }
+
+ setCCColor(CCcolorObject) {
+ this.pushData("/colorCorrection/color",CCcolorObject).then(() => sleep(1000).then(() => this.getColorCorrection()));
+ }
+
+ setCCLumaContribuion(CClumacontributionObject) {
+ this.pushData("/colorCorrection/lumaContribution",CClumacontributionObject).then(() => sleep(1000).then(() => this.getColorCorrection()));
+ }
+
+ // =============== Other Commands =======================
+ doAutoFocus() {
+ this.pushData("/lens/focus/doAutoFocus").then(() => sleep(1500).then(() => this.getFocus()));
+ }
+
+ play() {
+ this.pushData("/transports/0/play").then(() => sleep(1000).then(() => this.getPlaybackState()));
+ }
+
+ record() {
+ this.pushData("/transports/0/record",{"recording": true}).then(() => {
+ sleep(2000).then(() => this.getRecordState());
+ });
+ }
+
+ stopTransport() {
+ this.pushData("/transports/0/stop").then(() => {
+ sleep(2000).then(() => this.getPlaybackState());
+ });
+ }
+
+ stopRecord() {
+ this.pushData("/transports/0/record",{"recording": false}).then(() => {
+ sleep(2000).then(() => this.getRecordState());
+ });
}
}
@@ -398,8 +539,27 @@ async function sendRequest(method, url, data) {
}
}
- xhttp.open(method, url, false);
- xhttp.send(JSON.stringify(data));
+ // 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));
+ }
return responseObject;
}
diff --git a/web-ui/Screenshot 2024-06-12 171720.png b/web-ui/Screenshot 2024-06-12 171720.png
new file mode 100644
index 0000000..27d7cf6
Binary files /dev/null and b/web-ui/Screenshot 2024-06-12 171720.png differ
diff --git a/web-ui/index.html b/web-ui/index.html
index b443a8b..6b9896e 100644
--- a/web-ui/index.html
+++ b/web-ui/index.html
@@ -24,71 +24,268 @@
-
-
-
CAM1
+
+
+
CAM1
-
+
+
+
Lift
+
+
+
+ 0.00
+ 0.00
+ 0.00
+ 0.00
+
+
+
+
Gamma
+
+
+
+ 0.00
+ 0.00
+ 0.00
+ 0.00
+
+
+
+
+
Gain
+
+
+
+ 0.00
+ 0.00
+ 0.00
+ 0.00
+
+
+
+
+
+
Offset
+
+
+
+ 0.00
+ 0.00
+ 0.00
+ 0.00
+
+
+
-
+
-
-
-
-
TIMECODE
+
+
+
CAMERA NAME
+
+
+
+
+
+
+
+
+
+
+
TIMECODE
-
-
Hostname:
-
-
+
+
+
+
+
+
+
+
Exposure
+
+
+
+
+
+
+
@@ -97,6 +294,11 @@