<commit_before>#include <Internal/DoremiEngineImplementation.hpp>
#include <Subsystem/EngineModuleEnum.hpp>

#include <DoremiEngine/Audio/Include/AudioModule.hpp>
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Graphic/Include/GraphicModule.hpp>
#include <DoremiEngine/Network/Include/NetworkModule.hpp>
#include <DoremiEngine/Input/Include/InputModule.hpp>
#include <DoremiEngine/AI/Include/AIModule.hpp>
#include <Utility/DynamicLoader/Include/DynamicLoader.hpp>

#include <Internal/SharedContextImplementation.hpp>
#include <Windows.h>

// Logging
#include <Utility/DebugLog/Include/ConsoleManager.hpp>

namespace DoremiEngine
{
    namespace Core
    {
        DoremiEngineImplementation::DoremiEngineImplementation()
            : m_audioLibrary(nullptr),
              m_graphicLibrary(nullptr),
              m_networkLibrary(nullptr),
              m_physicsLibrary(nullptr),
              m_inputLibrary(nullptr),
              m_audioModule(nullptr),
              m_graphicModule(nullptr),
              m_networkModule(nullptr),
              m_physicsModule(nullptr),
              m_inputModule(nullptr),
              m_aiModule(nullptr),
              m_logger(nullptr)
        {
            Utility::DebugLog::ConsoleManager::Startup();
            m_logger = &Utility::DebugLog::ConsoleManager::GetInstance().CreateNewConsole("engine", false);
        }

