reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

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 &regEntry = 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 });