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