        DoremiEngineImplementation::~DoremiEngineImplementation()
        {
            if(m_audioModule != nullptr)
            {
                delete m_audioModule;
            }

            if(m_graphicModule != nullptr)
            {
                delete m_graphicModule;
            }

            if(m_networkModule != nullptr)
            {
                delete m_networkModule;
            }

            if(m_physicsModule != nullptr)
            {
                delete m_physicsModule;
            }

            if(m_audioLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_audioLibrary);
            }
            if(m_graphicLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_graphicLibrary);
            }
            if(m_networkLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_networkLibrary);
            }
            if(m_physicsLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_physicsLibrary);
            }
            if(m_aiLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_aiLibrary);
            }
        }

        SharedContext& DoremiEngineImplementation::Start(const size_t& p_flags)
        {
            m_sharedContext = new SharedContextImplementation();
            m_sharedContext->SetCoreModule(this);
            BuildWorkingDirectory(*m_sharedContext);

            if((p_flags & EngineModuleEnum::AUDIO) == EngineModuleEnum::AUDIO)
            {
                LoadAudioModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::GRAPHIC) == EngineModuleEnum::GRAPHIC)
            {
                LoadGraphicModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::NETWORK) == EngineModuleEnum::NETWORK)
            {
                LoadNetworkModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::PHYSICS) == EngineModuleEnum::PHYSICS)
            {
                LoadPhysicsModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::INPUT) == EngineModuleEnum::INPUT)
            {
                LoadInputModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::AI) == EngineModuleEnum::AI)
            {
                LoadAIModule(*m_sharedContext);
            }
            return *m_sharedContext;
        }

        void DoremiEngineImplementation::Stop()
        {
            if(m_audioModule != nullptr)
            {
                m_audioModule->Shutdown();
            }

            if(m_graphicModule != nullptr)
            {
                m_graphicModule->Shutdown();
            }

            if(m_networkModule != nullptr)
            {
                m_networkModule->Shutdown();
            }

            if(m_physicsModule != nullptr)
            {
                m_physicsModule->Shutdown();
            }

            if(m_aiModule != nullptr)
            {
                m_aiModule->Shutdown();
            }
        }

        void DoremiEngineImplementation::BuildWorkingDirectory(SharedContextImplementation& o_sharedContext)
        {
            char path[254];
            GetModuleFileNameA(NULL, path, 254);
            std::string* directoryPath = new std::string(path);
            o_sharedContext.SetWorkingDirectory(directoryPath->substr(0, directoryPath->length() - 10));
        }

        void DoremiEngineImplementation::LoadAudioModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Audio.dll");
            m_audioLibrary = DynamicLoader::LoadSharedLibrary("Audio.dll");

            if(m_audioLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Audio.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Audio.dll");

                CREATE_AUDIO_MODULE functionCreateAudioModule = (CREATE_AUDIO_MODULE)DynamicLoader::LoadProcess(m_audioLibrary, "CreateAudioModule");
                if(functionCreateAudioModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Audio.dll - Success");

                    m_audioModule = static_cast<Audio::AudioModule*>(functionCreateAudioModule(o_sharedContext));
                    m_audioModule->Startup();
                    o_sharedContext.SetAudioModule(m_audioModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Audio.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Audio.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadGraphicModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Graphic.dll");
            m_graphicLibrary = DynamicLoader::LoadSharedLibrary("Graphic.dll");

            if(m_graphicLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Graphic.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Graphic.dll");
                CREATE_GRAPHIC_MODULE functionCreateGraphicModule =
                    (CREATE_GRAPHIC_MODULE)DynamicLoader::LoadProcess(m_graphicLibrary, "CreateGraphicModule");
                if(functionCreateGraphicModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Graphic.dll - Success");
                    m_graphicModule = static_cast<Graphic::GraphicModule*>(functionCreateGraphicModule(o_sharedContext));
                    m_graphicModule->Startup();
                    o_sharedContext.SetGraphicModule(m_graphicModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Graphic.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Graphic.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadNetworkModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Network.dll");
            m_networkLibrary = DynamicLoader::LoadSharedLibrary("Network.dll");

            if(m_networkLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Network.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Network.dll");
                CREATE_NETWORK_MODULE functionCreateNetworkModule =
                    (CREATE_NETWORK_MODULE)DynamicLoader::LoadProcess(m_networkLibrary, "CreateNetworkModule");
                if(functionCreateNetworkModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Network.dll - Success");
                    m_networkModule = static_cast<Network::NetworkModule*>(functionCreateNetworkModule(o_sharedContext));
                    m_networkModule->Startup();
                    o_sharedContext.SetNetworkModule(m_networkModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Network.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Network.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadPhysicsModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Physics.dll");
            m_physicsLibrary = DynamicLoader::LoadSharedLibrary("Physics.dll");

            if(m_physicsLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Physics.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Physics.dll");
                CREATE_PHYSICS_MODULE functionCreatePhysicsModule =
                    (CREATE_PHYSICS_MODULE)DynamicLoader::LoadProcess(m_physicsLibrary, "CreatePhysicsModule");
                if(functionCreatePhysicsModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Physics.dll - Success");
                    m_physicsModule = static_cast<Physics::PhysicsModule*>(functionCreatePhysicsModule(o_sharedContext));
                    m_physicsModule->Startup();
                    o_sharedContext.SetPhysicsModule(m_physicsModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Physics.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Physics.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadInputModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Input.dll");
            m_inputLibrary = DynamicLoader::LoadSharedLibrary("Input.dll");

            if(m_inputLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Input.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Input.dll");
                CREATE_INPUT_MODULE functionCreateInputModule = (CREATE_INPUT_MODULE)DynamicLoader::LoadProcess(m_inputLibrary, "CreateInputModule");
                if(functionCreateInputModule != nullptr)
                {
                    //              m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Input.dll - Success");
                    m_inputModule = static_cast<Input::InputModule*>(functionCreateInputModule(o_sharedContext));
                    m_inputModule->Startup();
                    o_sharedContext.SetInputModule(m_inputModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Input.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Input.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadAIModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading AI.dll");
            m_aiLibrary = DynamicLoader::LoadSharedLibrary("AI.dll");

            if(m_aiLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading AI.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from AI.dll");
                CREATE_AI_MODULE functionCreateAIModule = (CREATE_AI_MODULE)DynamicLoader::LoadProcess(m_aiLibrary, "CreateAIModule");
                if(functionCreateAIModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from AI.dll - Success");

                    m_aiModule = static_cast<AI::AIModule*>(functionCreateAIModule(o_sharedContext));
                    m_aiModule->Startup();
                    o_sharedContext.SetAIModule(m_aiModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from AI.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading AI.dll - Failed");
            }
        }
    }
}

namespace
{
    DoremiEngine::Core::DoremiEngineImplementation* engine = nullptr;
}

const DoremiEngine::Core::SharedContext& StartEngine(const size_t& p_flags)
{
    if(engine == nullptr)
    {
        engine = new DoremiEngine::Core::DoremiEngineImplementation();
        engine->Start(p_flags);
    }
    return engine->GetSharedContext();
}

void StopEngine()
{
    engine->Stop();
    delete engine;
    engine = nullptr;
}<commit_msg>Added TODOXX on important functionality<commit_after>#include <Internal/DoremiEngineImplementation.hpp>
#include <Subsystem/EngineModuleEnum.hpp>

#include <DoremiEngine/Audio/Include/AudioModule.hpp>
#include <DoremiEngine/Physics/Include/PhysicsModule.hpp>
#include <DoremiEngine/Graphic/Include/GraphicModule.hpp>
#include <DoremiEngine/Network/Include/NetworkModule.hpp>
#include <DoremiEngine/Input/Include/InputModule.hpp>
#include <DoremiEngine/AI/Include/AIModule.hpp>
#include <Utility/DynamicLoader/Include/DynamicLoader.hpp>

#include <Internal/SharedContextImplementation.hpp>
#include <Windows.h>

// Logging
#include <Utility/DebugLog/Include/ConsoleManager.hpp>

namespace DoremiEngine
{
    namespace Core
    {
        DoremiEngineImplementation::DoremiEngineImplementation()
            : m_audioLibrary(nullptr),
              m_graphicLibrary(nullptr),
              m_networkLibrary(nullptr),
              m_physicsLibrary(nullptr),
              m_inputLibrary(nullptr),
              m_audioModule(nullptr),
              m_graphicModule(nullptr),
              m_networkModule(nullptr),
              m_physicsModule(nullptr),
              m_inputModule(nullptr),
              m_aiModule(nullptr),
              m_logger(nullptr)
        {
            Utility::DebugLog::ConsoleManager::Startup();
            m_logger = &Utility::DebugLog::ConsoleManager::GetInstance().CreateNewConsole("engine", false);
        }

        DoremiEngineImplementation::~DoremiEngineImplementation()
        {
            if(m_audioModule != nullptr)
            {
                delete m_audioModule;
            }

            if(m_graphicModule != nullptr)
            {
                delete m_graphicModule;
            }

            if(m_networkModule != nullptr)
            {
                delete m_networkModule;
            }

            if(m_physicsModule != nullptr)
            {
                delete m_physicsModule;
            }

            if(m_audioLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_audioLibrary);
            }
            if(m_graphicLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_graphicLibrary);
            }
            if(m_networkLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_networkLibrary);
            }
            if(m_physicsLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_physicsLibrary);
            }
            if(m_aiLibrary != nullptr)
            {
                DynamicLoader::FreeSharedLibrary(m_aiLibrary);
            }
        }

        SharedContext& DoremiEngineImplementation::Start(const size_t& p_flags)
        {
            m_sharedContext = new SharedContextImplementation();
            m_sharedContext->SetCoreModule(this);
            BuildWorkingDirectory(*m_sharedContext);

            if((p_flags & EngineModuleEnum::AUDIO) == EngineModuleEnum::AUDIO)
            {
                LoadAudioModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::GRAPHIC) == EngineModuleEnum::GRAPHIC)
            {
                LoadGraphicModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::NETWORK) == EngineModuleEnum::NETWORK)
            {
                LoadNetworkModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::PHYSICS) == EngineModuleEnum::PHYSICS)
            {
                LoadPhysicsModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::INPUT) == EngineModuleEnum::INPUT)
            {
                LoadInputModule(*m_sharedContext);
            }

            if((p_flags & EngineModuleEnum::AI) == EngineModuleEnum::AI)
            {
                LoadAIModule(*m_sharedContext);
            }
            return *m_sharedContext;
        }

        void DoremiEngineImplementation::Stop()
        {
            if(m_audioModule != nullptr)
            {
                m_audioModule->Shutdown();
            }

            if(m_graphicModule != nullptr)
            {
                m_graphicModule->Shutdown();
            }

            if(m_networkModule != nullptr)
            {
                m_networkModule->Shutdown();
            }

            if(m_physicsModule != nullptr)
            {
                m_physicsModule->Shutdown();
            }

            if(m_aiModule != nullptr)
            {
                m_aiModule->Shutdown();
            }
        }

        void DoremiEngineImplementation::BuildWorkingDirectory(SharedContextImplementation& o_sharedContext)
        {
            char path[254];
            GetModuleFileNameA(NULL, path, 254);
            std::string* directoryPath = new std::string(path);
            // TODOXX This only works because Client.exe and Server.exe is 10 characters long.
            o_sharedContext.SetWorkingDirectory(directoryPath->substr(0, directoryPath->length() - 10));
        }

        void DoremiEngineImplementation::LoadAudioModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Audio.dll");
            m_audioLibrary = DynamicLoader::LoadSharedLibrary("Audio.dll");

            if(m_audioLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Audio.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Audio.dll");

                CREATE_AUDIO_MODULE functionCreateAudioModule = (CREATE_AUDIO_MODULE)DynamicLoader::LoadProcess(m_audioLibrary, "CreateAudioModule");
                if(functionCreateAudioModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Audio.dll - Success");

                    m_audioModule = static_cast<Audio::AudioModule*>(functionCreateAudioModule(o_sharedContext));
                    m_audioModule->Startup();
                    o_sharedContext.SetAudioModule(m_audioModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Audio.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Audio.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadGraphicModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Graphic.dll");
            m_graphicLibrary = DynamicLoader::LoadSharedLibrary("Graphic.dll");

            if(m_graphicLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Graphic.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Graphic.dll");
                CREATE_GRAPHIC_MODULE functionCreateGraphicModule =
                    (CREATE_GRAPHIC_MODULE)DynamicLoader::LoadProcess(m_graphicLibrary, "CreateGraphicModule");
                if(functionCreateGraphicModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Graphic.dll - Success");
                    m_graphicModule = static_cast<Graphic::GraphicModule*>(functionCreateGraphicModule(o_sharedContext));
                    m_graphicModule->Startup();
                    o_sharedContext.SetGraphicModule(m_graphicModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Graphic.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Graphic.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadNetworkModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Network.dll");
            m_networkLibrary = DynamicLoader::LoadSharedLibrary("Network.dll");

            if(m_networkLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Network.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Network.dll");
                CREATE_NETWORK_MODULE functionCreateNetworkModule =
                    (CREATE_NETWORK_MODULE)DynamicLoader::LoadProcess(m_networkLibrary, "CreateNetworkModule");
                if(functionCreateNetworkModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Network.dll - Success");
                    m_networkModule = static_cast<Network::NetworkModule*>(functionCreateNetworkModule(o_sharedContext));
                    m_networkModule->Startup();
                    o_sharedContext.SetNetworkModule(m_networkModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Network.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Network.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadPhysicsModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Physics.dll");
            m_physicsLibrary = DynamicLoader::LoadSharedLibrary("Physics.dll");

            if(m_physicsLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Physics.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Physics.dll");
                CREATE_PHYSICS_MODULE functionCreatePhysicsModule =
                    (CREATE_PHYSICS_MODULE)DynamicLoader::LoadProcess(m_physicsLibrary, "CreatePhysicsModule");
                if(functionCreatePhysicsModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Physics.dll - Success");
                    m_physicsModule = static_cast<Physics::PhysicsModule*>(functionCreatePhysicsModule(o_sharedContext));
                    m_physicsModule->Startup();
                    o_sharedContext.SetPhysicsModule(m_physicsModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Physics.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Physics.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadInputModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Input.dll");
            m_inputLibrary = DynamicLoader::LoadSharedLibrary("Input.dll");

            if(m_inputLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Input.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Input.dll");
                CREATE_INPUT_MODULE functionCreateInputModule = (CREATE_INPUT_MODULE)DynamicLoader::LoadProcess(m_inputLibrary, "CreateInputModule");
                if(functionCreateInputModule != nullptr)
                {
                    //              m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Input.dll - Success");
                    m_inputModule = static_cast<Input::InputModule*>(functionCreateInputModule(o_sharedContext));
                    m_inputModule->Startup();
                    o_sharedContext.SetInputModule(m_inputModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from Input.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading Input.dll - Failed");
            }
        }

        void DoremiEngineImplementation::LoadAIModule(SharedContextImplementation& o_sharedContext)
        {
            using namespace Utility::DebugLog;
            m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading AI.dll");
            m_aiLibrary = DynamicLoader::LoadSharedLibrary("AI.dll");

            if(m_aiLibrary != nullptr)
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading AI.dll - Success");
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from AI.dll");
                CREATE_AI_MODULE functionCreateAIModule = (CREATE_AI_MODULE)DynamicLoader::LoadProcess(m_aiLibrary, "CreateAIModule");
                if(functionCreateAIModule != nullptr)
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from AI.dll - Success");

                    m_aiModule = static_cast<AI::AIModule*>(functionCreateAIModule(o_sharedContext));
                    m_aiModule->Startup();
                    o_sharedContext.SetAIModule(m_aiModule);
                }
                else
                {
                    m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading process from AI.dll - Failed");
                }
            }
            else
            {
                m_logger->LogText(LogTag::ENGINE_CORE, LogLevel::INFO, "Loading AI.dll - Failed");
            }
        }
    }
}

namespace
{
    DoremiEngine::Core::DoremiEngineImplementation* engine = nullptr;
}

const DoremiEngine::Core::SharedContext& StartEngine(const size_t& p_flags)
{
    if(engine == nullptr)
    {
        engine = new DoremiEngine::Core::DoremiEngineImplementation();
        engine->Start(p_flags);
    }
    return engine->GetSharedContext();
}

void StopEngine()
{
    engine->Stop();
    delete engine;
    engine = nullptr;
}<|endoftext|>


<commit_before>#include "JME_Time.h"
#include "boost/date_time/posix_time/posix_time.hpp"

namespace JMEngine
{
	namespace game
	{

		bool JME_Time::isTimeToday(time_t t)
		{
			auto ct = boost::posix_time::from_time_t(t);
			auto nt = boost::posix_time::second_clock::local_time();

			return ct.date() == nt.date();
		}

		int JME_Time::todayYearday()
		{
			auto nt = boost::posix_time::second_clock::local_time();
			return nt.date().day_of_year();
		}

		tm JME_Time::localTime()
		{
			return boost::posix_time::to_tm(boost::posix_time::second_clock::local_time());
		}

		tm JME_Time::localTime(time_t t)
		{
			return boost::posix_time::to_tm(boost::posix_time::from_time_t(t));
		}

	}
}<commit_msg>time_t 转换 tm<commit_after>#include "JME_Time.h"
#include "boost/date_time/posix_time/posix_time.hpp"

namespace JMEngine
{
	namespace game
	{

		bool JME_Time::isTimeToday(time_t t)
		{
			auto ct = boost::posix_time::from_time_t(t);
			auto nt = boost::posix_time::second_clock::local_time();

			return ct.date() == nt.date();
		}

		int JME_Time::todayYearday()
		{
			auto nt = boost::posix_time::second_clock::local_time();
			return nt.date().day_of_year();
		}

		tm JME_Time::localTime()
		{
			return boost::posix_time::to_tm(boost::posix_time::second_clock::local_time());
		}

		tm JME_Time::localTime(time_t t)
		{
			tm * timeinfo = localtime(&t);
			return *timeinfo;
		}

	}
}<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <climits>
#include <ctime>

#define minVal adj[i][j].value < min &&  adj[i][j].value != -1
#define setMin min = adj[i][j].value; k = i; l = j;

using namespace std;

//const static int n = 40;
const static int n = 7;

struct data
{
  bool marked, connected; int value;
  data(){marked = connected = 0; value = -1;};
};

data adj[n][n];

void print_adj()
{
  for(int i = 0; i < n; ++i)
  {
    for(int j = 0; j < n; ++j)
    {
      cout << adj[i][j].value << "|";
      if(adj[i][j].connected) cout << "1|"; else cout << "0|";
      if(adj[i][j].marked) cout << "1"; else cout << "0";
      if(j + 1 < n) cout << "  " ; else cout << "\n";
    }
  }
}

void initialize(int & initial)
{
  char temp;
  ifstream in;
  in.open("n2.txt");
  for(int i = 0; i < n; i++)
  {
    for(int j = 0; j < n; j++)
    {
      temp = in.peek();
      if(temp == '-')in >> temp;
      else
      {
        in >> adj[i][j].value;
        initial += adj[i][j].value;
      }
      j == n - 1 ? in.ignore(1, '\n') : in >> temp;
    }
  }
  in.close();
  print_adj();
}

bool connected()
{
  for(int i = 0; i < n; i++)
    if(!adj[0][i].connected) return false;
  return true;
}

void markConnected(const int & jj, const int & ll)
{
  for(int i = 0; i < n; i++)
  {
    if(i == jj)
      for(int j = 0; j < n; j++)
        adj[i][j].marked = true;
    adj[i][ll].connected = true;
  }
}

void optimize(int & pruned, int & k, int & l)
{
  int i, j, min;
  do{
    min = INT_MAX;
    for(i = 0; i < n; i++)
    {
      if(adj[i][0].marked)
      {
        for(j = 1; j < n; j++)
          if(!adj[i][j].connected && minVal){setMin}
      }
    }
    pruned += min;
    adj[k][l].value = -1;
    markConnected(l, l);
  }while(!connected());
}

int main()
{
  clock_t start, end;
  int initial = 0, pruned = 0, i = 0, j = 0, min, k, l;
  start = clock();
  initialize(initial);
  while(adj[i++][j].value == -1)
  setMin
  for(i; i < n; i++)
    if(minVal){setMin}
  adj[k][l].value = -1;
  markConnected(0, l);
  optimize(pruned, k, l);
  end = clock();
  cout << initial / 2 - pruned << endl;
  cout << "Computation Time: " << (end - start) / (double) CLOCKS_PER_SEC << "ms\n";
  return 0;
}
<commit_msg>Update a3.cpp<commit_after>#include <iostream>
#include <fstream>
#include <climits>
#include <ctime>

#define minVal adj[i][j].value < min &&  adj[i][j].value != -1
#define setMin min = adj[i][j].value; k = i; l = j;

const char* nn = "ABCDEFG"; // node names

using namespace std;

//const static int n = 40;
const static int n = 7;

struct data
{
  bool marked, connected; int value;
  data(){marked = connected = 0; value = -1;};
};

data adj[n][n];

void print_adj()
{
  for(int i = 0; i < n; ++i)
  {
    for(int j = 0; j < n; ++j)
    {
      cout << adj[i][j].value << "|";
      if(adj[i][j].connected) cout << "1|"; else cout << "0|";
      if(adj[i][j].marked) cout << "1"; else cout << "0";
      if(j + 1 < n) cout << "  " ; else cout << "\n";
    }
  }
}

void initialize(int & initial)
{
  char temp;
  ifstream in;
  in.open("n2.txt");
  for(int i = 0; i < n; i++)
  {
    for(int j = 0; j < n; j++)
    {
      temp = in.peek();
      if(temp == '-')in >> temp;
      else
      {
        in >> adj[i][j].value;
        initial += adj[i][j].value;
      }
      j == n - 1 ? in.ignore(1, '\n') : in >> temp;
    }
  }
  in.close();
  print_adj();
}

bool connected()
{
  for(int i = 0; i < n; i++)
    if(!adj[0][i].connected) return false;
  return true;
}

void markConnected(const int & jj, const int & ll)
{
  for(int i = 0; i < n; i++)
  {
    if(i == jj)
      for(int j = 0; j < n; j++)
        adj[i][j].marked = true;
    adj[i][ll].connected = true;
  }
}

void optimize(int & pruned, int & k, int & l)
{
  int i, j, min;
  do{
    min = INT_MAX;
    for(i = 0; i < n; i++)
    {
      if(adj[i][0].marked)
      {
        for(j = 1; j < n; j++)
          if(!adj[i][j].connected && minVal){setMin}
      }
    }
    pruned += min;
    cout << "Add Edge: " << nn[k] << "--" << nn[l] << " weight: " << min
         << " total weight: " << pruned << endl;
    adj[k][l].value = -1;
    markConnected(l, l);
  }while(!connected());
}

int main()
{
  clock_t start, end;
  int initial = 0, pruned = 0, i = 0, j = 0, min, k, l;
  start = clock();
  initialize(initial);
  while(adj[i++][j].value == -1)
  setMin
  for(i; i < n; i++)
    if(minVal){setMin}
  adj[k][l].value = -1;
  markConnected(0, l);
  optimize(pruned, k, l);
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include <random>

#include "../../Foundation/Characters/StringBuilder.h"
#include "../../Foundation/Characters/ToString.h"
#include "../../Foundation/Containers/Collection.h"
#include "../../Foundation/Debug/Trace.h"
#include "../../Foundation/Execution/Sleep.h"
#include "../../Foundation/IO/Network/Listener.h"
#include "../../Foundation/IO/Network/Socket.h"

#include "Traceroute.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::Debug;
using namespace Stroika::Foundation::Execution;
using namespace Stroika::Foundation::Memory;
using namespace Stroika::Foundation::IO;
using namespace Stroika::Foundation::IO::Network;
using namespace Stroika::Foundation::IO::Network::InternetProtocol;
using namespace Stroika::Foundation::IO::Network::InternetProtocol::ICMP;
using namespace Stroika::Foundation::IO::Network::InternetProtocol::IP;
using namespace Stroika::Foundation::Traversal;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::NetworkMonitor;
using namespace Stroika::Frameworks::NetworkMonitor::Traceroute;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

namespace {
    const Options::SampleInfo kDefaultSampleInfo_{Duration (0), 1};
}

/*
 ********************************************************************************
 ************ NetworkMonitor::Traceroute::Options::SampleInfo *******************
 ********************************************************************************
 */
Characters::String Traceroute::Options::SampleInfo::ToString () const
{
    StringBuilder sb;
    sb += L"{";
    sb += L"Interval: " + Characters::ToString (fInterval) + L", ";
    sb += L"Count: " + Characters::Format (L"%d", fSampleCount) + L", ";
    sb += L"}";
    return sb.str ();
}

/*
 ********************************************************************************
 ***************** NetworkMonitor::Traceroute::Options **************************
 ********************************************************************************
 */
constexpr Traversal::Range<size_t> Traceroute::Options::kAllowedICMPPayloadSizeRange;

const Duration Traceroute::Options::kDefaultTimeout{1.0};

String Traceroute::Options::ToString () const
{
    StringBuilder sb;
    sb += L"{";
    if (fMaxHops) {
        sb += L"Max-Hops: " + Characters::Format (L"%d", *fMaxHops) + L", ";
    }
    if (fTimeout) {
        sb += L"Timeout: " + Characters::ToString (*fTimeout) + L", ";
    }
    if (fPacketPayloadSize) {
        sb += L"Packet-Payload-Size: " + Characters::Format (L"%d", *fPacketPayloadSize) + L", ";
    }
    if (fSampleInfo) {
        sb += L"Sample: " + Characters::ToString (*fSampleInfo) + L", ";
    }
    sb += L"}";
    return sb.str ();
}

/*
 ********************************************************************************
 ******************** NetworkMonitor::Traceroute::Hop ***************************
 ********************************************************************************
 */
String Hop::ToString () const
{
    StringBuilder sb;
    sb += L"{";
    sb += L"Time: " + Characters::ToString (fTime) + L", ";
    sb += L"Address: " + Characters::ToString (fAddress) + L", ";
    sb += L"}";
    return sb.str ();
}

/*
 ********************************************************************************
 *********************** NetworkMonitor::Traceroute *****************************
 ********************************************************************************
 */
Sequence<Hop> NetworkMonitor::Traceroute::Run (const InternetAddress& addr, const Options& options)
{
    Sequence<Hop> result;

    Debug::TraceContextBumper ctx{Stroika_Foundation_Debug_OptionalizeTraceArgs (L"Frameworks::NetworkMonitor::Traceroute::Run", L"addr=%s, options=%s", Characters::ToString (addr).c_str (), Characters::ToString (options).c_str ())};
    size_t                    icmpPacketSize = Options::kAllowedICMPPayloadSizeRange.Pin (options.fPacketPayloadSize.Value (Options::kDefaultPayloadSize)) + sizeof (ICMP::PacketHeader);
    unsigned int              ttl            = options.fMaxHops.Value (Options::kDefaultMaxHops);

    Time::DurationSecondsType pingTimeout = options.fTimeout.Value (Options::kDefaultTimeout).As<Time::DurationSecondsType> ();

    Options::SampleInfo sampleInfo = options.fSampleInfo.Value (kDefaultSampleInfo_);
    Require (sampleInfo.fSampleCount >= 1);

    static std::mt19937    rng{std::random_device () ()};
    SmallStackBuffer<Byte> sendPacket (icmpPacketSize);
    // use random data as a payload
    static std::uniform_int_distribution<std::mt19937::result_type> distByte (0, numeric_limits<Byte>::max ());
    for (Byte* p = (Byte*)sendPacket.begin () + sizeof (ICMP::PacketHeader); p < sendPacket.end (); ++p) {
        static std::uniform_int_distribution<std::mt19937::result_type> distribution (0, numeric_limits<Byte>::max ());
        *p = distribution (rng);
    }

    /*
    *  General theorey of operation:
    *      >   Use ICMP (low level IP raw packets) to send a packet with a time-to-live (max # of hops) to the target address.
    *      >   That target address - if ICMP enabled properly - will send an ECHO reply back.
    *      >   we can look at how long this took, and report back the difference.
    *
    *  Also, allow for sampling differntly sized packets, etc.
    */

    Socket s{Socket::ProtocolFamily::INET, Socket::SocketKind::RAW, IPPROTO_ICMP};
    s.setsockopt (IPPROTO_IP, IP_TTL, ttl); // max # of hops

    Collection<DurationSecondsType> sampleTimes;
    Collection<unsigned int>        sampleHopCounts;
    unsigned int                    samplesTaken{};
    while (samplesTaken < sampleInfo.fSampleCount) {
        if (sampleInfo.fSampleCount != 0) {
            Execution::Sleep (sampleInfo.fInterval);
        }
        try {
            ICMP::PacketHeader pingRequest = [&]() {
                static std::uniform_int_distribution<std::mt19937::result_type> distribution (0, numeric_limits<uint16_t>::max ());
                static uint16_t                                                 seq_no = distribution (rng);
                ICMP::PacketHeader                                              tmp{};
                tmp.type      = ICMP_ECHO_REQUEST;
                tmp.id        = distribution (rng);
                tmp.seq       = seq_no++;
                tmp.timestamp = static_cast<uint32_t> (Time::GetTickCount () * 1000);
                return tmp;
            }();
            memcpy (sendPacket.begin (), &pingRequest, sizeof (pingRequest));
            reinterpret_cast<ICMP::PacketHeader*> (sendPacket.begin ())->checksum = ip_checksum (sendPacket.begin (), sendPacket.begin () + icmpPacketSize);
            s.SendTo (sendPacket.begin (), sendPacket.end (), SocketAddress{addr, 0});

            // Find first packet responding
            while (true) {
                using IO::Network::InternetProtocol::IP::PacketHeader;
                SocketAddress fromAddress;

                SmallStackBuffer<Byte> recv_buf (icmpPacketSize + sizeof (PacketHeader));
                size_t                 n = s.ReceiveFrom (begin (recv_buf), end (recv_buf), 0, &fromAddress, pingTimeout);
#if USE_NOISY_TRACE_IN_THIS_MODULE_
                DbgTrace (L"got back packet from %s", Characters::ToString (fromAddress).c_str ());
#endif
                const PacketHeader* reply = reinterpret_cast<const PacketHeader*> (recv_buf.begin ());

                {
                    // Skip ahead to the ICMP header within the IP packet
                    unsigned short            header_len = reply->ihl * 4;
                    const ICMP::PacketHeader* icmphdr    = (const ICMP::PacketHeader*)((const Byte*)reply + header_len);

                    // Make sure the reply is sane
                    if (n < header_len + ICMP_MIN) {
                        Execution::Throw (Execution::StringException (L"too few bytes from " + Characters::ToString (fromAddress))); // draft @todo fix
                    }
                    else if (icmphdr->id != pingRequest.id) {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
                        DbgTrace (L"icmphdr->id != pingRequest.id so ignoring this reply");
#endif
                        // Must be a reply for another pinger running locally, so just
                        // ignore it.
                        continue;
                    }
                    switch (icmphdr->type) {
                        case ICMP_ECHO_REPLY: {
                            // Different operating systems use different starting values for TTL. TTL here is the original number used,
                            // less the number of hops. So we are left with making an educated guess. Need refrence and would be nice to find better
                            // way, but this seems to work pretty often.
                            unsigned int nHops{};
                            if (reply->ttl > 128) {
                                nHops = 256 - reply->ttl;
                            }
                            else if (reply->ttl > 64) {
                                nHops = 128 - reply->ttl;
                            }
                            else {
                                nHops = 65 - reply->ttl;
                            }
#if USE_NOISY_TRACE_IN_THIS_MODULE_
                            DbgTrace (L"reply->ttl = %d, nHops = %d", reply->ttl, nHops);
#endif

                            sampleTimes += (Time::GetTickCount () * 1000 - icmphdr->timestamp) / 1000;
                            sampleHopCounts += nHops;
                            samplesTaken++;
                            goto nextSample;
                        }
                        case ICMP_TTL_EXPIRE: {
                            Execution::Throw (ICMP::TTLExpiredException ());
                        }
                        case ICMP_DEST_UNREACH: {
                            Execution::Throw (Network::InternetProtocol::ICMP::DestinationUnreachableException (icmphdr->code));
                        };
                        default: {
                            Execution::Throw (Network::InternetProtocol::ICMP::UnknownICMPPacket (icmphdr->type));
                        }
                    }
                }
            }
        }
        catch (...) {
            bool suppressThrows = sampleInfo.fSampleCount > 1;
            if (suppressThrows) {
                DbgTrace (L"ignore exception %s", Characters::ToString (current_exception ()).c_str ());
            }
            else {
                Execution::ReThrow ();
            }
            samplesTaken++;
        }
    nextSample:;
    }

    Assert (sampleTimes.empty () == sampleHopCounts.empty ());
#if 0
    if (sampleTimes.empty ()) {
        return Results{ {},{}, samplesTaken };
    }
    else {
        return Results{ Duration (*sampleTimes.Median ()), *sampleHopCounts.Median (), static_cast<unsigned int> (samplesTaken - sampleTimes.size ()) };
    }
#endif
    return result;
}
<commit_msg>traceroute code - just vectors through ping code<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2017.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include <random>

#include "../../Foundation/Characters/StringBuilder.h"
#include "../../Foundation/Characters/ToString.h"
#include "../../Foundation/Containers/Collection.h"
#include "../../Foundation/Debug/Trace.h"
#include "../../Foundation/Execution/Sleep.h"
#include "../../Foundation/IO/Network/Listener.h"
#include "../../Foundation/IO/Network/Socket.h"

#include "Ping.h"

#include "Traceroute.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::Debug;
using namespace Stroika::Foundation::Execution;
using namespace Stroika::Foundation::Memory;
using namespace Stroika::Foundation::IO;
using namespace Stroika::Foundation::IO::Network;
using namespace Stroika::Foundation::IO::Network::InternetProtocol;
using namespace Stroika::Foundation::IO::Network::InternetProtocol::ICMP;
using namespace Stroika::Foundation::IO::Network::InternetProtocol::IP;
using namespace Stroika::Foundation::Traversal;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::NetworkMonitor;
using namespace Stroika::Frameworks::NetworkMonitor::Traceroute;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define   USE_NOISY_TRACE_IN_THIS_MODULE_       1

namespace {
    const Options::SampleInfo kDefaultSampleInfo_{Duration (0), 1};
}

/*
 ********************************************************************************
 ************ NetworkMonitor::Traceroute::Options::SampleInfo *******************
 ********************************************************************************
 */
Characters::String Traceroute::Options::SampleInfo::ToString () const
{
    StringBuilder sb;
    sb += L"{";
    sb += L"Interval: " + Characters::ToString (fInterval) + L", ";
    sb += L"Count: " + Characters::Format (L"%d", fSampleCount) + L", ";
    sb += L"}";
    return sb.str ();
}

/*
 ********************************************************************************
 ***************** NetworkMonitor::Traceroute::Options **************************
 ********************************************************************************
 */
constexpr Traversal::Range<size_t> Traceroute::Options::kAllowedICMPPayloadSizeRange;

const Duration Traceroute::Options::kDefaultTimeout{1.0};

String Traceroute::Options::ToString () const
{
    StringBuilder sb;
    sb += L"{";
    if (fMaxHops) {
        sb += L"Max-Hops: " + Characters::Format (L"%d", *fMaxHops) + L", ";
    }
    if (fTimeout) {
        sb += L"Timeout: " + Characters::ToString (*fTimeout) + L", ";
    }
    if (fPacketPayloadSize) {
        sb += L"Packet-Payload-Size: " + Characters::Format (L"%d", *fPacketPayloadSize) + L", ";
    }
    if (fSampleInfo) {
        sb += L"Sample: " + Characters::ToString (*fSampleInfo) + L", ";
    }
    sb += L"}";
    return sb.str ();
}

/*
 ********************************************************************************
 ******************** NetworkMonitor::Traceroute::Hop ***************************
 ********************************************************************************
 */
String Hop::ToString () const
{
    StringBuilder sb;
    sb += L"{";
    sb += L"Time: " + Characters::ToString (fTime) + L", ";
    sb += L"Address: " + Characters::ToString (fAddress) + L", ";
    sb += L"}";
    return sb.str ();
}

/*
 ********************************************************************************
 *********************** NetworkMonitor::Traceroute *****************************
 ********************************************************************************
 */
Sequence<Hop> NetworkMonitor::Traceroute::Run (const InternetAddress& addr, const Options& options)
{
    Debug::TraceContextBumper ctx{Stroika_Foundation_Debug_OptionalizeTraceArgs (L"Frameworks::NetworkMonitor::Traceroute::Run", L"addr=%s, options=%s", Characters::ToString (addr).c_str (), Characters::ToString (options).c_str ())};
    Sequence<Hop>             results;
    unsigned int              maxTTL = options.fMaxHops.Value (Options::kDefaultMaxHops);
    for (unsigned int ttl = 1; ttl <= maxTTL; ++ttl) {
        Ping::Options pingOptions{};
        pingOptions.fMaxHops           = ttl;
        pingOptions.fPacketPayloadSize = options.fPacketPayloadSize;
        if (options.fSampleInfo) {
            pingOptions.fSampleInfo = Ping::Options::SampleInfo{options.fSampleInfo->fInterval, options.fSampleInfo->fSampleCount};
        }
        try {
            Ping::Results r = Ping::Run (addr, pingOptions);
            results += Hop{
                r.fMedianPingTime.Value (),
            };
        }
        catch (...) {
            results += Hop{
                Duration (10000),
            };
            ///
        }
    }
    return results;
}
<|endoftext|>


<commit_before>/*

openfx-arena - https://github.com/olear/openfx-arena

Copyright (c) 2015, Ole-André Rodlie <olear@fxarena.net>
Copyright (c) 2015, FxArena DA <mail@fxarena.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Neither the name of FxArena DA nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "Wave.h"
#include "ofxsMacros.h"
#include <Magick++.h>
#include <iostream>
#include <stdint.h>
#include <cmath>

#define kPluginName "WaveOFX"
#define kPluginGrouping "Transform"
#define kPluginIdentifier "net.fxarena.openfx.Wave"
#define kPluginVersionMajor 1
#define kPluginVersionMinor 0

#define kParamWaveAmp "amp"
#define kParamWaveAmpLabel "Amplitude"
#define kParamWaveAmpHint "Adjust wave amplitude"
#define kParamWaveAmpDefault 25

#define kParamWaveLength "length"
#define kParamWaveLengthLabel "Length"
#define kParamWaveLengthHint "Adjust wave length"
#define kParamWaveLengthDefault 150

#define kSupportsTiles 0
#define kSupportsMultiResolution 1
#define kSupportsRenderScale 1
#define kRenderThreadSafety eRenderFullySafe
#define kHostFrameThreading false

using namespace OFX;

class WavePlugin : public OFX::ImageEffect
{
public:
    WavePlugin(OfxImageEffectHandle handle);
    virtual ~WavePlugin();
    virtual void render(const OFX::RenderArguments &args) OVERRIDE FINAL;
    virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod) OVERRIDE FINAL;
private:
    OFX::Clip *dstClip_;
    OFX::Clip *srcClip_;
    OFX::DoubleParam *waveAmp_;
    OFX::DoubleParam *waveLength_;
};

WavePlugin::WavePlugin(OfxImageEffectHandle handle)
: OFX::ImageEffect(handle)
, dstClip_(0)
, srcClip_(0)
{
    Magick::InitializeMagick(NULL);
    dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
    assert(dstClip_ && dstClip_->getPixelComponents() == OFX::ePixelComponentRGBA);
    srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert(srcClip_ && srcClip_->getPixelComponents() == OFX::ePixelComponentRGBA);

    waveAmp_ = fetchDoubleParam(kParamWaveAmp);
    waveLength_ = fetchDoubleParam(kParamWaveLength);

    assert(waveAmp_ && waveLength_);
}

WavePlugin::~WavePlugin()
{
}

void WavePlugin::render(const OFX::RenderArguments &args)
{
    // render scale
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get src clip
    if (!srcClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(srcClip_);
    std::auto_ptr<const OFX::Image> srcImg(srcClip_->fetchImage(args.time));
    OfxRectI srcRod,srcBounds;
    if (srcImg.get()) {
        srcRod = srcImg->getRegionOfDefinition();
        srcBounds = srcImg->getBounds();
        if (srcImg->getRenderScale().x != args.renderScale.x ||
            srcImg->getRenderScale().y != args.renderScale.y ||
            srcImg->getField() != args.fieldToRender) {
            setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
            OFX::throwSuiteStatusException(kOfxStatFailed);
            return;
        }
    }

    // get dest clip
    if (!dstClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(dstClip_);
    std::auto_ptr<OFX::Image> dstImg(dstClip_->fetchImage(args.time));
    if (!dstImg.get()) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    if (dstImg->getRenderScale().x != args.renderScale.x ||
        dstImg->getRenderScale().y != args.renderScale.y ||
        dstImg->getField() != args.fieldToRender) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get bit depth
    OFX::BitDepthEnum dstBitDepth = dstImg->getPixelDepth();
    if (dstBitDepth != OFX::eBitDepthFloat || (srcImg.get() && (dstBitDepth != srcImg->getPixelDepth()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // get pixel component
    OFX::PixelComponentEnum dstComponents  = dstImg->getPixelComponents();
    if (dstComponents != OFX::ePixelComponentRGBA || (srcImg.get() && (dstComponents != srcImg->getPixelComponents()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // are we in the image bounds?
    OfxRectI dstBounds = dstImg->getBounds();
    if(args.renderWindow.x1 < dstBounds.x1 || args.renderWindow.x1 >= dstBounds.x2 || args.renderWindow.y1 < dstBounds.y1 || args.renderWindow.y1 >= dstBounds.y2 ||
       args.renderWindow.x2 <= dstBounds.x1 || args.renderWindow.x2 > dstBounds.x2 || args.renderWindow.y2 <= dstBounds.y1 || args.renderWindow.y2 > dstBounds.y2) {
        OFX::throwSuiteStatusException(kOfxStatErrValue);
        return;
    }

    // get params
    double waveAmp, waveLength;
    waveAmp_->getValueAtTime(args.time, waveAmp);
    waveLength_->getValueAtTime(args.time, waveLength);

    // setup
    int width = srcRod.x2-srcRod.x1;
    int height = srcRod.y2-srcRod.y1;

    // read image
    Magick::Image image(Magick::Geometry(width,height),Magick::Color("rgba(0,0,0,0)"));
    if (srcClip_ && srcClip_->isConnected())
        image.read(width,height,"RGBA",Magick::FloatPixel,(float*)srcImg->getPixelData());

    #ifdef DEBUG
    image.debug(true);
    #endif

    // wave
    image.backgroundColor(Magick::Color("rgba(0,0,0,0)"));
    image.wave(std::floor(waveAmp * args.renderScale.x + 0.5),std::floor(waveLength * args.renderScale.x + 0.5));

    // return image
    if (dstClip_ && dstClip_->isConnected() && srcClip_ && srcClip_->isConnected())
        image.write(0,0,width,height,"RGBA",Magick::FloatPixel,(float*)dstImg->getPixelData());
}

bool WavePlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return false;
    }
    if (srcClip_ && srcClip_->isConnected()) {
        rod = srcClip_->getRegionOfDefinition(args.time);
    } else {
        rod.x1 = rod.y1 = kOfxFlagInfiniteMin;
        rod.x2 = rod.y2 = kOfxFlagInfiniteMax;
    }
    return true;
}

mDeclarePluginFactory(WavePluginFactory, {}, {});

/** @brief The basic describe function, passed a plugin descriptor */
void WavePluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // basic labels
    desc.setLabel(kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    std::string magickV = MagickCore::GetMagickVersion(NULL);
    desc.setPluginDescription("Wave filter for Natron.\n\nWritten by Ole-André Rodlie <olear@fxarena.net>\n\nPowered by "+magickV);

    // add the supported contexts
    desc.addSupportedContext(eContextGeneral);
    desc.addSupportedContext(eContextFilter);

    // add supported pixel depths
    desc.addSupportedBitDepth(eBitDepthFloat);

    desc.setSupportsTiles(kSupportsTiles);
    desc.setSupportsMultiResolution(kSupportsMultiResolution);
    desc.setRenderThreadSafety(kRenderThreadSafety);
    desc.setHostFrameThreading(kHostFrameThreading);
}

/** @brief The describe in context function, passed a plugin descriptor and a context */
void WavePluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, ContextEnum /*context*/)
{
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(kSupportsTiles);
    srcClip->setIsMask(false);

    // create the mandated output clip
    ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(ePixelComponentRGBA);
    dstClip->setSupportsTiles(kSupportsTiles);

    // make some pages
    PageParamDescriptor *page = desc.definePageParam(kPluginName);
    {
        DoubleParamDescriptor *param = desc.defineDoubleParam(kParamWaveAmp);
        param->setLabel(kParamWaveAmpLabel);
        param->setHint(kParamWaveAmpHint);
        param->setRange(0, 1000);
        param->setDisplayRange(0, 500);
        param->setDefault(kParamWaveAmpDefault);
        page->addChild(*param);
    }
    {
        DoubleParamDescriptor *param = desc.defineDoubleParam(kParamWaveLength);
        param->setLabel(kParamWaveLengthLabel);
        param->setHint(kParamWaveLengthHint);
        param->setRange(0, 1000);
        param->setDisplayRange(0, 500);
        param->setDefault(kParamWaveLengthDefault);
        page->addChild(*param);
    }
}

/** @brief The create instance function, the plugin must return an object derived from the \ref OFX::ImageEffect class */
ImageEffect* WavePluginFactory::createInstance(OfxImageEffectHandle handle, ContextEnum /*context*/)
{
    return new WavePlugin(handle);
}

void getWavePluginID(OFX::PluginFactoryArray &ids)
{
    static WavePluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}
<commit_msg>Wave: added mask support, issue #144<commit_after>/*

openfx-arena - https://github.com/olear/openfx-arena

Copyright (c) 2015, Ole-André Rodlie <olear@fxarena.net>
Copyright (c) 2015, FxArena DA <mail@fxarena.net>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Neither the name of FxArena DA nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "Wave.h"
#include "ofxsMacros.h"
#include <Magick++.h>
#include <iostream>
#include <stdint.h>
#include <cmath>

#define kPluginName "WaveOFX"
#define kPluginGrouping "Transform"
#define kPluginIdentifier "net.fxarena.openfx.Wave"
#define kPluginVersionMajor 2
#define kPluginVersionMinor 0

#define kParamWaveAmp "amp"
#define kParamWaveAmpLabel "Amplitude"
#define kParamWaveAmpHint "Adjust wave amplitude"
#define kParamWaveAmpDefault 25

#define kParamWaveLength "length"
#define kParamWaveLengthLabel "Length"
#define kParamWaveLengthHint "Adjust wave length"
#define kParamWaveLengthDefault 150

#define kSupportsTiles 0
#define kSupportsMultiResolution 1
#define kSupportsRenderScale 1
#define kRenderThreadSafety eRenderFullySafe
#define kHostFrameThreading false

using namespace OFX;

class WavePlugin : public OFX::ImageEffect
{
public:
    WavePlugin(OfxImageEffectHandle handle);
    virtual ~WavePlugin();
    virtual void render(const OFX::RenderArguments &args) OVERRIDE FINAL;
    virtual bool getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod) OVERRIDE FINAL;
private:
    OFX::Clip *dstClip_;
    OFX::Clip *srcClip_;
    OFX::Clip *maskClip_;
    OFX::DoubleParam *waveAmp_;
    OFX::DoubleParam *waveLength_;
};

WavePlugin::WavePlugin(OfxImageEffectHandle handle)
: OFX::ImageEffect(handle)
, dstClip_(0)
, srcClip_(0)
{
    Magick::InitializeMagick(NULL);
    dstClip_ = fetchClip(kOfxImageEffectOutputClipName);
    assert(dstClip_ && dstClip_->getPixelComponents() == OFX::ePixelComponentRGBA);
    srcClip_ = fetchClip(kOfxImageEffectSimpleSourceClipName);
    assert(srcClip_ && srcClip_->getPixelComponents() == OFX::ePixelComponentRGBA);
    maskClip_ = getContext() == OFX::eContextFilter ? NULL : fetchClip(getContext() == OFX::eContextPaint ? "Brush" : "Mask");
    assert(!maskClip_ || maskClip_->getPixelComponents() == OFX::ePixelComponentAlpha);

    waveAmp_ = fetchDoubleParam(kParamWaveAmp);
    waveLength_ = fetchDoubleParam(kParamWaveLength);

    assert(waveAmp_ && waveLength_);
}

WavePlugin::~WavePlugin()
{
}

void WavePlugin::render(const OFX::RenderArguments &args)
{
    // render scale
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get src clip
    if (!srcClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(srcClip_);
    std::auto_ptr<const OFX::Image> srcImg(srcClip_->fetchImage(args.time));
    OfxRectI srcRod,srcBounds;
    if (srcImg.get()) {
        srcRod = srcImg->getRegionOfDefinition();
        srcBounds = srcImg->getBounds();
        if (srcImg->getRenderScale().x != args.renderScale.x ||
            srcImg->getRenderScale().y != args.renderScale.y ||
            srcImg->getField() != args.fieldToRender) {
            setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
            OFX::throwSuiteStatusException(kOfxStatFailed);
            return;
        }
    }

    // Get mask clip
    std::auto_ptr<const OFX::Image> maskImg((getContext() != OFX::eContextFilter && maskClip_ && maskClip_->isConnected()) ? maskClip_->fetchImage(args.time) : 0);
    OfxRectI maskRod;
    if (getContext() != OFX::eContextFilter && maskClip_ && maskClip_->isConnected())
        maskRod=maskImg->getRegionOfDefinition();

    // get dest clip
    if (!dstClip_) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    assert(dstClip_);
    std::auto_ptr<OFX::Image> dstImg(dstClip_->fetchImage(args.time));
    if (!dstImg.get()) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }
    if (dstImg->getRenderScale().x != args.renderScale.x ||
        dstImg->getRenderScale().y != args.renderScale.y ||
        dstImg->getField() != args.fieldToRender) {
        setPersistentMessage(OFX::Message::eMessageError, "", "OFX Host gave image with wrong scale or field properties");
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return;
    }

    // get bit depth
    OFX::BitDepthEnum dstBitDepth = dstImg->getPixelDepth();
    if (dstBitDepth != OFX::eBitDepthFloat || (srcImg.get() && (dstBitDepth != srcImg->getPixelDepth()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // get pixel component
    OFX::PixelComponentEnum dstComponents  = dstImg->getPixelComponents();
    if (dstComponents != OFX::ePixelComponentRGBA || (srcImg.get() && (dstComponents != srcImg->getPixelComponents()))) {
        OFX::throwSuiteStatusException(kOfxStatErrFormat);
        return;
    }

    // are we in the image bounds?
    OfxRectI dstBounds = dstImg->getBounds();
    if(args.renderWindow.x1 < dstBounds.x1 || args.renderWindow.x1 >= dstBounds.x2 || args.renderWindow.y1 < dstBounds.y1 || args.renderWindow.y1 >= dstBounds.y2 ||
       args.renderWindow.x2 <= dstBounds.x1 || args.renderWindow.x2 > dstBounds.x2 || args.renderWindow.y2 <= dstBounds.y1 || args.renderWindow.y2 > dstBounds.y2) {
        OFX::throwSuiteStatusException(kOfxStatErrValue);
        return;
    }

    // get params
    double waveAmp, waveLength;
    waveAmp_->getValueAtTime(args.time, waveAmp);
    waveLength_->getValueAtTime(args.time, waveLength);

    // setup
    int width = srcRod.x2-srcRod.x1;
    int height = srcRod.y2-srcRod.y1;

    // read image
    Magick::Image image(Magick::Geometry(width,height),Magick::Color("rgba(0,0,0,0)"));
    if (srcClip_ && srcClip_->isConnected())
        image.read(width,height,"RGBA",Magick::FloatPixel,(float*)srcImg->getPixelData());

    #ifdef DEBUG
    image.debug(true);
    #endif

    // apply mask
    if (maskClip_ && maskClip_->isConnected()) {
        int maskWidth = maskRod.x2-maskRod.x1;
        int maskHeight = maskRod.y2-maskRod.y1;
        if (maskWidth>0 && maskHeight>0) {
            Magick::Image mask(maskWidth,maskHeight,"A",Magick::FloatPixel,(float*)maskImg->getPixelData());
            image.composite(mask,0,0,Magick::CopyOpacityCompositeOp);
        }
        Magick::Image container(Magick::Geometry(width,height),Magick::Color("rgba(0,0,0,0)"));
        container.composite(image,0,0,Magick::OverCompositeOp);
        image=container;
    }

    // wave
    image.backgroundColor(Magick::Color("rgba(0,0,0,0)"));
    image.wave(std::floor(waveAmp * args.renderScale.x + 0.5),std::floor(waveLength * args.renderScale.x + 0.5));

    // return image
    if (dstClip_ && dstClip_->isConnected() && srcClip_ && srcClip_->isConnected())
        image.write(0,0,width,height,"RGBA",Magick::FloatPixel,(float*)dstImg->getPixelData());
}

bool WavePlugin::getRegionOfDefinition(const OFX::RegionOfDefinitionArguments &args, OfxRectD &rod)
{
    if (!kSupportsRenderScale && (args.renderScale.x != 1. || args.renderScale.y != 1.)) {
        OFX::throwSuiteStatusException(kOfxStatFailed);
        return false;
    }
    if (srcClip_ && srcClip_->isConnected()) {
        rod = srcClip_->getRegionOfDefinition(args.time);
    } else {
        rod.x1 = rod.y1 = kOfxFlagInfiniteMin;
        rod.x2 = rod.y2 = kOfxFlagInfiniteMax;
    }
    return true;
}

mDeclarePluginFactory(WavePluginFactory, {}, {});

/** @brief The basic describe function, passed a plugin descriptor */
void WavePluginFactory::describe(OFX::ImageEffectDescriptor &desc)
{
    // basic labels
    desc.setLabel(kPluginName);
    desc.setPluginGrouping(kPluginGrouping);
    std::string magickV = MagickCore::GetMagickVersion(NULL);
    desc.setPluginDescription("Wave filter for Natron.\n\nWritten by Ole-André Rodlie <olear@fxarena.net>\n\nPowered by "+magickV);

    // add the supported contexts
    desc.addSupportedContext(eContextGeneral);
    desc.addSupportedContext(eContextFilter);

    // add supported pixel depths
    desc.addSupportedBitDepth(eBitDepthFloat);

    desc.setSupportsTiles(kSupportsTiles);
    desc.setSupportsMultiResolution(kSupportsMultiResolution);
    desc.setRenderThreadSafety(kRenderThreadSafety);
    desc.setHostFrameThreading(kHostFrameThreading);
}

/** @brief The describe in context function, passed a plugin descriptor and a context */
void WavePluginFactory::describeInContext(OFX::ImageEffectDescriptor &desc, ContextEnum /*context*/)
{
    // create the mandated source clip
    ClipDescriptor *srcClip = desc.defineClip(kOfxImageEffectSimpleSourceClipName);
    srcClip->addSupportedComponent(ePixelComponentRGBA);
    srcClip->setTemporalClipAccess(false);
    srcClip->setSupportsTiles(kSupportsTiles);
    srcClip->setIsMask(false);

    // create optional mask clip
    ClipDescriptor *maskClip = desc.defineClip("Mask");
    maskClip->addSupportedComponent(OFX::ePixelComponentAlpha);
    maskClip->setTemporalClipAccess(false);
    maskClip->setOptional(true);
    maskClip->setSupportsTiles(kSupportsTiles);
    maskClip->setIsMask(true);

    // create the mandated output clip
    ClipDescriptor *dstClip = desc.defineClip(kOfxImageEffectOutputClipName);
    dstClip->addSupportedComponent(ePixelComponentRGBA);
    dstClip->setSupportsTiles(kSupportsTiles);

    // make some pages
    PageParamDescriptor *page = desc.definePageParam(kPluginName);
    {
        DoubleParamDescriptor *param = desc.defineDoubleParam(kParamWaveAmp);
        param->setLabel(kParamWaveAmpLabel);
        param->setHint(kParamWaveAmpHint);
        param->setRange(0, 1000);
        param->setDisplayRange(0, 500);
        param->setDefault(kParamWaveAmpDefault);
        page->addChild(*param);
    }
    {
        DoubleParamDescriptor *param = desc.defineDoubleParam(kParamWaveLength);
        param->setLabel(kParamWaveLengthLabel);
        param->setHint(kParamWaveLengthHint);
        param->setRange(0, 1000);
        param->setDisplayRange(0, 500);
        param->setDefault(kParamWaveLengthDefault);
        page->addChild(*param);
    }
}

/** @brief The create instance function, the plugin must return an object derived from the \ref OFX::ImageEffect class */
ImageEffect* WavePluginFactory::createInstance(OfxImageEffectHandle handle, ContextEnum /*context*/)
{
    return new WavePlugin(handle);
}

void getWavePluginID(OFX::PluginFactoryArray &ids)
{
    static WavePluginFactory p(kPluginIdentifier, kPluginVersionMajor, kPluginVersionMinor);
    ids.push_back(&p);
}
<|endoftext|>


<commit_before>/*
 *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "pc/audio_rtp_receiver.h"

#include <stddef.h>

#include <utility>
#include <vector>

#include "api/media_stream_proxy.h"
#include "api/media_stream_track_proxy.h"
#include "pc/audio_track.h"
#include "pc/jitter_buffer_delay.h"
#include "pc/jitter_buffer_delay_proxy.h"
#include "pc/media_stream.h"
#include "rtc_base/checks.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/trace_event.h"

namespace webrtc {

AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
                                   std::string receiver_id,
                                   std::vector<std::string> stream_ids)
    : AudioRtpReceiver(worker_thread,
                       receiver_id,
                       CreateStreamsFromIds(std::move(stream_ids))) {}

AudioRtpReceiver::AudioRtpReceiver(
    rtc::Thread* worker_thread,
    const std::string& receiver_id,
    const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
    : worker_thread_(worker_thread),
      id_(receiver_id),
      source_(new rtc::RefCountedObject<RemoteAudioSource>(worker_thread)),
      track_(AudioTrackProxy::Create(rtc::Thread::Current(),
                                     AudioTrack::Create(receiver_id, source_))),
      cached_track_enabled_(track_->enabled()),
      attachment_id_(GenerateUniqueId()),
      delay_(JitterBufferDelayProxy::Create(
          rtc::Thread::Current(),
          worker_thread_,
          new rtc::RefCountedObject<JitterBufferDelay>(worker_thread))) {
  RTC_DCHECK(worker_thread_);
  RTC_DCHECK(track_->GetSource()->remote());
  track_->RegisterObserver(this);
  track_->GetSource()->RegisterAudioObserver(this);
  SetStreams(streams);
}

AudioRtpReceiver::~AudioRtpReceiver() {
  track_->GetSource()->UnregisterAudioObserver(this);
  track_->UnregisterObserver(this);
  Stop();
}

void AudioRtpReceiver::OnChanged() {
  if (cached_track_enabled_ != track_->enabled()) {
    cached_track_enabled_ = track_->enabled();
    Reconfigure();
  }
}

bool AudioRtpReceiver::SetOutputVolume(double volume) {
  RTC_DCHECK_GE(volume, 0.0);
  RTC_DCHECK_LE(volume, 10.0);
  RTC_DCHECK(media_channel_);
  RTC_DCHECK(!stopped_);
  return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
    return ssrc_ ? media_channel_->SetOutputVolume(*ssrc_, volume)
                 : media_channel_->SetDefaultOutputVolume(volume);
  });
}

void AudioRtpReceiver::OnSetVolume(double volume) {
  RTC_DCHECK_GE(volume, 0);
  RTC_DCHECK_LE(volume, 10);
  cached_volume_ = volume;
  if (!media_channel_ || stopped_) {
    RTC_LOG(LS_ERROR)
        << "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
    return;
  }
  // When the track is disabled, the volume of the source, which is the
  // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
  // setting the volume to the source when the track is disabled.
  if (!stopped_ && track_->enabled()) {
    if (!SetOutputVolume(cached_volume_)) {
      RTC_NOTREACHED();
    }
  }
}

std::vector<std::string> AudioRtpReceiver::stream_ids() const {
  std::vector<std::string> stream_ids(streams_.size());
  for (size_t i = 0; i < streams_.size(); ++i)
    stream_ids[i] = streams_[i]->id();
  return stream_ids;
}

RtpParameters AudioRtpReceiver::GetParameters() const {
  if (!media_channel_ || stopped_) {
    return RtpParameters();
  }
  return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
    return ssrc_ ? media_channel_->GetRtpReceiveParameters(*ssrc_)
                 : media_channel_->GetDefaultRtpReceiveParameters();
  });
}

void AudioRtpReceiver::SetFrameDecryptor(
    rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
  frame_decryptor_ = std::move(frame_decryptor);
  // Special Case: Set the frame decryptor to any value on any existing channel.
  if (media_channel_ && ssrc_.has_value() && !stopped_) {
    worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
      media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
    });
  }
}

rtc::scoped_refptr<FrameDecryptorInterface>
AudioRtpReceiver::GetFrameDecryptor() const {
  return frame_decryptor_;
}

void AudioRtpReceiver::Stop() {
  // TODO(deadbeef): Need to do more here to fully stop receiving packets.
  if (stopped_) {
    return;
  }
  if (media_channel_) {
    // Allow that SetOutputVolume fail. This is the normal case when the
    // underlying media channel has already been deleted.
    SetOutputVolume(0.0);
  }
  stopped_ = true;
}

void AudioRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
  RTC_DCHECK(media_channel_);
  if (!stopped_ && ssrc_ == ssrc) {
    return;
  }

  if (!stopped_) {
    source_->Stop(media_channel_, ssrc_);
    delay_->OnStop();
  }
  ssrc_ = ssrc;
  stopped_ = false;
  source_->Start(media_channel_, ssrc);
  delay_->OnStart(media_channel_, ssrc.value_or(0));
  Reconfigure();
}

void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
  if (!media_channel_) {
    RTC_LOG(LS_ERROR)
        << "AudioRtpReceiver::SetupMediaChannel: No audio channel exists.";
    return;
  }
  RestartMediaChannel(ssrc);
}

void AudioRtpReceiver::SetupUnsignaledMediaChannel() {
  if (!media_channel_) {
    RTC_LOG(LS_ERROR) << "AudioRtpReceiver::SetupUnsignaledMediaChannel: No "
                         "audio channel exists.";
  }
  RestartMediaChannel(absl::nullopt);
}

void AudioRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
  SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
}

void AudioRtpReceiver::SetStreams(
    const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
  // Remove remote track from any streams that are going away.
  for (const auto& existing_stream : streams_) {
    bool removed = true;
    for (const auto& stream : streams) {
      if (existing_stream->id() == stream->id()) {
        RTC_DCHECK_EQ(existing_stream.get(), stream.get());
        removed = false;
        break;
      }
    }
    if (removed) {
      existing_stream->RemoveTrack(track_);
    }
  }
  // Add remote track to any streams that are new.
  for (const auto& stream : streams) {
    bool added = true;
    for (const auto& existing_stream : streams_) {
      if (stream->id() == existing_stream->id()) {
        RTC_DCHECK_EQ(stream.get(), existing_stream.get());
        added = false;
        break;
      }
    }
    if (added) {
      stream->AddTrack(track_);
    }
  }
  streams_ = streams;
}

std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
  if (!media_channel_ || !ssrc_ || stopped_) {
    return {};
  }
  return worker_thread_->Invoke<std::vector<RtpSource>>(
      RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
}

void AudioRtpReceiver::SetDepacketizerToDecoderFrameTransformer(
    rtc::scoped_refptr<webrtc::FrameTransformerInterface> frame_transformer) {
  if (media_channel_ && ssrc_.has_value() && !stopped_) {
    worker_thread_->Invoke<void>(
        RTC_FROM_HERE,
        [this, frame_transformer = std::move(frame_transformer)] {
          RTC_DCHECK_RUN_ON(worker_thread_);
          frame_transformer_ = frame_transformer;
          media_channel_->SetDepacketizerToDecoderFrameTransformer(
              *ssrc_, frame_transformer);
        });
  }
}

void AudioRtpReceiver::Reconfigure() {
  if (!media_channel_ || stopped_) {
    RTC_LOG(LS_ERROR)
        << "AudioRtpReceiver::Reconfigure: No audio channel exists.";
    return;
  }
  if (!SetOutputVolume(track_->enabled() ? cached_volume_ : 0)) {
    RTC_NOTREACHED();
  }
  // Reattach the frame decryptor if we were reconfigured.
  MaybeAttachFrameDecryptorToMediaChannel(
      ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);

  if (media_channel_ && ssrc_.has_value() && !stopped_) {
    worker_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
      RTC_DCHECK_RUN_ON(worker_thread_);
      if (!frame_transformer_)
        return;
      media_channel_->SetDepacketizerToDecoderFrameTransformer(
          *ssrc_, frame_transformer_);
    });
  }
}

void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
  observer_ = observer;
  // Deliver any notifications the observer may have missed by being set late.
  if (received_first_packet_ && observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
}

void AudioRtpReceiver::SetJitterBufferMinimumDelay(
    absl::optional<double> delay_seconds) {
  delay_->Set(delay_seconds);
}

void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
  RTC_DCHECK(media_channel == nullptr ||
             media_channel->media_type() == media_type());
  media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
}

void AudioRtpReceiver::NotifyFirstPacketReceived() {
  if (observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
  received_first_packet_ = true;
}

}  // namespace webrtc
<commit_msg>[InsertableStreams] Save the transformer to be set on Reconfigure.<commit_after>/*
 *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "pc/audio_rtp_receiver.h"

#include <stddef.h>

#include <utility>
#include <vector>

#include "api/media_stream_proxy.h"
#include "api/media_stream_track_proxy.h"
#include "pc/audio_track.h"
#include "pc/jitter_buffer_delay.h"
#include "pc/jitter_buffer_delay_proxy.h"
#include "pc/media_stream.h"
#include "rtc_base/checks.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/trace_event.h"

namespace webrtc {

AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
                                   std::string receiver_id,
                                   std::vector<std::string> stream_ids)
    : AudioRtpReceiver(worker_thread,
                       receiver_id,
                       CreateStreamsFromIds(std::move(stream_ids))) {}

AudioRtpReceiver::AudioRtpReceiver(
    rtc::Thread* worker_thread,
    const std::string& receiver_id,
    const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
    : worker_thread_(worker_thread),
      id_(receiver_id),
      source_(new rtc::RefCountedObject<RemoteAudioSource>(worker_thread)),
      track_(AudioTrackProxy::Create(rtc::Thread::Current(),
                                     AudioTrack::Create(receiver_id, source_))),
      cached_track_enabled_(track_->enabled()),
      attachment_id_(GenerateUniqueId()),
      delay_(JitterBufferDelayProxy::Create(
          rtc::Thread::Current(),
          worker_thread_,
          new rtc::RefCountedObject<JitterBufferDelay>(worker_thread))) {
  RTC_DCHECK(worker_thread_);
  RTC_DCHECK(track_->GetSource()->remote());
  track_->RegisterObserver(this);
  track_->GetSource()->RegisterAudioObserver(this);
  SetStreams(streams);
}

AudioRtpReceiver::~AudioRtpReceiver() {
  track_->GetSource()->UnregisterAudioObserver(this);
  track_->UnregisterObserver(this);
  Stop();
}

void AudioRtpReceiver::OnChanged() {
  if (cached_track_enabled_ != track_->enabled()) {
    cached_track_enabled_ = track_->enabled();
    Reconfigure();
  }
}

bool AudioRtpReceiver::SetOutputVolume(double volume) {
  RTC_DCHECK_GE(volume, 0.0);
  RTC_DCHECK_LE(volume, 10.0);
  RTC_DCHECK(media_channel_);
  RTC_DCHECK(!stopped_);
  return worker_thread_->Invoke<bool>(RTC_FROM_HERE, [&] {
    return ssrc_ ? media_channel_->SetOutputVolume(*ssrc_, volume)
                 : media_channel_->SetDefaultOutputVolume(volume);
  });
}

void AudioRtpReceiver::OnSetVolume(double volume) {
  RTC_DCHECK_GE(volume, 0);
  RTC_DCHECK_LE(volume, 10);
  cached_volume_ = volume;
  if (!media_channel_ || stopped_) {
    RTC_LOG(LS_ERROR)
        << "AudioRtpReceiver::OnSetVolume: No audio channel exists.";
    return;
  }
  // When the track is disabled, the volume of the source, which is the
  // corresponding WebRtc Voice Engine channel will be 0. So we do not allow
  // setting the volume to the source when the track is disabled.
  if (!stopped_ && track_->enabled()) {
    if (!SetOutputVolume(cached_volume_)) {
      RTC_NOTREACHED();
    }
  }
}

std::vector<std::string> AudioRtpReceiver::stream_ids() const {
  std::vector<std::string> stream_ids(streams_.size());
  for (size_t i = 0; i < streams_.size(); ++i)
    stream_ids[i] = streams_[i]->id();
  return stream_ids;
}

RtpParameters AudioRtpReceiver::GetParameters() const {
  if (!media_channel_ || stopped_) {
    return RtpParameters();
  }
  return worker_thread_->Invoke<RtpParameters>(RTC_FROM_HERE, [&] {
    return ssrc_ ? media_channel_->GetRtpReceiveParameters(*ssrc_)
                 : media_channel_->GetDefaultRtpReceiveParameters();
  });
}

void AudioRtpReceiver::SetFrameDecryptor(
    rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {
  frame_decryptor_ = std::move(frame_decryptor);
  // Special Case: Set the frame decryptor to any value on any existing channel.
  if (media_channel_ && ssrc_.has_value() && !stopped_) {
    worker_thread_->Invoke<void>(RTC_FROM_HERE, [&] {
      media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_);
    });
  }
}

rtc::scoped_refptr<FrameDecryptorInterface>
AudioRtpReceiver::GetFrameDecryptor() const {
  return frame_decryptor_;
}

void AudioRtpReceiver::Stop() {
  // TODO(deadbeef): Need to do more here to fully stop receiving packets.
  if (stopped_) {
    return;
  }
  if (media_channel_) {
    // Allow that SetOutputVolume fail. This is the normal case when the
    // underlying media channel has already been deleted.
    SetOutputVolume(0.0);
  }
  stopped_ = true;
}

void AudioRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) {
  RTC_DCHECK(media_channel_);
  if (!stopped_ && ssrc_ == ssrc) {
    return;
  }

  if (!stopped_) {
    source_->Stop(media_channel_, ssrc_);
    delay_->OnStop();
  }
  ssrc_ = ssrc;
  stopped_ = false;
  source_->Start(media_channel_, ssrc);
  delay_->OnStart(media_channel_, ssrc.value_or(0));
  Reconfigure();
}

void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) {
  if (!media_channel_) {
    RTC_LOG(LS_ERROR)
        << "AudioRtpReceiver::SetupMediaChannel: No audio channel exists.";
    return;
  }
  RestartMediaChannel(ssrc);
}

void AudioRtpReceiver::SetupUnsignaledMediaChannel() {
  if (!media_channel_) {
    RTC_LOG(LS_ERROR) << "AudioRtpReceiver::SetupUnsignaledMediaChannel: No "
                         "audio channel exists.";
  }
  RestartMediaChannel(absl::nullopt);
}

void AudioRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
  SetStreams(CreateStreamsFromIds(std::move(stream_ids)));
}

void AudioRtpReceiver::SetStreams(
    const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {
  // Remove remote track from any streams that are going away.
  for (const auto& existing_stream : streams_) {
    bool removed = true;
    for (const auto& stream : streams) {
      if (existing_stream->id() == stream->id()) {
        RTC_DCHECK_EQ(existing_stream.get(), stream.get());
        removed = false;
        break;
      }
    }
    if (removed) {
      existing_stream->RemoveTrack(track_);
    }
  }
  // Add remote track to any streams that are new.
  for (const auto& stream : streams) {
    bool added = true;
    for (const auto& existing_stream : streams_) {
      if (stream->id() == existing_stream->id()) {
        RTC_DCHECK_EQ(stream.get(), existing_stream.get());
        added = false;
        break;
      }
    }
    if (added) {
      stream->AddTrack(track_);
    }
  }
  streams_ = streams;
}

std::vector<RtpSource> AudioRtpReceiver::GetSources() const {
  if (!media_channel_ || !ssrc_ || stopped_) {
    return {};
  }
  return worker_thread_->Invoke<std::vector<RtpSource>>(
      RTC_FROM_HERE, [&] { return media_channel_->GetSources(*ssrc_); });
}

void AudioRtpReceiver::SetDepacketizerToDecoderFrameTransformer(
    rtc::scoped_refptr<webrtc::FrameTransformerInterface> frame_transformer) {
  worker_thread_->Invoke<void>(
      RTC_FROM_HERE, [this, frame_transformer = std::move(frame_transformer)] {
        RTC_DCHECK_RUN_ON(worker_thread_);
        frame_transformer_ = frame_transformer;
        if (media_channel_ && ssrc_.has_value() && !stopped_) {
          media_channel_->SetDepacketizerToDecoderFrameTransformer(
              *ssrc_, frame_transformer);
        }
      });
}

void AudioRtpReceiver::Reconfigure() {
  if (!media_channel_ || stopped_) {
    RTC_LOG(LS_ERROR)
        << "AudioRtpReceiver::Reconfigure: No audio channel exists.";
    return;
  }
  if (!SetOutputVolume(track_->enabled() ? cached_volume_ : 0)) {
    RTC_NOTREACHED();
  }
  // Reattach the frame decryptor if we were reconfigured.
  MaybeAttachFrameDecryptorToMediaChannel(
      ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);

  if (media_channel_ && ssrc_.has_value() && !stopped_) {
    worker_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
      RTC_DCHECK_RUN_ON(worker_thread_);
      if (!frame_transformer_)
        return;
      media_channel_->SetDepacketizerToDecoderFrameTransformer(
          *ssrc_, frame_transformer_);
    });
  }
}

void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) {
  observer_ = observer;
  // Deliver any notifications the observer may have missed by being set late.
  if (received_first_packet_ && observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
}

void AudioRtpReceiver::SetJitterBufferMinimumDelay(
    absl::optional<double> delay_seconds) {
  delay_->Set(delay_seconds);
}

void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
  RTC_DCHECK(media_channel == nullptr ||
             media_channel->media_type() == media_type());
  media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
}

void AudioRtpReceiver::NotifyFirstPacketReceived() {
  if (observer_) {
    observer_->OnFirstPacketReceived(media_type());
  }
  received_first_packet_ = true;
}

}  // namespace webrtc
<|endoftext|>