savepatchdesc.cpp (3191B)
1 #include "savepatchdesc.h" 2 3 #include "patchmanager.h" 4 5 #include "jucePluginLib/filetype.h" 6 7 #include "synthLib/sysexToMidi.h" 8 9 namespace jucePluginEditorLib::patchManager 10 { 11 SavePatchDesc::SavePatchDesc(PatchManager& _pm, const int _part, std::string _name) 12 : m_patchManager(_pm) 13 , m_part(_part) 14 , m_name(std::move(_name)) 15 { 16 } 17 18 SavePatchDesc::SavePatchDesc(PatchManager& _pm, std::map<uint32_t, pluginLib::patchDB::PatchPtr>&& _patches, std::string _name) 19 : m_patchManager(_pm) 20 , m_part(InvalidPart) 21 , m_patches(std::move(_patches)) 22 , m_name(std::move(_name)) 23 { 24 } 25 26 std::map<uint32_t, pluginLib::patchDB::PatchPtr>& SavePatchDesc::getPatches() const 27 { 28 if(m_patches.empty() && isPartValid()) 29 { 30 auto patch = m_patchManager.requestPatchForPart(m_part); 31 if(!patch) 32 return m_patches; 33 m_patches.insert({m_part, patch}); 34 } 35 return m_patches; 36 } 37 38 bool SavePatchDesc::writePatchesToFile(const juce::File& _file) const 39 { 40 const auto& patches = getPatches(); 41 42 if(patches.empty()) 43 return false; 44 45 std::vector<std::vector<uint8_t>> patchesData; 46 47 for (auto& patch : patches) 48 { 49 auto data = m_patchManager.applyModifications(patch.second, pluginLib::FileType::Mid, pluginLib::ExportType::DragAndDrop); 50 if(data.empty()) 51 return false; 52 patchesData.emplace_back(std::move(data)); 53 } 54 55 std::stringstream ss; 56 57 synthLib::SysexToMidi::write(ss, patchesData); 58 59 const auto size = ss.tellp(); 60 std::vector<char> buffer; 61 buffer.resize(size); 62 ss.read(buffer.data(), size); 63 64 return _file.replaceWithData(buffer.data(), size); 65 } 66 67 std::string getPatchName(const pluginLib::patchDB::PatchPtr& _patch) 68 { 69 auto name = _patch->getName(); 70 71 // trim whitespace 72 while(!name.empty() && name.back() == ' ') 73 name.pop_back(); 74 75 return name; 76 } 77 78 std::string createValidFilename(const std::string& _name) 79 { 80 std::string result; 81 result.reserve(_name.size()); 82 83 const std::string invalid = "\\/:?\"<>|"; 84 85 for (const char c : _name) 86 { 87 if(invalid.find(c) != std::string::npos) 88 result += '_'; 89 else 90 result += c; 91 } 92 return result; 93 } 94 95 std::string SavePatchDesc::getExportFileName(const pluginLib::Processor& _p) const 96 { 97 const auto& patches = getPatches(); 98 99 std::string name; 100 101 if(patches.size() == 1) 102 { 103 name = getPatchName(patches.begin()->second); // if there is only one patch, we use the name of the patch 104 } 105 else if(!m_name.empty()) 106 { 107 name = m_name; // otherwise use custom name if provided 108 } 109 else 110 { 111 name = std::to_string(patches.size()) + " patches"; 112 } 113 114 return _p.getProperties().name + " - " + createValidFilename(name) + ".mid"; 115 } 116 117 bool SavePatchDesc::writeToFile(const juce::File& _file) const 118 { 119 return writePatchesToFile(_file); 120 } 121 122 std::vector<pluginLib::patchDB::PatchPtr> SavePatchDesc::getPatchesFromDragSource(const juce::DragAndDropTarget::SourceDetails& _dragSourceDetails) 123 { 124 const auto* savePatchDesc = fromDragSource(_dragSourceDetails); 125 126 if(!savePatchDesc) 127 return {}; 128 129 std::vector<pluginLib::patchDB::PatchPtr> patches; 130 131 for (const auto& it : savePatchDesc->getPatches()) 132 patches.push_back(it.second); 133 134 return patches; 135 } 136 }