From 329656837af731cfef4ddde19db2d48537043cd8 Mon Sep 17 00:00:00 2001 From: Bryan Mayland Date: Thu, 20 Jun 2013 17:41:10 +0200 Subject: [PATCH] Renamed flipX, flipY to flipH, flipV, made update upon change instant, also made timelapse video reflect flipped webcam --- octoprint/server.py | 12 +++++------- octoprint/settings.py | 4 ++-- octoprint/static/css/octoprint.less | 27 +++++++++++++++------------ octoprint/static/js/ui.js | 18 +++++++++--------- octoprint/templates/index.jinja2 | 4 ++-- octoprint/templates/settings.jinja2 | 4 ++-- octoprint/timelapse.py | 27 +++++++++++++++++++++++++-- 7 files changed, 60 insertions(+), 36 deletions(-) diff --git a/octoprint/server.py b/octoprint/server.py index f4d9aca..c840ad7 100644 --- a/octoprint/server.py +++ b/octoprint/server.py @@ -119,9 +119,7 @@ def index(): enableGCodeVisualizer=settings().get(["feature", "gCodeVisualizer"]), enableSystemMenu=settings().get(["system"]) is not None and settings().get(["system", "actions"]) is not None and len(settings().get(["system", "actions"])) > 0, enableAccessControl=userManager is not None, - enableSdSupport=settings().get(["feature", "sdSupport"]), - webcamFlipX=settings().get(["webcam", "flipX"]), - webcamFlipY=settings().get(["webcam", "flipY"]) + enableSdSupport=settings().get(["feature", "sdSupport"]) ) #~~ Printer control @@ -435,8 +433,8 @@ def getSettings(): "ffmpegPath": s.get(["webcam", "ffmpeg"]), "bitrate": s.get(["webcam", "bitrate"]), "watermark": s.getBoolean(["webcam", "watermark"]), - "flipX": s.getBoolean(["webcam", "flipX"]), - "flipY": s.getBoolean(["webcam", "flipY"]) + "flipH": s.getBoolean(["webcam", "flipH"]), + "flipV": s.getBoolean(["webcam", "flipV"]) }, "feature": { "gcodeViewer": s.getBoolean(["feature", "gCodeVisualizer"]), @@ -483,8 +481,8 @@ def setSettings(): if "ffmpegPath" in data["webcam"].keys(): s.set(["webcam", "ffmpeg"], data["webcam"]["ffmpegPath"]) if "bitrate" in data["webcam"].keys(): s.set(["webcam", "bitrate"], data["webcam"]["bitrate"]) if "watermark" in data["webcam"].keys(): s.setBoolean(["webcam", "watermark"], data["webcam"]["watermark"]) - if "flipX" in data["webcam"].keys(): s.setBoolean(["webcam", "flipX"], data["webcam"]["flipX"]) - if "flipY" in data["webcam"].keys(): s.setBoolean(["webcam", "flipY"], data["webcam"]["flipY"]) + if "flipH" in data["webcam"].keys(): s.setBoolean(["webcam", "flipH"], data["webcam"]["flipH"]) + if "flipV" in data["webcam"].keys(): s.setBoolean(["webcam", "flipV"], data["webcam"]["flipV"]) if "feature" in data.keys(): if "gcodeViewer" in data["feature"].keys(): s.setBoolean(["feature", "gCodeVisualizer"], data["feature"]["gcodeViewer"]) diff --git a/octoprint/settings.py b/octoprint/settings.py index 58da843..f1ca051 100644 --- a/octoprint/settings.py +++ b/octoprint/settings.py @@ -36,8 +36,8 @@ default_settings = { "ffmpeg": None, "bitrate": "5000k", "watermark": True, - "flipX": False, - "flipY": False + "flipH": False, + "flipV": False }, "feature": { "gCodeVisualizer": True, diff --git a/octoprint/static/css/octoprint.less b/octoprint/static/css/octoprint.less index 5629f47..85a90ce 100644 --- a/octoprint/static/css/octoprint.less +++ b/octoprint/static/css/octoprint.less @@ -358,18 +358,21 @@ ul.dropdown-menu li a { #webcam_container { width: 100%; -} -#webcam_container.flipX { - -webkit-transform: scaleX(-1); - -moz-transform: scaleX(-1); -} -#webcam_container.flipY { - -webkit-transform: scaleY(-1); - -moz-transform: scaleY(-1); -} -#webcam_container.flipX.flipY { - -webkit-transform: scaleX(-1) scaleY(-1); - -moz-transform: scaleX(-1) scaleY(-1); + + .flipH { + -webkit-transform: scaleX(-1); + -moz-transform: scaleX(-1); + } + + .flipV { + -webkit-transform: scaleY(-1); + -moz-transform: scaleY(-1); + } + + .flipH.flipV { + -webkit-transform: scaleX(-1) scaleY(-1); + -moz-transform: scaleX(-1) scaleY(-1); + } } /** GCODE file manager */ diff --git a/octoprint/static/js/ui.js b/octoprint/static/js/ui.js index c924305..e1c1a4a 100644 --- a/octoprint/static/js/ui.js +++ b/octoprint/static/js/ui.js @@ -526,10 +526,11 @@ function TemperatureViewModel(loginStateViewModel, settingsViewModel) { } } -function ControlViewModel(loginStateViewModel) { +function ControlViewModel(loginStateViewModel, settingsViewModel) { var self = this; self.loginState = loginStateViewModel; + self.settings = settingsViewModel; self.isErrorOrClosed = ko.observable(undefined); self.isOperational = ko.observable(undefined); @@ -1328,8 +1329,8 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) { self.webcam_ffmpegPath = ko.observable(undefined); self.webcam_bitrate = ko.observable(undefined); self.webcam_watermark = ko.observable(undefined); - self.webcam_flipX = ko.observable(undefined); - self.webcam_flipY = ko.observable(undefined); + self.webcam_flipH = ko.observable(undefined); + self.webcam_flipV = ko.observable(undefined); self.feature_gcodeViewer = ko.observable(undefined); self.feature_waitForStart = ko.observable(undefined); @@ -1377,8 +1378,8 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) { self.webcam_ffmpegPath(response.webcam.ffmpegPath); self.webcam_bitrate(response.webcam.bitrate); self.webcam_watermark(response.webcam.watermark); - self.webcam_flipX(response.webcam.flipX); - self.webcam_flipY(response.webcam.flipY); + self.webcam_flipH(response.webcam.flipH); + self.webcam_flipV(response.webcam.flipV); self.feature_gcodeViewer(response.feature.gcodeViewer); self.feature_waitForStart(response.feature.waitForStart); @@ -1414,15 +1415,14 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) { "ffmpegPath": self.webcam_ffmpegPath(), "bitrate": self.webcam_bitrate(), "watermark": self.webcam_watermark(), - "flipX": self.webcam_flipX(), - "flipY": self.webcam_flipY() + "flipH": self.webcam_flipH(), + "flipV": self.webcam_flipV() }, "feature": { "gcodeViewer": self.feature_gcodeViewer(), "waitForStart": self.feature_waitForStart(), "alwaysSendChecksum": self.feature_alwaysSendChecksum(), "resetLineNumbersWithPrefixedN": self.feature_resetLineNumbersWithPrefixedN(), - "waitForStart": self.feature_waitForStart(), "sdSupport": self.feature_sdSupport() }, "folder": { @@ -1837,7 +1837,7 @@ $(function() { var settingsViewModel = new SettingsViewModel(loginStateViewModel, usersViewModel); var appearanceViewModel = new AppearanceViewModel(settingsViewModel); var temperatureViewModel = new TemperatureViewModel(loginStateViewModel, settingsViewModel); - var controlViewModel = new ControlViewModel(loginStateViewModel); + var controlViewModel = new ControlViewModel(loginStateViewModel, settingsViewModel); var terminalViewModel = new TerminalViewModel(loginStateViewModel); var gcodeFilesViewModel = new GcodeFilesViewModel(loginStateViewModel); var timelapseViewModel = new TimelapseViewModel(loginStateViewModel); diff --git a/octoprint/templates/index.jinja2 b/octoprint/templates/index.jinja2 index 74e025d..46d52ac 100644 --- a/octoprint/templates/index.jinja2 +++ b/octoprint/templates/index.jinja2 @@ -310,8 +310,8 @@
{% if webcamStream %} -
- +
+
{% endif %} diff --git a/octoprint/templates/settings.jinja2 b/octoprint/templates/settings.jinja2 index 4e55cd2..b247cdf 100644 --- a/octoprint/templates/settings.jinja2 +++ b/octoprint/templates/settings.jinja2 @@ -92,12 +92,12 @@
diff --git a/octoprint/timelapse.py b/octoprint/timelapse.py index 3f2c1d6..1f5a302 100644 --- a/octoprint/timelapse.py +++ b/octoprint/timelapse.py @@ -106,19 +106,42 @@ class Timelapse(object): ffmpeg, '-i', input, '-vcodec', 'mpeg2video', '-pix_fmt', 'yuv420p', '-r', '25', '-y', '-b:v', bitrate, '-f', 'vob'] + filters = [] + + # flip video if configured + if settings().getBoolean(["webcam", "flipX"]): + filters.append('hflip') + if settings().getBoolean(["webcam", "flipY"]): + filters.append('vflip') + # add watermark if configured + watermarkFilter = None if settings().getBoolean(["webcam", "watermark"]): watermark = os.path.join(os.path.dirname(__file__), "static", "img", "watermark.png") if sys.platform == "win32": # Because ffmpeg hiccups on windows' drive letters and backslashes we have to give the watermark # path a special treatment. Yeah, I couldn't believe it either... watermark = watermark.replace("\\", "/").replace(":", "\\\\:") - command.extend(['-vf', 'movie=%s [wm]; [in][wm] overlay=10:main_h-overlay_h-10 [out]' % watermark]) + + watermarkFilter = "movie=%s [wm]; [%%(inputName)s][wm] overlay=10:main_h-overlay_h-10" % watermark + + filterstring = None + if len(filters) > 0: + if watermarkFilter is not None: + filterstring = "[in] %s [postprocessed]; %s [out]" % (",".join(filters), watermarkFilter % {"inputName": "postprocessed"}) + else: + filterstring = "[in] %s [out]" % ",".join(filters) + elif watermarkFilter is not None: + filterstring = watermarkFilter % {"inputName": "in"} + " [out]" + + if filterstring is not None: + self._logger.debug("Applying videofilter chain: %s" % filterstring) + command.extend(["-vf", filterstring]) # finalize command with output file command.append(output) - subprocess.call(command) self._logger.debug("Rendering movie to %s" % output) + subprocess.call(command) def cleanCaptureDir(self): if not os.path.isdir(self._captureDir):