diff --git a/src/synth/patch.cpp b/src/synth/patch.cpp index 4be76ed..00b949f 100644 --- a/src/synth/patch.cpp +++ b/src/synth/patch.cpp @@ -22,6 +22,7 @@ namespace baconpaul::six_sines void Patch::resetToInit() { + dirty = false; // Sweep any new param since this stream to default for (auto [id, p] : paramMap) { diff --git a/src/synth/patch.h b/src/synth/patch.h index fd39d3a..85becab 100644 --- a/src/synth/patch.h +++ b/src/synth/patch.h @@ -56,6 +56,7 @@ struct Param struct Patch { + bool dirty{false}; static constexpr uint32_t patchVersion{8}; std::vector params; std::unordered_map paramMap; diff --git a/src/synth/synth.cpp b/src/synth/synth.cpp index 35793fa..ed03ab5 100644 --- a/src/synth/synth.cpp +++ b/src/synth/synth.cpp @@ -256,6 +256,13 @@ void Synth::processUIQueue(const clap_output_events_t *outq) { resetPlaymode(); } + + auto d = patch.dirty; + if (!d) + { + patch.dirty = true; + audioToUi.push({AudioToUIMsg::SET_PATCH_DIRTY_STATE, patch.dirty}); + } } break; case UIToAudioMsg::BEGIN_EDIT: @@ -291,6 +298,12 @@ void Synth::processUIQueue(const clap_output_events_t *outq) audioToUi.push({AudioToUIMsg::SET_PATCH_NAME, 0, 0, 0, patch.name}); } break; + case UIToAudioMsg::SEND_PATCH_IS_CLEAN: + { + patch.dirty = false; + audioToUi.push({AudioToUIMsg::SET_PATCH_DIRTY_STATE, patch.dirty}); + } + break; case UIToAudioMsg::EDITOR_ATTACH_DETATCH: { isEditorAttached = uiM->paramId; @@ -363,6 +376,7 @@ void Synth::pushFullUIRefresh() audioToUi.push(au); } audioToUi.push({AudioToUIMsg::SET_PATCH_NAME, 0, 0, 0, patch.name}); + audioToUi.push({AudioToUIMsg::SET_PATCH_DIRTY_STATE, patch.dirty}); } } // namespace baconpaul::six_sines \ No newline at end of file diff --git a/src/synth/synth.h b/src/synth/synth.h index f862872..769c708 100644 --- a/src/synth/synth.h +++ b/src/synth/synth.h @@ -251,7 +251,8 @@ struct Synth UPDATE_PARAM, UPDATE_VU, UPDATE_VOICE_COUNT, - SET_PATCH_NAME + SET_PATCH_NAME, + SET_PATCH_DIRTY_STATE } action; uint32_t paramId{0}; float value{0}, value2{0}; @@ -268,6 +269,7 @@ struct Synth STOP_AUDIO, START_AUDIO, SEND_PATCH_NAME, + SEND_PATCH_IS_CLEAN, EDITOR_ATTACH_DETATCH, // paramid is true for attach and false for detach PANIC_STOP_VOICES } action; diff --git a/src/ui/preset-manager.cpp b/src/ui/preset-manager.cpp index 15f84b0..691d360 100644 --- a/src/ui/preset-manager.cpp +++ b/src/ui/preset-manager.cpp @@ -45,32 +45,37 @@ struct PresetDataBinding : sst::jucegui::data::Discrete int getValue() const override { return curr; } int getDefaultValue() const override { return 0; }; + bool isDirty{false}; + std::string getValueAsStringFor(int i) const override { if (hasExtra && i < 0) return extraName; + std::string postfix = isDirty ? " *" : ""; + if (i == 0) - return "Init"; + return "Init" + postfix; auto fp = i - 1; if (fp < pm.factoryPatchVector.size()) { fs::path p{pm.factoryPatchVector[fp].first}; p = p / pm.factoryPatchVector[fp].second; p = p.replace_extension(""); - return p.u8string(); + return p.u8string() + postfix; } fp -= pm.factoryPatchVector.size(); if (fp < pm.userPatches.size()) { auto pt = pm.userPatches[fp]; pt = pt.replace_extension(""); - return pt.u8string(); + return pt.u8string() + postfix; } return "ERR"; } void setValueFromGUI(const int &f) override { + isDirty = false; if (hasExtra) { hasExtra = false; @@ -344,4 +349,6 @@ void PresetManager::setStateForDisplayName(const std::string &s) } } +void PresetManager::setDirtyState(bool b) { discreteDataBinding->isDirty = b; } + } // namespace baconpaul::six_sines::ui \ No newline at end of file diff --git a/src/ui/preset-manager.h b/src/ui/preset-manager.h index 9ccca97..94793d2 100644 --- a/src/ui/preset-manager.h +++ b/src/ui/preset-manager.h @@ -55,6 +55,8 @@ struct PresetManager std::unique_ptr discreteDataBinding; sst::jucegui::data::Discrete *getDiscreteData(); + + void setDirtyState(bool b); }; } // namespace baconpaul::six_sines::ui #endif // PRESET_MANAGER_H diff --git a/src/ui/six-sines-editor.cpp b/src/ui/six-sines-editor.cpp index e93da59..f1fcda1 100644 --- a/src/ui/six-sines-editor.cpp +++ b/src/ui/six-sines-editor.cpp @@ -194,6 +194,16 @@ void SixSinesEditor::idle() strncpy(patchCopy.name, aum->hackPointer, 255); setPatchNameDisplay(); } + else if (aum->action == Synth::AudioToUIMsg::SET_PATCH_DIRTY_STATE) + { + patchCopy.dirty = (bool)aum->paramId; + presetManager->setDirtyState(patchCopy.dirty); + presetButton->repaint(); + } + else + { + SXSNLOG("Ignored patch message " << aum->action); + } aum = audioToUI.pop(); } } @@ -645,6 +655,7 @@ void SixSinesEditor::sendEntirePatchToAudio(const std::string &s) uiToAudio.push({Synth::UIToAudioMsg::END_EDIT, p->meta.id}); } uiToAudio.push({Synth::UIToAudioMsg::START_AUDIO}); + uiToAudio.push({Synth::UIToAudioMsg::SEND_PATCH_IS_CLEAN, true}); } void SixSinesEditor::setParamValueOnCopy(uint32_t paramId, float value, bool notifyAudio)