From a4418dc5a3e73b616bddd361be72b038d25f234b Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 22 Dec 2023 16:44:09 +0100 Subject: [PATCH] Always save snapshots, regen screenshot as needed, save indicator Signed-off-by: falkTX --- html/css/pedals.css | 4 ++++ html/js/desktop.js | 33 ++++++++++++++++++++------------- html/js/host.js | 2 +- html/js/snapshot.js | 2 +- mod/host.py | 4 ++++ mod/session.py | 14 +++++++++++++- mod/webserver.py | 4 ++++ 7 files changed, 47 insertions(+), 16 deletions(-) diff --git a/html/css/pedals.css b/html/css/pedals.css index 5dc7664a..f7ed24eb 100644 --- a/html/css/pedals.css +++ b/html/css/pedals.css @@ -1032,3 +1032,7 @@ body > .mod-settings.mod-window-visible { .plugin-description p::selection { background: #4f2157 } + +#pedalboard-info .js-save.unmodified-changes { + background-color: #883996; +} diff --git a/html/js/desktop.js b/html/js/desktop.js index 1f085896..1709c462 100644 --- a/html/js/desktop.js +++ b/html/js/desktop.js @@ -140,7 +140,7 @@ function Desktop(elements) { data: JSON.stringify(addressing), success: function (resp) { if (resp) { - self.pedalboardModified = true + self.setPedalboardAsModified(true) callback(true) } else { new Bug("Couldn't address parameter, not allowed") @@ -467,6 +467,15 @@ function Desktop(elements) { }) } + this.setPedalboardAsModified = function (modified) { + this.pedalboardModified = modified + if (modified) { + elements.saveButton.addClass('unmodified-changes') + } else { + elements.saveButton.removeClass('unmodified-changes') + } + } + elements.devicesIcon.statusTooltip() this.ccDeviceManager = new ControlChainDeviceManager({ devicesIcon: elements.devicesIcon, @@ -540,7 +549,7 @@ function Desktop(elements) { var source = syncMode === "link" ? "Ableton Link" : "MIDI" new Notification('info', 'BPM addressing removed, incompatible with ' + source + ' sync mode', 8000) } - self.pedalboardModified = true + self.setPedalboardAsModified(true) }, setSyncMode: function(syncMode, callback) { $.ajax({ @@ -583,7 +592,7 @@ function Desktop(elements) { var source = syncMode === "link" ? "Ableton Link" : "MIDI" new Notification('info', 'BPM addressing removed, incompatible with ' + source + ' sync mode', 8000) } - self.pedalboardModified = true + self.setPedalboardAsModified(true) callback(true) } else { new Bug("Couldn't address parameter") @@ -855,7 +864,7 @@ function Desktop(elements) { transfer.reportFinished = function () { self.pedalboardEmpty = false - self.pedalboardModified = true + self.setPedalboardAsModified(true) } transfer.reportError = function (error) { @@ -987,7 +996,6 @@ function Desktop(elements) { url: '/snapshot/save', method: 'POST', success: function () { - self.pedalboardModified = true new Notification('info', 'Pedalboard snapshot saved', 2000) }, error: function () { @@ -1015,7 +1023,6 @@ function Desktop(elements) { } self.pedalboardPresetId = resp.id self.pedalboardPresetName = resp.title - self.pedalboardModified = true self.titleBox.text((self.title || 'Untitled') + " - " + resp.title) new Notification('info', 'Pedalboard snapshot saved', 2000) }, @@ -1456,13 +1463,13 @@ Desktop.prototype.makePedalboard = function (el, effectBox) { self.title = '' self.pedalboardBundle = null self.pedalboardEmpty = true - self.pedalboardModified = false self.pedalboardPresetId = 0 self.pedalboardPresetName = '' self.pedalboardDemoPluginsNotified = false self.titleBox.text('Untitled') self.titleBox.addClass("blend") self.transportControls.resetControlsEnabled() + self.setPedalboardAsModified(false) callback(true) }, @@ -1488,7 +1495,7 @@ Desktop.prototype.makePedalboard = function (el, effectBox) { }, pluginParameterChange: function (port, value) { - self.pedalboardModified = true + self.setPedalboardAsModified(true) ws.send(sprintf("param_set %s %f", port, value)) }, @@ -1497,12 +1504,12 @@ Desktop.prototype.makePedalboard = function (el, effectBox) { }, pluginPatchSet: function (instance, uri, valuetype, value) { - self.pedalboardModified = true + self.setPedalboardAsModified(true) ws.send(sprintf("patch_set %s %s %s %s", instance, uri, valuetype, value)) }, pluginMove: function (instance, x, y) { - self.pedalboardModified = true + self.setPedalboardAsModified(true) ws.send(sprintf("plugin_pos %s %f %f", instance, x, y)) }, @@ -1582,7 +1589,7 @@ Desktop.prototype.makePedalboard = function (el, effectBox) { // Bind events el.bind('modified', function () { self.pedalboardEmpty = false - self.pedalboardModified = true + self.setPedalboardAsModified(true) }) /* el.bind('dragStart', function () { @@ -1837,8 +1844,8 @@ Desktop.prototype.loadPedalboard = function (bundlepath, callback) { self.title = resp.name self.pedalboardBundle = bundlepath self.pedalboardEmpty = false - self.pedalboardModified = false self.pedalboardDemoPluginsNotified = false + self.setPedalboardAsModified(false) self.titleBox.text(resp.name); self.titleBox.removeClass("blend"); @@ -1876,7 +1883,7 @@ Desktop.prototype.saveCurrentPedalboard = function (asNew, callback) { self.title = title self.pedalboardBundle = errorOrPath self.pedalboardEmpty = false - self.pedalboardModified = false + self.setPedalboardAsModified(false) self.titleBox.text(title + " - " + self.pedalboardPresetName) if (self.previousPedalboardList != null) { diff --git a/html/js/host.js b/html/js/host.js index fc8637b0..66ebd76b 100644 --- a/html/js/host.js +++ b/html/js/host.js @@ -506,9 +506,9 @@ $('document').ready(function() { success: function (resp) { desktop.pedalboard.pedalboard('scheduleAdapt', true) desktop.pedalboardEmpty = empty && !modified - desktop.pedalboardModified = modified desktop.pedalboardPresetId = snapshotId desktop.pedalboardPresetName = resp.name + desktop.setPedalboardAsModified(modified) if (resp.ok) { desktop.titleBox.text((desktop.title || 'Untitled') + " - " + resp.name) diff --git a/html/js/snapshot.js b/html/js/snapshot.js index 63b21ab3..27a94905 100644 --- a/html/js/snapshot.js +++ b/html/js/snapshot.js @@ -102,7 +102,7 @@ function SnapshotsManager(options) { options.pedalPresetsWindow.find('.js-assign-all').addClass('disabled') } - // Replace options value and text so we can a sequential list 0, 1, 2, etc. + // Replace options value and text so we get a sequential list 1, 2, 3, etc. var i = 0 options.pedalPresetsList.children().each(function(option) { var optionHtml = $(this).html() diff --git a/mod/host.py b/mod/host.py index 6094f00d..ed70a140 100644 --- a/mod/host.py +++ b/mod/host.py @@ -3270,6 +3270,10 @@ def snapshot_load(self, idx, from_hmi, abort_catcher, callback): # callback must be last action callback(True) + def save_snapshots_to_disk(self): + if self.pedalboard_path: + self.save_state_snapshots(self.pedalboard_path) + @gen.coroutine def page_load(self, idx, abort_catcher, callback): if not self.addressings.addressing_pages: diff --git a/mod/session.py b/mod/session.py index bcd0a25a..4e7da8f0 100644 --- a/mod/session.py +++ b/mod/session.py @@ -69,6 +69,7 @@ def __init__(self): self.recordhandle = None self.external_ui_timer = None + self.screenshot_needed = False self.screenshot_generator = ScreenshotGenerator() self.websockets = [] @@ -155,10 +156,12 @@ def hmi_reinit_cb(self): # Add a new plugin, starts enabled (ie, not bypassed) def web_add(self, instance, uri, x, y, callback): + self.screenshot_needed = True self.host.add_plugin(instance, uri, x, y, callback) # Remove a plugin def web_remove(self, instance, callback): + self.screenshot_needed = True self.host.remove_plugin(instance, callback) # Address a plugin parameter @@ -181,10 +184,12 @@ def web_set_sync_mode(self, mode, callback): # Connect 2 ports def web_connect(self, port_from, port_to, callback): + self.screenshot_needed = True self.host.connect(port_from, port_to, callback) # Disconnect 2 ports def web_disconnect(self, port_from, port_to, callback): + self.screenshot_needed = True self.host.disconnect(port_from, port_to, callback) # Save the current pedalboard @@ -196,7 +201,10 @@ def web_save_pedalboard(self, title, asNew, callback): if self.hmi.initialized and self.host.descriptor.get('hmi_set_pb_name', False): self.hmi_set_pb_name(newTitle or title) - self.screenshot_generator.schedule_screenshot(bundlepath) + if bundlepath and self.screenshot_needed: + self.screenshot_needed = False + self.screenshot_generator.schedule_screenshot(bundlepath) + return bundlepath, newTitle # Get list of Hardware MIDI devices @@ -334,11 +342,13 @@ def ws_patch_set(self, instance, uri, valuetype, valuedata, ws): # Set a plugin block position within the canvas def ws_plugin_position(self, instance, x, y, ws): + self.screenshot_needed = True self.host.set_position(instance, x, y) self.msg_callback_broadcast("plugin_pos %s %d %d" % (instance, x, y), ws) # set the size of the pedalboard (in 1:1 view, aka "full zoom") def ws_pedalboard_size(self, width, height): + self.screenshot_needed = True self.host.set_pedalboard_size(width, height) def ws_show_external_ui(self, instance): @@ -412,6 +422,7 @@ def msg_callback_broadcast(self, msg, ws2): ws.write_message(msg) def load_pedalboard(self, bundlepath, isDefault): + self.screenshot_needed = False self.host.send_notmodified("feature_enable processing 0") title = self.host.load(bundlepath, isDefault) self.host.send_notmodified("feature_enable processing 1") @@ -429,6 +440,7 @@ def load_pedalboard(self, bundlepath, isDefault): def reset(self, callback): logging.debug("SESSION RESET") + self.screenshot_needed = False self.host.send_notmodified("feature_enable processing 0") def host_callback(resp): diff --git a/mod/webserver.py b/mod/webserver.py index 864b1581..d9d7d874 100644 --- a/mod/webserver.py +++ b/mod/webserver.py @@ -1599,6 +1599,7 @@ def post(self, mode): class SnapshotSave(JsonRequestHandler): def post(self): ok = SESSION.host.snapshot_save() + SESSION.host.save_snapshots_to_disk() self.write(ok) class SnapshotSaveAs(JsonRequestHandler): @@ -1611,6 +1612,7 @@ def get(self): yield gen.Task(SESSION.host.hmi_report_ss_name_if_current, idx) + SESSION.host.save_snapshots_to_disk() self.write({ 'ok': idx is not None, 'id': idx, @@ -1630,6 +1632,7 @@ def get(self): yield gen.Task(SESSION.host.hmi_report_ss_name_if_current, idx) + SESSION.host.save_snapshots_to_disk() self.write({ 'ok': ok, 'title': title, @@ -1639,6 +1642,7 @@ class SnapshotRemove(JsonRequestHandler): def get(self): idx = int(self.get_argument('id')) ok = SESSION.host.snapshot_remove(idx) + SESSION.host.save_snapshots_to_disk() self.write(ok) class SnapshotList(JsonRequestHandler):