api_package.cpp (5406B)
1 /* ReaPack: Package manager for REAPER 2 * Copyright (C) 2015-2025 Christian Fillion 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "api.hpp" 19 #include "api_helper.hpp" 20 21 #include "about.hpp" 22 #include "errors.hpp" 23 #include "index.hpp" 24 #include "reapack.hpp" 25 #include "registry.hpp" 26 #include "remote.hpp" 27 #include "transaction.hpp" 28 29 struct PackageEntry { 30 Registry::Entry regEntry; 31 std::vector<Registry::File> files; 32 }; 33 34 static std::set<PackageEntry *> s_entries; 35 36 DEFINE_API(bool, AboutInstalledPackage, ((PackageEntry*, entry)), 37 R"(Show the about dialog of the given package entry. 38 The repository index is downloaded asynchronously if the cached copy doesn't exist or is older than one week.)", 39 { 40 if(!s_entries.count(entry)) 41 return false; 42 43 // the one given by the user may be deleted while we download the idnex 44 const Registry::Entry entryCopy = entry->regEntry; 45 46 const Remote &repo = g_reapack->remote(entryCopy.remote); 47 if(!repo) 48 return false; 49 50 Transaction *tx = g_reapack->setupTransaction(); 51 if(!tx) 52 return false; 53 54 const std::vector<Remote> repos{repo}; 55 56 tx->fetchIndexes(repos); 57 tx->onFinish >> [=] { 58 const auto &indexes = tx->getIndexes(repos); 59 if(indexes.empty()) 60 return; 61 62 const Package *pkg = indexes.front()->find(entryCopy.category, entryCopy.package); 63 if(pkg) 64 g_reapack->about()->setDelegate(std::make_shared<AboutPackageDelegate>( 65 pkg, entryCopy.version)); 66 }; 67 tx->runTasks(); 68 69 return true; 70 }); 71 72 DEFINE_API(bool, EnumOwnedFiles, ((PackageEntry*, entry))((int, index)) 73 ((char*, pathOut))((int, pathOut_sz))((int*, sectionsOut))((int*, typeOut)), 74 R"(Enumerate the files owned by the given package. Returns false when there is no more data. 75 76 sections: 0=not in action list, &1=main, &2=midi editor, &4=midi inline editor 77 type: see <a href="#ReaPack_GetEntryInfo">ReaPack_GetEntryInfo</a>.)", 78 { 79 const size_t i = index; 80 81 if(!s_entries.count(entry) || i >= entry->files.size()) 82 return false; 83 84 const Registry::File &file = entry->files[i]; 85 if(pathOut) 86 snprintf(pathOut, pathOut_sz, "%s", file.path.prependRoot().join().c_str()); 87 if(sectionsOut) 88 *sectionsOut = file.sections; 89 if(typeOut) 90 *typeOut = static_cast<int>(file.type); 91 92 return entry->files.size() > i + 1; 93 }); 94 95 DEFINE_API(bool, FreeEntry, ((PackageEntry*, entry)), 96 R"(Free resources allocated for the given package entry.)", 97 { 98 if(!s_entries.count(entry)) 99 return false; 100 101 s_entries.erase(entry); 102 delete entry; 103 return true; 104 }); 105 106 DEFINE_API(bool, GetEntryInfo, ((PackageEntry*, entry)) 107 ((char*, repoOut))((int, repoOut_sz))((char*, catOut))((int, catOut_sz)) 108 ((char*, pkgOut))((int, pkgOut_sz))((char*, descOut))((int, descOut_sz)) 109 ((int*, typeOut))((char*, verOut))((int, verOut_sz)) 110 ((char*, authorOut))((int, authorOut_sz)) 111 ((int*, flagsOut))((int*, fileCountOut)), 112 R"(Get the repository name, category, package name, package description, package type, the currently installed version, author name, flags (&1=Pinned, &2=BleedingEdge) and how many files are owned by the given package entry. 113 114 type: 1=script, 2=extension, 3=effect, 4=data, 5=theme, 6=langpack, 7=webinterface)", 115 { 116 if(!s_entries.count(entry)) 117 return false; 118 119 const Registry::Entry ®Entry = entry->regEntry; 120 121 if(repoOut) 122 snprintf(repoOut, repoOut_sz, "%s", regEntry.remote.c_str()); 123 if(catOut) 124 snprintf(catOut, catOut_sz, "%s", regEntry.category.c_str()); 125 if(pkgOut) 126 snprintf(pkgOut, pkgOut_sz, "%s", regEntry.package.c_str()); 127 if(descOut) 128 snprintf(descOut, descOut_sz, "%s", regEntry.description.c_str()); 129 if(typeOut) 130 *typeOut = static_cast<int>(regEntry.type); 131 if(verOut) 132 snprintf(verOut, verOut_sz, "%s", regEntry.version.toString().c_str()); 133 if(authorOut) 134 snprintf(authorOut, authorOut_sz, "%s", regEntry.author.c_str()); 135 if(flagsOut) 136 *flagsOut = regEntry.flags; 137 if(fileCountOut) 138 *fileCountOut = static_cast<int>(entry->files.size()); 139 140 return true; 141 }); 142 143 DEFINE_API(PackageEntry*, GetOwner, ((const char*, fn))((char*, errorOut))((int, errorOut_sz)), 144 R"(Returns the package entry owning the given file. 145 Delete the returned object from memory after use with <a href="#ReaPack_FreeEntry">ReaPack_FreeEntry</a>.)", 146 { 147 try { 148 const Registry reg(Path::REGISTRY.prependRoot()); 149 const auto &owner = reg.getOwner(Path(fn).removeRoot()); 150 151 if(owner) { 152 auto entry = new PackageEntry{owner, reg.getFiles(owner)}; 153 s_entries.insert(entry); 154 return entry; 155 } 156 else if(errorOut) 157 snprintf(errorOut, errorOut_sz, "the file is not owned by any package entry"); 158 159 return nullptr; 160 } 161 catch(const reapack_error &e) 162 { 163 if(errorOut) 164 snprintf(errorOut, errorOut_sz, "%s", e.what()); 165 166 return nullptr; 167 } 168 });