omni/ext/ExtensionsUtils.h
File members: omni/ext/ExtensionsUtils.h
// Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once
#include "IExtensions.h"
#include "../../carb/ObjectUtils.h"
#include "../../carb/dictionary/DictionaryUtils.h"
#include "../../carb/settings/ISettings.h"
#include "../../carb/settings/SettingsUtils.h"
#include <functional>
#include <string>
#include <utility>
#include <vector>
namespace omni
{
namespace ext
{
inline std::string getExtensionPath(ExtensionManager* manager, const char* extId)
{
    auto dict = carb::dictionary::getCachedDictionaryInterface();
    carb::dictionary::Item* infoDict = manager->getExtensionDict(extId);
    return infoDict ? dict->get<const char*>(infoDict, "path") : "";
}
inline const char* getEnabledExtensionId(ExtensionManager* manager, const char* extFullName)
{
    size_t count;
    ExtensionInfo* extensions;
    manager->fetchExtensionVersions(extFullName, &extensions, &count);
    for (size_t i = 0; i < count; i++)
    {
        if (extensions[i].enabled)
            return extensions[i].id;
    }
    return nullptr;
}
inline bool isExtensionEnabled(ExtensionManager* manager, const char* extFullName)
{
    return getEnabledExtensionId(manager, extFullName) != nullptr;
}
inline std::vector<ExtensionInfo> fetchAllExtensionPackages(ExtensionManager* manager)
{
    std::vector<ExtensionInfo> packages;
    ExtensionSummary* summaries;
    size_t summaryCount;
    manager->fetchExtensionSummaries(&summaries, &summaryCount);
    for (size_t i = 0; i < summaryCount; i++)
    {
        const ExtensionSummary& summary = summaries[i];
        ExtensionInfo* extensions;
        size_t extensionCount;
        manager->fetchExtensionPackages(summary.fullname, &extensions, &extensionCount);
        packages.insert(packages.end(), extensions, extensions + extensionCount);
    }
    return packages;
}
class ExtensionStateChangeHookLambda : public IExtensionStateChangeHook
{
public:
    ExtensionStateChangeHookLambda(const std::function<void(const char*, ExtensionStateChangeType)>& fn) : m_fn(fn)
    {
    }
    void onStateChange(const char* extId, ExtensionStateChangeType type) override
    {
        if (m_fn)
            m_fn(extId, type);
    }
private:
    std::function<void(const char*, ExtensionStateChangeType)> m_fn;
    CARB_IOBJECT_IMPL
};
inline IHookHolderPtr createExtensionStateChangeHook(
    IExtensionManagerHooks* hooks,
    const std::function<void(const char* extId, ExtensionStateChangeType type)>& onStateChange,
    ExtensionStateChangeType type,
    const char* extFullName = "",
    const char* extDictPath = "",
    Order order = kDefaultOrder,
    const char* hookName = nullptr)
{
    return hooks->createExtensionStateChangeHook(
        carb::stealObject(new ExtensionStateChangeHookLambda(onStateChange)).get(), type, extFullName, extDictPath,
        order, hookName);
}
inline std::pair<IHookHolderPtr, IHookHolderPtr> subscribeToExtensionEnable(
    ExtensionManager* manager,
    const std::function<void(const char* extId)>& onEnable,
    const std::function<void(const char* extId)>& onDisable = nullptr,
    const char* extFullName = "",
    const char* hookName = nullptr)
{
    // Already enabled?
    if (extFullName && extFullName[0] != '\0')
    {
        const char* enabledExtId = getEnabledExtensionId(manager, extFullName);
        if (enabledExtId)
            onEnable(enabledExtId);
    }
    // Subscribe for enabling:
    IHookHolderPtr holder0 = createExtensionStateChangeHook(
        manager->getHooks(), [onEnable = onEnable](const char* extId, ExtensionStateChangeType) { onEnable(extId); },
        ExtensionStateChangeType::eAfterExtensionEnable, extFullName, "", kDefaultOrder, hookName);
    // Optionally subscribe for disabling
    IHookHolderPtr holder1;
    if (onDisable)
        holder1 = createExtensionStateChangeHook(
            manager->getHooks(),
            [onDisable = onDisable](const char* extId, ExtensionStateChangeType) { onDisable(extId); },
            ExtensionStateChangeType::eBeforeExtensionShutdown, extFullName, "", kDefaultOrder, hookName);
    return std::make_pair(holder0, holder1);
}
struct ExtPathUrl
{
    std::string scheme;
    std::string path;
};
inline ExtPathUrl parseExtUrl(const std::string& url)
{
    const std::string kSchemeDelimiter = ":";
    auto pos = url.find(kSchemeDelimiter);
    if (pos == std::string::npos || pos == 1)
        return { "", url };
    ExtPathUrl res = {};
    res.scheme = url.substr(0, pos);
    res.path = url.substr(pos + kSchemeDelimiter.size() + 1);
    res.path = res.path.erase(0, res.path.find_first_not_of("/"));
    return res;
}
} // namespace ext
} // namespace omni