diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Alias.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Alias.fxp index 3d0f83d92ba..878cb119fce 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Alias.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Alias.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Classic.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Classic.fxp index 0014df6ef80..c177fa9b8f9 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Classic.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Classic.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM2.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM2.fxp index fc8b427c265..204230938c8 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM2.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM2.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM3.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM3.fxp index 562763804b7..2e5c79a949a 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM3.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/FM3.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Modern.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Modern.fxp index e6bb4404f53..dc6c115e084 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Modern.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Modern.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/S&H Noise.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/S&H Noise.fxp index 95b8d35868a..dbe327b5132 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/S&H Noise.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/S&H Noise.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Sine.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Sine.fxp index 069050bb3e7..17455390e2e 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Sine.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Sine.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/String.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/String.fxp index 97966e0bbfb..00b5fcc5680 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/String.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/String.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Twist.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Twist.fxp index db935e2777a..fb11929d1a2 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Twist.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Twist.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Wavetable.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Wavetable.fxp index 573073017b6..28d21065cb6 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Wavetable.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Wavetable.fxp differ diff --git a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Window.fxp b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Window.fxp index 7ea2f526ec4..e47d00da027 100644 Binary files a/resources/data/patches_3rdparty/Jacky Ligon/Templates/Window.fxp and b/resources/data/patches_3rdparty/Jacky Ligon/Templates/Window.fxp differ diff --git a/resources/data/patches_factory/Templates/Audio In Left Osc 1 + Right Osc 2.fxp b/resources/data/patches_factory/Templates/Audio In Left Osc 1 + Right Osc 2.fxp index 1599cb2c4de..b7d0b317931 100644 Binary files a/resources/data/patches_factory/Templates/Audio In Left Osc 1 + Right Osc 2.fxp and b/resources/data/patches_factory/Templates/Audio In Left Osc 1 + Right Osc 2.fxp differ diff --git a/resources/data/patches_factory/Templates/Audio In Left Scene A + Right Scene B.fxp b/resources/data/patches_factory/Templates/Audio In Left Scene A + Right Scene B.fxp index 218b0debd4a..c950452df82 100644 Binary files a/resources/data/patches_factory/Templates/Audio In Left Scene A + Right Scene B.fxp and b/resources/data/patches_factory/Templates/Audio In Left Scene A + Right Scene B.fxp differ diff --git a/resources/data/patches_factory/Templates/Audio In Mono Osc 1.fxp b/resources/data/patches_factory/Templates/Audio In Mono Osc 1.fxp index 747a0e65993..636b76ede7a 100644 Binary files a/resources/data/patches_factory/Templates/Audio In Mono Osc 1.fxp and b/resources/data/patches_factory/Templates/Audio In Mono Osc 1.fxp differ diff --git a/resources/data/patches_factory/Templates/Audio In Stereo Osc 1.fxp b/resources/data/patches_factory/Templates/Audio In Stereo Osc 1.fxp index c80b3021ffd..61cfff1c801 100644 Binary files a/resources/data/patches_factory/Templates/Audio In Stereo Osc 1.fxp and b/resources/data/patches_factory/Templates/Audio In Stereo Osc 1.fxp differ diff --git a/resources/data/patches_factory/Templates/Init Env Per Osc.fxp b/resources/data/patches_factory/Templates/Init Env Per Osc.fxp index 3a7c30f8578..1908f3eab53 100644 Binary files a/resources/data/patches_factory/Templates/Init Env Per Osc.fxp and b/resources/data/patches_factory/Templates/Init Env Per Osc.fxp differ diff --git a/resources/data/patches_factory/Templates/Init FM2.fxp b/resources/data/patches_factory/Templates/Init FM2.fxp index c21b5659112..3a2685a2547 100644 Binary files a/resources/data/patches_factory/Templates/Init FM2.fxp and b/resources/data/patches_factory/Templates/Init FM2.fxp differ diff --git a/resources/data/patches_factory/Templates/Init Karplus-Strong.fxp b/resources/data/patches_factory/Templates/Init Karplus-Strong.fxp index 895f4a7eafb..406bae1728e 100644 Binary files a/resources/data/patches_factory/Templates/Init Karplus-Strong.fxp and b/resources/data/patches_factory/Templates/Init Karplus-Strong.fxp differ diff --git a/resources/data/patches_factory/Templates/Init Saw.fxp b/resources/data/patches_factory/Templates/Init Saw.fxp index 5ba7bc3c58f..25567a1802b 100644 Binary files a/resources/data/patches_factory/Templates/Init Saw.fxp and b/resources/data/patches_factory/Templates/Init Saw.fxp differ diff --git a/resources/data/patches_factory/Templates/Init Sine.fxp b/resources/data/patches_factory/Templates/Init Sine.fxp index a7fc6099332..e690592f57d 100644 Binary files a/resources/data/patches_factory/Templates/Init Sine.fxp and b/resources/data/patches_factory/Templates/Init Sine.fxp differ diff --git a/src/common/SkinModel.cpp b/src/common/SkinModel.cpp index 3f5b2083dac..6cba5039638 100644 --- a/src/common/SkinModel.cpp +++ b/src/common/SkinModel.cpp @@ -606,7 +606,7 @@ Connector oscilloscope = Connector("oscilloscope.window", 300, 263, 450, 212, Co Connector ws_analysis = Connector("filter.waveshaper_analysis.window", 450, 237, 300, 160, Components::Custom, Connector::WAVESHAPER_ANALYSIS_WINDOW); -Connector save_patch_dialog = Connector("controls.patch.save.window", 157, 57, 390, 270, +Connector save_patch_dialog = Connector("controls.patch.save.window", 157, 57, 390, 300, Components::Custom, Connector::SAVE_PATCH_DIALOG); // modulation panel is special, so it shows up as 'CUSTOM' with no connector and is special-cased in diff --git a/src/common/SurgePatch.cpp b/src/common/SurgePatch.cpp index 6c51959380a..2a31542421c 100644 --- a/src/common/SurgePatch.cpp +++ b/src/common/SurgePatch.cpp @@ -1334,6 +1334,17 @@ void SurgePatch::load_xml(const void *data, int datasize, bool is_preset) author = s; } + s = meta->Attribute("license"); + + if (s) + { + license = s; + } + else + { + license = ""; + } + auto *tagsX = TINYXML_SAFE_TO_ELEMENT(meta->FirstChild("tags")); tags.clear(); @@ -2883,6 +2894,7 @@ unsigned int SurgePatch::save_xml(void **data) // allocates mem, must be freed b meta.SetAttribute("category", this->category); meta.SetAttribute("comment", comment); meta.SetAttribute("author", author); + meta.SetAttribute("license", license); TiXmlElement tagsX("tags"); diff --git a/src/common/SurgeStorage.h b/src/common/SurgeStorage.h index bb8fa0cebcd..e1fab314911 100644 --- a/src/common/SurgeStorage.h +++ b/src/common/SurgeStorage.h @@ -924,7 +924,7 @@ class SurgePatch SurgeStorage *storage; // metadata - std::string name, category, author, comment; + std::string name, category, author, license, comment; struct Tag { diff --git a/src/common/SurgeSynthesizer.cpp b/src/common/SurgeSynthesizer.cpp index dda363fbf1b..2b3f5a22212 100644 --- a/src/common/SurgeSynthesizer.cpp +++ b/src/common/SurgeSynthesizer.cpp @@ -189,6 +189,7 @@ SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, const std::string &suppl storage.getPatch().name = "Init"; storage.getPatch().comment = ""; storage.getPatch().author = "Surge Synth Team"; + storage.getPatch().license = "Licensed under the maximally permissive CC0 license"; midiprogramshavechanged = false; for (int i = 0; i < BLOCK_SIZE; i++) diff --git a/src/common/SurgeSynthesizerIO.cpp b/src/common/SurgeSynthesizerIO.cpp index 6b18eeeb2d9..e5d1fe32d2a 100644 --- a/src/common/SurgeSynthesizerIO.cpp +++ b/src/common/SurgeSynthesizerIO.cpp @@ -261,12 +261,17 @@ bool SurgeSynthesizer::loadPatchByPath(const char *fxpPath, int categoryId, cons int cs = vt_read_int32BE(fxp.chunkSize); std::unique_ptr data{new char[cs]}; + if (f.sgetn(data.get(), cs) != cs) + { perror("Error while loading patch!"); + } + f.close(); storage.getPatch().comment = ""; storage.getPatch().author = ""; + if (categoryId >= 0) { storage.getPatch().category = storage.patch_category[categoryId].name; @@ -275,6 +280,7 @@ bool SurgeSynthesizer::loadPatchByPath(const char *fxpPath, int categoryId, cons { storage.getPatch().category = "Drag & Drop"; } + current_category_id = categoryId; storage.getPatch().name = patchName; diff --git a/src/surge-xt/gui/SurgeGUIEditorOverlays.cpp b/src/surge-xt/gui/SurgeGUIEditorOverlays.cpp index 25a7e9d4577..1660b7d67d6 100644 --- a/src/surge-xt/gui/SurgeGUIEditorOverlays.cpp +++ b/src/surge-xt/gui/SurgeGUIEditorOverlays.cpp @@ -38,6 +38,7 @@ std::unique_ptr SurgeGUIEditor::makeStorePatc std::string name = synth->storage.getPatch().name; std::string category = synth->storage.getPatch().category; std::string author = synth->storage.getPatch().author; + std::string license = synth->storage.getPatch().license; std::string comments = synth->storage.getPatch().comment; auto defaultAuthor = Surge::Storage::getUserDefaultValue( @@ -88,6 +89,7 @@ std::unique_ptr SurgeGUIEditor::makeStorePatc pb->setSkin(currentSkin); pb->setName(name); pb->setAuthor(author); + pb->setLicense(license); pb->setCategory(category); pb->setComment(comments); pb->setTags(synth->storage.getPatch().tags); diff --git a/src/surge-xt/gui/overlays/PatchStoreDialog.cpp b/src/surge-xt/gui/overlays/PatchStoreDialog.cpp index 21525e03d18..e0f87280f4c 100644 --- a/src/surge-xt/gui/overlays/PatchStoreDialog.cpp +++ b/src/surge-xt/gui/overlays/PatchStoreDialog.cpp @@ -151,12 +151,14 @@ PatchStoreDialog::PatchStoreDialog() nameEd->setWantsKeyboardFocus(true); authorEd = makeEd("patch author"); authorEd->setSelectAllWhenFocused(true); + tagEd = makeEd("patch tags"); + tagEd->setVisible(showTagsField); + licenseEd = makeEd("patch license"); + licenseEd->setSelectAllWhenFocused(true); commentEd = makeEd("patch comment"); commentEd->setMultiLine(true, true); commentEd->setReturnKeyStartsNewLine(true); commentEd->setJustification(juce::Justification::topLeft); - tagEd = makeEd("patch tags"); - tagEd->setVisible(showTagsField); categoryProvider = std::make_unique(); auto ta = std::make_unique("patch category", categoryProvider.get()); @@ -178,6 +180,7 @@ PatchStoreDialog::PatchStoreDialog() nameEdL = makeL("Name"); authorEdL = makeL("Author"); tagEdL = makeL("Tags"); + licenseEdL = makeL("License"); catEdL = makeL("Category"); commentEdL = makeL("Comment"); @@ -274,12 +277,14 @@ void PatchStoreDialog::onSkinChanged() resetColors(authorEd); resetColors(catEd); resetColors(tagEd); + resetColors(licenseEd); resetColors(commentEd); resetLabel(nameEdL); resetLabel(authorEdL); resetLabel(catEdL); resetLabel(tagEdL); + resetLabel(licenseEdL); resetLabel(commentEdL); resetLabel(storeTuningLabel); @@ -309,7 +314,7 @@ void PatchStoreDialog::setIsRename(bool b) { isRename = b; } void PatchStoreDialog::resized() { auto h = 25; - auto commH = getHeight() - (5 + showTagsField) * h + 8; + auto commH = getHeight() - (6 + showTagsField) * h + 8; auto xSplit = 70; auto buttonWidth = 50; auto margin = 4; @@ -328,6 +333,9 @@ void PatchStoreDialog::resized() ce = ce.translated(0, h); authorEd->setBounds(ce); authorEd->setIndents(4, (authorEd->getHeight() - authorEd->getTextHeight()) / 2); + ce = ce.translated(0, h); + licenseEd->setBounds(ce); + licenseEd->setIndents(4, (licenseEd->getHeight() - licenseEd->getTextHeight()) / 2); if (isVisible()) { @@ -364,6 +372,8 @@ void PatchStoreDialog::resized() catEdL->setBounds(cl); cl = cl.translated(0, h); authorEdL->setBounds(cl); + cl = cl.translated(0, h); + licenseEdL->setBounds(cl); if (showTagsField) { @@ -406,6 +416,7 @@ void PatchStoreDialog::buttonClicked(juce::Button *button) synth->storage.getPatch().name = nameEd->getText().toStdString(); synth->storage.getPatch().author = authorEd->getText().toStdString(); synth->storage.getPatch().category = catEd->getText().toStdString(); + synth->storage.getPatch().license = licenseEd->getText().toStdString(); synth->storage.getPatch().comment = commentEd->getText().toStdString(); auto tagString = tagEd->getText(); diff --git a/src/surge-xt/gui/overlays/PatchStoreDialog.h b/src/surge-xt/gui/overlays/PatchStoreDialog.h index 06530693436..6c556ee4e9c 100644 --- a/src/surge-xt/gui/overlays/PatchStoreDialog.h +++ b/src/surge-xt/gui/overlays/PatchStoreDialog.h @@ -72,6 +72,7 @@ struct PatchStoreDialog : public OverlayComponent, void setName(const std::string &n) { nameEd->setText(n, juce::dontSendNotification); } void setAuthor(const std::string &a) { authorEd->setText(a, juce::dontSendNotification); } + void setLicense(const std::string &a) { licenseEd->setText(a, juce::dontSendNotification); } void setCategory(const std::string &c) { catEd->setText(c, juce::dontSendNotification); } void setComment(const std::string &c) { commentEd->setText(c, juce::dontSendNotification); } void setTags(const std::vector &t); @@ -79,8 +80,8 @@ struct PatchStoreDialog : public OverlayComponent, void onSkinChanged() override; void buttonClicked(juce::Button *button) override; - std::unique_ptr nameEd, authorEd, catEd, tagEd, commentEd; - std::unique_ptr nameEdL, authorEdL, catEdL, tagEdL, commentEdL; + std::unique_ptr nameEd, authorEd, catEd, licenseEd, tagEd, commentEd; + std::unique_ptr nameEdL, authorEdL, catEdL, licenseEdL, tagEdL, commentEdL; std::unique_ptr okButton, okOverButton, cancelButton; std::unique_ptr storeTuningLabel; std::unique_ptr storeTuningButton; diff --git a/src/surge-xt/gui/widgets/PatchSelector.cpp b/src/surge-xt/gui/widgets/PatchSelector.cpp index 9d85d23a2b4..6cdadaca68b 100644 --- a/src/surge-xt/gui/widgets/PatchSelector.cpp +++ b/src/surge-xt/gui/widgets/PatchSelector.cpp @@ -1379,30 +1379,41 @@ void PatchSelectorCommentTooltip::paint(juce::Graphics &g) } void PatchSelectorCommentTooltip::positionForComment(const juce::Point ¢erPoint, - const std::string &c, const int maxWidth) + const std::string &c, + const int maxTooltipWidth) { comment = c; std::stringstream ss(comment); std::string to; - int idx = 0; + int numLines = 0; auto ft = skin->fontManager->getLatoAtSize(9); - auto width = 0; + auto width = 0.f; while (std::getline(ss, to, '\n')) { - auto w = ft.getStringWidth(to); + auto w = ft.getStringWidthFloat(to); + + // in case of an empty line, we still need to count it as an extra row + // so bump it up a bit so that the rows calculation ceils to 1 + if (w == 0.f) + { + w = 1.f; + } + + auto rows = std::ceil(w / (float)maxTooltipWidth); + width = std::max(w, width); - idx++; + numLines += (int)rows; } - auto height = std::max(idx * (ft.getHeight() + 2), 30.f); + auto height = std::max(numLines * (ft.getHeight() + 2), 30.f); auto r = juce::Rectangle() .withCentre(juce::Point(centerPoint.x, centerPoint.y)) - .withSizeKeepingCentre(std::min(width + 12, maxWidth), height) + .withSizeKeepingCentre(std::min(width, (float)maxTooltipWidth), height) .translated(0, height / 2); setBounds(r); diff --git a/src/surge-xt/gui/widgets/PatchSelector.h b/src/surge-xt/gui/widgets/PatchSelector.h index 31e0b120f78..a52da83d658 100644 --- a/src/surge-xt/gui/widgets/PatchSelector.h +++ b/src/surge-xt/gui/widgets/PatchSelector.h @@ -204,7 +204,7 @@ struct PatchSelectorCommentTooltip : public juce::Component, std::string comment; void positionForComment(const juce::Point ¢erPoint, const std::string &comment, - const int maxWidth); + const int maxTooltipWidth); protected: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PatchSelectorCommentTooltip);