From 379416dc2318ed090dc1666c9e65ab9d30d137b9 Mon Sep 17 00:00:00 2001 From: gralkapk Date: Tue, 3 Oct 2023 16:32:28 +0200 Subject: [PATCH 1/8] wip --- .../utility/graphics/ScreenShotComments.h | 4 +- .../utility/graphics/ScreenShotComments.cpp | 14 +- frontend/resources/include/RuntimeInfo.h | 12 ++ frontend/resources/include/Screenshots.h | 8 +- frontend/services/CMakeLists.txt | 3 + .../RuntimeInfo_Service.cpp | 127 +++++++++++++ .../RuntimeInfo_Service.hpp | 179 ++++++++++++++++++ .../screenshot_service/Screenshot_Service.cpp | 39 ++-- .../screenshot_service/Screenshot_Service.hpp | 4 + vcpkg.json | 4 + 10 files changed, 366 insertions(+), 28 deletions(-) create mode 100644 frontend/resources/include/RuntimeInfo.h create mode 100644 frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp create mode 100644 frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp diff --git a/core/include/mmcore/utility/graphics/ScreenShotComments.h b/core/include/mmcore/utility/graphics/ScreenShotComments.h index ce30f66c20..81cc120a4b 100644 --- a/core/include/mmcore/utility/graphics/ScreenShotComments.h +++ b/core/include/mmcore/utility/graphics/ScreenShotComments.h @@ -14,6 +14,8 @@ #include +#include "RuntimeInfo.h" + namespace megamol::core::utility::graphics { class ScreenShotComments { @@ -26,7 +28,7 @@ class ScreenShotComments { * constructor and later get out the png_text you need for feeding libpng. Note that the returned png_text array * is only valid as long as the ScreenShotComments instance is in scope! */ - ScreenShotComments(std::string const& project_configuration, + ScreenShotComments(std::string const& project_configuration, megamol::frontend_resources::RuntimeInfo const* ri, const std::optional& additional_comments = std::nullopt); png_comments GetComments() const; diff --git a/core/src/utility/graphics/ScreenShotComments.cpp b/core/src/utility/graphics/ScreenShotComments.cpp index 85d53c7582..478a19c471 100644 --- a/core/src/utility/graphics/ScreenShotComments.cpp +++ b/core/src/utility/graphics/ScreenShotComments.cpp @@ -20,8 +20,9 @@ namespace mcu_graphics = megamol::core::utility::graphics; -mcu_graphics::ScreenShotComments::ScreenShotComments( - std::string const& project_configuration, const std::optional& additional_comments) { +mcu_graphics::ScreenShotComments::ScreenShotComments(std::string const& project_configuration, + megamol::frontend_resources::RuntimeInfo const* ri, + const std::optional& additional_comments) { the_comments["Title"] = "MegaMol Screen Capture " + utility::DateTime::CurrentDateTimeFormatted(); //the_comments["Author"] = ""; @@ -34,11 +35,14 @@ mcu_graphics::ScreenShotComments::ScreenShotComments( the_comments["Remote Branch"] = megamol::core::utility::buildinfo::MEGAMOL_GIT_BRANCH_NAME_FULL(); the_comments["Remote URL"] = megamol::core::utility::buildinfo::MEGAMOL_GIT_REMOTE_URL(); - the_comments["Software Environment"] = platform::RuntimeInfo::GetRuntimeLibraries(); - the_comments["Hardware Environment"] = platform::RuntimeInfo::GetHardwareInfo(); the_comments["CMakeCache"] = megamol::core::utility::buildinfo::MEGAMOL_CMAKE_CACHE(); the_comments["Git Diff"] = megamol::core::utility::buildinfo::MEGAMOL_GIT_DIFF(); - the_comments["Operating System"] = platform::RuntimeInfo::GetOsInfo(); + + if (ri) { + the_comments["Hardware Environment"] = ri->get_hardware_info(); + the_comments["Operating System"] = ri->get_os_info(); + the_comments["Software Environment"] = ri->get_runtime_libraries(); + } //the_comments["Disclaimer"] = ""; //the_comments["Warning"] = ""; diff --git a/frontend/resources/include/RuntimeInfo.h b/frontend/resources/include/RuntimeInfo.h new file mode 100644 index 0000000000..2ea1040df8 --- /dev/null +++ b/frontend/resources/include/RuntimeInfo.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace megamol::frontend_resources { +struct RuntimeInfo { + std::function get_hardware_info; + std::function get_os_info; + std::function get_runtime_libraries; +}; +} // namespace megamol::frontend_resources diff --git a/frontend/resources/include/Screenshots.h b/frontend/resources/include/Screenshots.h index 1b22ebce15..e3fdb24cef 100644 --- a/frontend/resources/include/Screenshots.h +++ b/frontend/resources/include/Screenshots.h @@ -57,11 +57,11 @@ class IScreenshotSource { class IImageDataWriter { public: - bool write_screenshot(IScreenshotSource const& image_source, std::filesystem::path const& filename) const { - return this->write_image(image_source.take_screenshot(), filename); + bool write_screenshot(IScreenshotSource const& image_source, std::filesystem::path const& filename, void const* user_ptr = nullptr) const { + return this->write_image(image_source.take_screenshot(), filename, user_ptr); } - virtual bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename) const = 0; + virtual bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename, void const* user_ptr = nullptr) const = 0; ~IImageDataWriter() = default; }; @@ -99,7 +99,7 @@ class GLScreenshotSource : public IScreenshotSource { class ScreenshotImageDataToPNGWriter : public IImageDataWriter { public: - bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename) const override; + bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename, void const* user_ptr = nullptr) const override; }; diff --git a/frontend/services/CMakeLists.txt b/frontend/services/CMakeLists.txt index 3d314937e1..eaeb757bed 100644 --- a/frontend/services/CMakeLists.txt +++ b/frontend/services/CMakeLists.txt @@ -32,6 +32,7 @@ file(GLOB_RECURSE header_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "remote_service/*.hpp" "profiling_service/*.hpp" "vr_service/*.hpp" + "runtimeinfo_service/*.hpp" # "service_template/*.hpp" ) @@ -48,6 +49,7 @@ file(GLOB_RECURSE source_files RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "remote_service/*.cpp" "profiling_service/*.cpp" "vr_service/*.cpp" + "runtimeinfo_service/*.cpp" # "service_template/*.cpp" ) @@ -109,6 +111,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC "gui/3rd" "gui/src" "vr_service" + "runtime_service" # "service_template" ) diff --git a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp new file mode 100644 index 0000000000..8ff6e4cc76 --- /dev/null +++ b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp @@ -0,0 +1,127 @@ +/** + * MegaMol + * Copyright (c) 2021, MegaMol Dev Team + * All rights reserved. + */ + +// search/replace Template_Service with your class name +// you should also delete the FAQ comments in these template files after you read and understood them +#include "RuntimeInfo_Service.hpp" + + +// local logging wrapper for your convenience until central MegaMol logger established +#include "mmcore/utility/log/Log.h" + +static const std::string service_name = "RuntimeInfo_Service: "; +static void log(std::string const& text) { + const std::string msg = service_name + text; + megamol::core::utility::log::Log::DefaultLog.WriteInfo(msg.c_str()); +} + +static void log_error(std::string const& text) { + const std::string msg = service_name + text; + megamol::core::utility::log::Log::DefaultLog.WriteError(msg.c_str()); +} + +static void log_warning(std::string const& text) { + const std::string msg = service_name + text; + megamol::core::utility::log::Log::DefaultLog.WriteWarn(msg.c_str()); +} + + +namespace megamol { +namespace frontend { + +RuntimeInfo_Service::RuntimeInfo_Service() { + // init members to default states +} + +RuntimeInfo_Service::~RuntimeInfo_Service() { + // clean up raw pointers you allocated with new, which is bad practice and nobody does +} + +bool RuntimeInfo_Service::init(void* configPtr) { + if (configPtr == nullptr) + return false; + + return init(*static_cast(configPtr)); +} + +bool RuntimeInfo_Service::init(const Config& config) { + // initialize your service and its provided resources using config parameters + // for now, you dont need to worry about your service beeing initialized or closed multiple times + // init() and close() only get called once in the lifetime of each service object + // but maybe more instances of your service will get created? this may be relevant for central resources you manage (like libraries, network connections). + + ri_resource_.get_hardware_info = [&]() { return get_hardware_info(); }; + ri_resource_.get_os_info = [&]() { return get_os_info(); }; + ri_resource_.get_runtime_libraries = [&]() { return get_runtime_libraries(); }; + + m_providedResourceReferences = {{"RuntimeInfo", ri_resource_}}; + + log("initialized successfully"); + return true; +} + +void RuntimeInfo_Service::close() { + // close libraries or APIs you manage + // wrap up resources your service provides, but don not depend on outside resources to be available here + // after this, at some point only the destructor of your service gets called +} + +std::vector& RuntimeInfo_Service::getProvidedResources() { + return m_providedResourceReferences; +} + +const std::vector RuntimeInfo_Service::getRequestedResourceNames() const { + return m_requestedResourcesNames; +} + +void RuntimeInfo_Service::setRequestedResources(std::vector resources) { + // maybe we want to keep the list of requested resources + this->m_requestedResourceReferences = resources; +} + +void RuntimeInfo_Service::updateProvidedResources() {} + +void RuntimeInfo_Service::digestChangedRequestedResources() {} + +void RuntimeInfo_Service::resetProvidedResources() { + // this gets called at the end of the main loop iteration + // since the current resources state should have been handled in this frame already + // you may clean up resources whose state is not needed for the next iteration + // e.g. m_keyboardEvents.clear(); + // network_traffic_buffer.reset_to_empty(); +} + +void RuntimeInfo_Service::preGraphRender() { + // this gets called right before the graph is told to render something + // e.g. you can start a start frame timer here + + // rendering via MegaMol View is called after this function finishes + // in the end this calls the equivalent of ::mmcRenderView(hView, &renderContext) + // which leads to view.Render() +} + +void RuntimeInfo_Service::postGraphRender() { + // the graph finished rendering and you may more stuff here + // e.g. end frame timer + // update window name + // swap buffers, glClear +} + +std::string RuntimeInfo_Service::get_hardware_info() { + return ri_.GetHardwareInfo(); +} + +std::string RuntimeInfo_Service::get_os_info() { + return ri_.GetOsInfo(); +} + +std::string RuntimeInfo_Service::get_runtime_libraries() { + return ri_.GetRuntimeLibraries(); +} + + +} // namespace frontend +} // namespace megamol diff --git a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp new file mode 100644 index 0000000000..2994f61c4e --- /dev/null +++ b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp @@ -0,0 +1,179 @@ +/** + * MegaMol + * Copyright (c) 2021, MegaMol Dev Team + * All rights reserved. + */ + +#pragma once + +#include "AbstractFrontendService.hpp" + +#include "mmcore/utility/platform/RuntimeInfo.h" + +#include "RuntimeInfo.h" + +namespace megamol { +namespace frontend { + +// search/replace Template_Service with your class name +// you should also delete the FAQ comments in these template files after you read and understood them +class RuntimeInfo_Service final : public AbstractFrontendService { +public: + // We encourage you to use a configuration struct + // that can be passed to your init() function. + struct Config {}; + + // sometimes somebody wants to know the name of the service + std::string serviceName() const override { + return "RuntimeInfo_Service"; + } + + // constructor should not take arguments, actual object initialization deferred until init() + RuntimeInfo_Service(); + ~RuntimeInfo_Service(); + // your service will be constructed and destructed, but not copy-constructed or move-constructed + // so no need to worry about copy or move constructors. + + // implement the following functions/callbacks to get your service hooked into the frontend + + // init service with input config data, e.g. init GLFW with OpenGL and open window with certain decorations/hints + // if init() fails return false (this will terminate program execution), on success return true + bool init(const Config& config); + bool init(void* configPtr) override; + void close() override; + + // expose the resources or input events this service provides via getProvidedResources(): e.g. Keyboard inputs, Controller inputs, GLFW Window events + // the FrontendResource is a named wrapper that wraps some type (struct) in an std::any and casts its content to a requested type + // each service may provide a set of resources for other services or graph modules to use + // usually resources shared among services and modules are read only, in the sense that the FrontendResource wrapper only returns const& to held resources + // if you need to manipulate a resource that you do not own, make sure you know what you're doing before using const_cast<> + // keep in mind that the FrontendResource is just a wrapper that holds a void* to an object that you provided + // thus, keep objects that you broadcast as resources alive until your close() gets called! + // if lifetime of one of your resources ends before your close() gets called you produce dangling references in other services! + // if you need to re-initialize or swap resource contents in a way that needs an objects lifetime to end, consider wrapping that behaviour in a way that is user friendly + std::vector& getProvidedResources() override; + + // a service may request a set of resources that are provided by other services or the system + // this works in two steps: the service tells the system which services it requests using the service names (usually the type name of the structs) + // the frontend system makes sure to provide the service with the requested resources, or else program execution is terminated with an error message + // note that the list of resources given to the service is in order of the initial resource requests, + // thus you don't need to search for resources by name but can rather access the set resource vector directly at the expected index + // the idea of behind resources is that when your service gets its list of requested resources, + // the contract is that there will be an actual resource available and not some null pointer. + // if somebody does not play along and provides fake resources with wrong wrapped types to the system, thus giving your code garbage to work with, + // we can not really stop him from doing so, but there should occur an unhandled exception thrown by std::any for a bad type cast + // the gist is that you should expect to get the correct resources you requested from the system + // and you can work on those resources without tedious error and type checking + // if you want to see how resources are distributed among the services, look into FrontendServiceCollection.cpp::assignRequestedResources() + // the lifetime of the resources you get starts when your setRequestedResources() gets called and ends before your close() gets called + // dont depend on requested resources being available in your close(). you yourself sould destroy or close the resources you provide in close(). + // init() gets called in order of service priority (see below) and close() gets called in reverse order, + // so if you really need access to some resource in your close() make sure + // the priority order of your service is _after_ the service that provides your critical resources (i.e. your set priority number should be higher) + const std::vector getRequestedResourceNames() const override; + void setRequestedResources(std::vector resources) override; + + // the following resource update and graph render callbacks get called in each iteration of the main loop + // this is probably where most work of your service is done + // the service callbacks get called in the main loop in the following order: + // + // auto services = {lua_service, opengl_service, gui_service}; // wrapper that loops over all services in service priority order + // services.init(); + // services.assignResourcesAmongServices(); + // + // while (true) { + // services.updateProvidedResources(); + // services.digestChangedRequestedResources(); + // + // if (services.shouldShutdown()) + // break; + // + // {// render step + // services.preGraphRender(); + // megamol_graph.RenderNextFrame(); + // services.postGraphRender(); // calls service callbacks in reverse order + // } + // + // services.resetProvidedResources(); + // } + // services.close(); // calls service callbacks in reverse order + + // called first in main loop, each service updates its shared resources to some new state here (e.g. receive keyboard inputs, network traffic) + void updateProvidedResources() override; + + // after each service updates its provided resources, services may check for updates in their requested resources + // for example, a GUI may check for user inputs placed in keyboard or mouse input resources that are provided by some other service + // usually working with resources should not modify them, + // but if you are really sure that it is ok for you to change resources, you may cast the away the const from the resource reference and manipulate the resource + // for example, you may cast away the const from the MegaMolGraph to issue creation/deletion of modules and calls + // or you may delete keyboard and mouse inputs from corresponding resources if you are sure they only affect your service + // this callback is also a good place to verify if your service received a shutdown request and propagate it to the system via setShutdown() + void digestChangedRequestedResources() override; + + // after rendering of a frame finished and before the next iteration of the main loop, services may want to reset resource state to some value + // e.g. after user inputs (keyboard, mouse) or window resize evets got handled by the relevant services or modules, + // the service providing and managing those resource structs may want to clear those inputs before the next frame starts + // (in some cases the distinction between updateProvidedResources() at the beginning of a main loop iteration + // and a resetProvidedResources() at the end of that iteration seems to be necessary) + void resetProvidedResources() override; + + // gets called before graph rendering, you may prepare rendering with some API, e.g. set frame-timers, etc + void preGraphRender() override; + // clean up after rendering, e.g. render gui over graph rendering, stop and show frame-timers in GLFW window, swap buffers, glClear for next framebuffer + void postGraphRender() override; + + // from AbstractFrontendService + // you inherit the following functions that manage priority of your service and shutdown requests to terminate the program + // you and others may use those functions, but you will not override them + // priority indicates the order in which services get their callbacks called, i.e. this is the sorting of the vector that holds all services + // lower priority numbers get called before the bigger ones. for close() and postGraphRender() services get called in the reverse order, + // i.e. this works like construction and destruction order of objects in a c++ + // + // int setPriority(const int p) // priority initially 0 + // int getPriority() const; + + // your service can signal to the program that a shutdown request has been received. + // call setShutdown() to set your shutdown status to true, this is best done in your updateProvidedResources() or digestChangedRequestedResources(). + // if a servie signals a shutdown the system calls close() on all services in reverse priority order, then program execution terminates. + // + // bool shouldShutdown() const; // shutdown initially false + // void setShutdown(const bool s = true); + +private: + std::string get_hardware_info(); + + std::string get_os_info(); + + std::string get_runtime_libraries(); + + // this can hold references to the resources (i.e. structs) we provide to others, e.g. you may fill this and return it in getProvidedResources() + // provided resources will be queried by the system only once, + // there is no requirement to store the resources in a vector the whole time, you just need to return such a vector in getProvidedResources() + // but you need to store the actual resource objects you provide and manage + // note that FrontendResource wraps a void* to the objects you provide, thus your resource objects will not be copied, but they will be referenced + // (however the FrontendResource objects themselves will be copied) + std::vector m_providedResourceReferences; + + // names of resources you request for your service can go here + // requested resource names will be queried by the system only once, + // there is no requirement to store the names in a vector the whole time, you just need to return such a vector in getRequestedResourceNames() + std::vector m_requestedResourcesNames; + + // you may store the resources you requested in this vector by filling it when your setRequestedResources() gets called + // the resources provided to you by the system match the names you requested in getRequestedResourceNames() and are expected to reference actual existing objects + // the sorting of resources matches the order of your requested resources names, you can use this to directly index into the vector provided by setRequestedResources() + // if every service follows the rules the provided resources should be valid existing objects, thus you can use them directly without error or nullptr checking, + // but we in the end we must blindly rely on the std::any in FrontendResource to hold the struct or type you expect it to hold + // (or else std::any will throw a bad type cast exception that should terminate program execution. + // you do NOT catch or check for that exception or need to care for it in any way!) + std::vector m_requestedResourceReferences; + + bool initialized_ = false; + + megamol::core::utility::platform::RuntimeInfo ri_; + + megamol::frontend_resources::RuntimeInfo ri_resource_; +}; + +} // namespace frontend +} // namespace megamol diff --git a/frontend/services/screenshot_service/Screenshot_Service.cpp b/frontend/services/screenshot_service/Screenshot_Service.cpp index b7aebf8699..166c6bad30 100644 --- a/frontend/services/screenshot_service/Screenshot_Service.cpp +++ b/frontend/services/screenshot_service/Screenshot_Service.cpp @@ -69,8 +69,8 @@ static void PNGAPI pngFlushFileFunc(png_structp pngPtr) { f->Flush(); } -static bool write_png_to_file( - megamol::frontend_resources::ScreenshotImageData const& image, std::filesystem::path const& filename) { +static bool write_png_to_file(megamol::frontend_resources::ScreenshotImageData const& image, + std::filesystem::path const& filename, megamol::frontend_resources::RuntimeInfo const* ri) { vislib::sys::FastFile file; try { // open final image file @@ -105,7 +105,7 @@ static bool write_png_to_file( if (guistate_resources_ptr) { project.append(guistate_resources_ptr->request_gui_state(true)); } - megamol::core::utility::graphics::ScreenShotComments ssc(project); + megamol::core::utility::graphics::ScreenShotComments ssc(project, ri); png_set_text(pngPtr, pngInfoPtr, ssc.GetComments().data(), ssc.GetComments().size()); png_set_IHDR(pngPtr, pngInfoPtr, image.width, image.height, 8, PNG_COLOR_TYPE_RGB_ALPHA /* PNG_COLOR_TYPE_RGB */, @@ -172,8 +172,9 @@ megamol::frontend_resources::ImageWrapperScreenshotSource::take_screenshot() con } bool megamol::frontend_resources::ScreenshotImageDataToPNGWriter::write_image( - ScreenshotImageData const& image, std::filesystem::path const& filename) const { - return write_png_to_file(image, filename); + ScreenshotImageData const& image, std::filesystem::path const& filename, void const* ri_ptr) const { + return write_png_to_file( + image, filename, reinterpret_cast(ri_ptr)); } namespace megamol::frontend { @@ -194,30 +195,30 @@ bool Screenshot_Service::init(void* configPtr) { bool Screenshot_Service::init(const Config& config) { m_requestedResourcesNames = {"optional", // TODO: for GLScreenshoSource. how to kill? - frontend_resources::MegaMolGraph_Req_Name, "optional", "RuntimeConfig", - "optional"}; + frontend_resources::MegaMolGraph_Req_Name, "optional", "RuntimeConfig", "optional", + "RuntimeInfo"}; + screenshot_show_privacy_note = config.show_privacy_note; + + log("initialized successfully"); + return true; +} + +void Screenshot_Service::close() {} + +std::vector& Screenshot_Service::getProvidedResources() { this->m_frontbufferToPNG_trigger = [&](std::filesystem::path const& filename) -> bool { log("write screenshot to " + filename.generic_u8string()); - return m_toFileWriter_resource.write_screenshot(m_frontbufferSource_resource, filename); + return m_toFileWriter_resource.write_screenshot(m_frontbufferSource_resource, filename, ri_); }; - screenshot_show_privacy_note = config.show_privacy_note; - this->m_imagewrapperToPNG_trigger = [&](megamol::frontend_resources::ImageWrapper const& image, std::filesystem::path const& filename) -> bool { log("write screenshot to " + filename.generic_u8string()); return m_toFileWriter_resource.write_screenshot( - megamol::frontend_resources::ImageWrapperScreenshotSource(image), filename); + megamol::frontend_resources::ImageWrapperScreenshotSource(image), filename, ri_); }; - log("initialized successfully"); - return true; -} - -void Screenshot_Service::close() {} - -std::vector& Screenshot_Service::getProvidedResources() { this->m_providedResourceReferences = {{"GLScreenshotSource", m_frontbufferSource_resource}, {"ImageDataToPNGWriter", m_toFileWriter_resource}, {"GLFrontbufferToPNG_ScreenshotTrigger", m_frontbufferToPNG_trigger}, @@ -247,6 +248,8 @@ void Screenshot_Service::setRequestedResources(std::vector res gui_window_request_resource.register_notification( "Screenshot", std::weak_ptr(service_open_popup), privacy_note); } + + ri_ = &resources[5].getResource(); } void Screenshot_Service::updateProvidedResources() {} diff --git a/frontend/services/screenshot_service/Screenshot_Service.hpp b/frontend/services/screenshot_service/Screenshot_Service.hpp index 33fe58197c..c81b1d22a8 100644 --- a/frontend/services/screenshot_service/Screenshot_Service.hpp +++ b/frontend/services/screenshot_service/Screenshot_Service.hpp @@ -11,6 +11,8 @@ // ImageData struct and interfaces for screenshot sources/writers #include "Screenshots.h" +#include "RuntimeInfo.h" + namespace megamol::frontend { class Screenshot_Service final : public AbstractFrontendService { @@ -66,6 +68,8 @@ class Screenshot_Service final : public AbstractFrontendService { std::vector m_providedResourceReferences; std::vector m_requestedResourcesNames; std::vector m_requestedResourceReferences; + + megamol::frontend_resources::RuntimeInfo const* ri_; }; } // namespace megamol::frontend diff --git a/vcpkg.json b/vcpkg.json index bb25792267..8630951085 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -57,6 +57,10 @@ "tinygltf", "tinyobjloader", "tinyply", + { + "name": "wil", + "platform": "windows" + }, "zeromq", "zfp", "zlib" From 9c03162cf0c63f71d4a4af41b85f5e177c71c481 Mon Sep 17 00:00:00 2001 From: gralkapk Date: Thu, 5 Oct 2023 17:51:03 +0200 Subject: [PATCH 2/8] runtimeinfo as resource --- plugins/cinematic_gl/src/CinematicView.cpp | 4 +++- plugins/cinematic_gl/src/CinematicView.h | 3 +++ plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h | 4 ++++ plugins/mmstd_gl/src/special/ScreenShooter.cpp | 3 ++- 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/cinematic_gl/src/CinematicView.cpp b/plugins/cinematic_gl/src/CinematicView.cpp index 64239ac0c5..713ca22ed6 100644 --- a/plugins/cinematic_gl/src/CinematicView.cpp +++ b/plugins/cinematic_gl/src/CinematicView.cpp @@ -109,6 +109,8 @@ CinematicView::CinematicView() this->addSBSideToNameParam << new param::BoolParam(false); this->MakeSlotAvailable(&this->addSBSideToNameParam); + + ri_ = &frontend_resources.get(); } @@ -685,7 +687,7 @@ bool CinematicView::render_to_file_write() { auto& megamolgraph = frontend_resources.get(); project = const_cast(megamolgraph).Convenience().SerializeGraph(); - megamol::core::utility::graphics::ScreenShotComments ssc(project); + megamol::core::utility::graphics::ScreenShotComments ssc(project, ri_); png_set_text( this->png_data.structptr, this->png_data.infoptr, ssc.GetComments().data(), ssc.GetComments().size()); png_set_IHDR(this->png_data.structptr, this->png_data.infoptr, this->png_data.width, this->png_data.height, 8, diff --git a/plugins/cinematic_gl/src/CinematicView.h b/plugins/cinematic_gl/src/CinematicView.h index 11c452f344..d0310136cf 100644 --- a/plugins/cinematic_gl/src/CinematicView.h +++ b/plugins/cinematic_gl/src/CinematicView.h @@ -20,6 +20,7 @@ #include "mmstd_gl/renderer/CallRenderViewGL.h" #include "mmstd_gl/view/View3DGL.h" #include "vislib/sys/FastFile.h" +#include "RuntimeInfo.h" namespace megamol::cinematic_gl { @@ -35,6 +36,7 @@ class CinematicView : public mmstd_gl::view::View3DGL { Base::requested_lifetime_resources(req); req.require(); req.require(); + req.require(); } /** @@ -113,6 +115,7 @@ class CinematicView : public mmstd_gl::view::View3DGL { unsigned int fps; bool skyboxCubeMode; std::shared_ptr cinematicFbo; + megamol::frontend_resources::RuntimeInfo const* ri_ = nullptr; /********************************************************************** * functions diff --git a/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h b/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h index 5cb072c0fb..df35be3612 100644 --- a/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h +++ b/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h @@ -15,6 +15,7 @@ #include "mmcore/job/AbstractJob.h" #include "mmcore/param/ParamSlot.h" #include "mmstd/view/AbstractView.h" +#include "RuntimeInfo.h" namespace megamol::mmstd_gl::special { @@ -26,6 +27,7 @@ class ScreenShooter : public core::job::AbstractJob, public core::Module, public static void requested_lifetime_resources(frontend_resources::ResourceRequest& req) { Module::requested_lifetime_resources(req); req.require(); + req.require(); } /** @@ -166,6 +168,8 @@ class ScreenShooter : public core::job::AbstractJob, public core::Module, public bool running; std::shared_ptr currentFbo; + + frontend_resources::RuntimeInfo const* ri_ = nullptr; }; } // namespace megamol::mmstd_gl::special diff --git a/plugins/mmstd_gl/src/special/ScreenShooter.cpp b/plugins/mmstd_gl/src/special/ScreenShooter.cpp index 73415b317f..40048fb93b 100644 --- a/plugins/mmstd_gl/src/special/ScreenShooter.cpp +++ b/plugins/mmstd_gl/src/special/ScreenShooter.cpp @@ -328,6 +328,7 @@ bool special::ScreenShooter::Terminate() { */ bool special::ScreenShooter::create() { currentFbo = std::make_shared(1, 1); + ri_ = &frontend_resources.get(); return true; } @@ -468,7 +469,7 @@ void special::ScreenShooter::BeforeRender(core::view::AbstractView* view) { std::string project; auto& megamolgraph = frontend_resources.get(); project = const_cast(megamolgraph).Convenience().SerializeGraph(); - megamol::core::utility::graphics::ScreenShotComments ssc(project); + megamol::core::utility::graphics::ScreenShotComments ssc(project, ri_); png_set_text(data.pngPtr, data.pngInfoPtr, ssc.GetComments().data(), ssc.GetComments().size()); From e5b746aea0496da8688abbd41ae9ed0c56115082 Mon Sep 17 00:00:00 2001 From: gralkapk Date: Thu, 5 Oct 2023 18:00:57 +0200 Subject: [PATCH 3/8] running runtimeinfo_service --- frontend/main/src/main.cpp | 5 +++++ frontend/services/CMakeLists.txt | 2 +- .../runtimeinfo_service/RuntimeInfo_Service.cpp | 12 ------------ .../runtimeinfo_service/RuntimeInfo_Service.hpp | 1 - 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/frontend/main/src/main.cpp b/frontend/main/src/main.cpp index 7f2eaba399..b2b8a14f87 100644 --- a/frontend/main/src/main.cpp +++ b/frontend/main/src/main.cpp @@ -25,6 +25,7 @@ #include "mmcore/MegaMolGraph.h" #include "mmcore/factories/PluginRegister.h" #include "mmcore/utility/log/Log.h" +#include "RuntimeInfo_Service.hpp" #ifdef MEGAMOL_USE_TRACY #include @@ -69,6 +70,9 @@ int main(const int argc, const char** argv) { log(config.as_string()); log(global_value_store.as_string()); + megamol::frontend::RuntimeInfo_Service ri_service; + ri_service.setPriority(1); + megamol::frontend::OpenGL_GLFW_Service gl_service; megamol::frontend::OpenGL_GLFW_Service::Config openglConfig; openglConfig.windowTitlePrefix = "MegaMol"; @@ -193,6 +197,7 @@ int main(const int argc, const char** argv) { // clang-format on bool run_megamol = true; megamol::frontend::FrontendServiceCollection services; + services.add(ri_service, nullptr); if (with_gl) { services.add(gl_service, &openglConfig); } diff --git a/frontend/services/CMakeLists.txt b/frontend/services/CMakeLists.txt index eaeb757bed..05fab7d89d 100644 --- a/frontend/services/CMakeLists.txt +++ b/frontend/services/CMakeLists.txt @@ -111,7 +111,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC "gui/3rd" "gui/src" "vr_service" - "runtime_service" + "runtimeinfo_service" # "service_template" ) diff --git a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp index 8ff6e4cc76..391bbb534a 100644 --- a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp +++ b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp @@ -41,18 +41,6 @@ RuntimeInfo_Service::~RuntimeInfo_Service() { } bool RuntimeInfo_Service::init(void* configPtr) { - if (configPtr == nullptr) - return false; - - return init(*static_cast(configPtr)); -} - -bool RuntimeInfo_Service::init(const Config& config) { - // initialize your service and its provided resources using config parameters - // for now, you dont need to worry about your service beeing initialized or closed multiple times - // init() and close() only get called once in the lifetime of each service object - // but maybe more instances of your service will get created? this may be relevant for central resources you manage (like libraries, network connections). - ri_resource_.get_hardware_info = [&]() { return get_hardware_info(); }; ri_resource_.get_os_info = [&]() { return get_os_info(); }; ri_resource_.get_runtime_libraries = [&]() { return get_runtime_libraries(); }; diff --git a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp index 2994f61c4e..7520d034ea 100644 --- a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp +++ b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp @@ -38,7 +38,6 @@ class RuntimeInfo_Service final : public AbstractFrontendService { // init service with input config data, e.g. init GLFW with OpenGL and open window with certain decorations/hints // if init() fails return false (this will terminate program execution), on success return true - bool init(const Config& config); bool init(void* configPtr) override; void close() override; From 5e377248ba418033a323706891a9c9f0efac616e Mon Sep 17 00:00:00 2001 From: gralkapk Date: Mon, 9 Oct 2023 16:45:39 +0200 Subject: [PATCH 4/8] extended runtimeinfo --- .../mmcore/utility/platform/RuntimeInfo.h | 48 +++++ .../include/mmcore/utility/platform/WMIUtil.h | 7 +- core/src/utility/platform/RuntimeInfo.cpp | 177 +++++++++++++----- core/src/utility/platform/WMIUtil.cpp | 79 +++++--- 4 files changed, 232 insertions(+), 79 deletions(-) diff --git a/core/include/mmcore/utility/platform/RuntimeInfo.h b/core/include/mmcore/utility/platform/RuntimeInfo.h index 368d9c8347..f6b053f4b6 100644 --- a/core/include/mmcore/utility/platform/RuntimeInfo.h +++ b/core/include/mmcore/utility/platform/RuntimeInfo.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include "WMIUtil.h" @@ -15,6 +16,7 @@ class RuntimeInfo { public: static std::string GetHardwareInfo() { if (m_hardware_info.empty()) { + std::lock_guard lock(write_mtx_); get_hardware_info(); } return m_hardware_info; @@ -22,6 +24,7 @@ class RuntimeInfo { static std::string GetOsInfo() { if (m_os_info.empty()) { + std::lock_guard lock(write_mtx_); get_os_info(); } return m_os_info; @@ -29,11 +32,44 @@ class RuntimeInfo { static std::string GetRuntimeLibraries() { if (m_runtime_libraries.empty()) { + std::lock_guard lock(write_mtx_); get_runtime_libraries(); } return m_runtime_libraries; } + static std::string GetSMBIOSInfo() { + if (smbios_.empty()) { + std::lock_guard lock(write_mtx_); + get_smbios_info(); + } + return smbios_; + } + + static std::string GetCPUInfo() { + if (cpu_.empty()) { + std::lock_guard lock(write_mtx_); + get_cpu_info(); + } + return cpu_; + } + + static std::string GetGPUInfo() { + if (gpu_.empty()) { + std::lock_guard lock(write_mtx_); + get_gpu_info(); + } + return gpu_; + } + + static std::string GetOSInfo() { + if (os_.empty()) { + std::lock_guard lock(write_mtx_); + get_OS_info(); + } + return os_; + } + private: static void get_hardware_info(); @@ -45,6 +81,18 @@ class RuntimeInfo { inline static std::string m_os_info; inline static std::string m_hardware_info; + static void get_smbios_info(bool serial = false); + static void get_cpu_info(); + static void get_gpu_info(); + static void get_OS_info(); + + inline static std::string smbios_; + inline static std::string cpu_; + inline static std::string gpu_; + inline static std::string os_; + + inline static std::mutex write_mtx_; + #ifdef _WIN32 inline static WMIUtil wmi; #endif diff --git a/core/include/mmcore/utility/platform/WMIUtil.h b/core/include/mmcore/utility/platform/WMIUtil.h index 359af1f499..116bde05a0 100644 --- a/core/include/mmcore/utility/platform/WMIUtil.h +++ b/core/include/mmcore/utility/platform/WMIUtil.h @@ -9,6 +9,7 @@ #ifdef _WIN32 #include +#include #define _WIN32_DCOM #include @@ -27,8 +28,10 @@ class WMIUtil { std::string get_value(const std::string& wmi_class, const std::string& attribute); private: - IWbemLocator* locator = nullptr; - IWbemServices* service = nullptr; + //IWbemLocator* locator = nullptr; + //IWbemServices* service = nullptr; + wil::com_ptr service; + //wil::unique_couninitialize_call cleanup; }; } // namespace megamol::core::utility::platform diff --git a/core/src/utility/platform/RuntimeInfo.cpp b/core/src/utility/platform/RuntimeInfo.cpp index efc18611c7..6021df3c2b 100644 --- a/core/src/utility/platform/RuntimeInfo.cpp +++ b/core/src/utility/platform/RuntimeInfo.cpp @@ -117,73 +117,79 @@ std::vector dlinfo_linkmap(void* handle) { } // namespace void megamol::core::utility::platform::RuntimeInfo::get_hardware_info() { + if (m_hardware_info.empty()) { #ifdef _WIN32 - //m_hardware_info = execute("systeminfo"); - std::stringstream s; - s << "{" << std::endl; - s << R"("Processor Name":")" << wmi.get_value("Win32_Processor", "Name") << "\"," << std::endl; - s << R"("Processor Version":")" << wmi.get_value("Win32_Processor", "Version") << "\"," << std::endl; - s << R"("GPU Name":")" << wmi.get_value("Win32_VideoController", "Name") << "\"," << std::endl; - s << R"("OS Name":")" << wmi.get_value("Win32_OperatingSystem", "Name") << "\"," << std::endl; - s << R"("OS Version":")" << wmi.get_value("Win32_OperatingSystem", "Version") << "\"," << std::endl; - s << R"("OS Architecture":")" << wmi.get_value("Win32_OperatingSystem", "OSArchitecture") << "\"," << std::endl; - s << R"("Available Memory":")" << wmi.get_value("Win32_OperatingSystem", "TotalVisibleMemorySize") << "\"" - << std::endl; - s << "}"; - m_hardware_info = s.str(); + //m_hardware_info = execute("systeminfo"); + std::stringstream s; + s << "{" << std::endl; + s << R"("Processor Name":")" << wmi.get_value("Win32_Processor", "Name") << "\"," << std::endl; + s << R"("Processor Version":")" << wmi.get_value("Win32_Processor", "Version") << "\"," << std::endl; + s << R"("GPU Name":")" << wmi.get_value("Win32_VideoController", "Name") << "\"," << std::endl; + s << R"("OS Name":")" << wmi.get_value("Win32_OperatingSystem", "Name") << "\"," << std::endl; + s << R"("OS Version":")" << wmi.get_value("Win32_OperatingSystem", "Version") << "\"," << std::endl; + s << R"("OS Architecture":")" << wmi.get_value("Win32_OperatingSystem", "OSArchitecture") << "\"," << std::endl; + s << R"("Available Memory":")" << wmi.get_value("Win32_OperatingSystem", "TotalVisibleMemorySize") << "\"" + << std::endl; + s << "}"; + m_hardware_info = s.str(); #else - m_hardware_info = execute("cat /proc/cpuinfo /proc/meminfo"); + m_hardware_info = execute("cat /proc/cpuinfo /proc/meminfo"); #endif + } } void megamol::core::utility::platform::RuntimeInfo::get_runtime_libraries() { + if (m_runtime_libraries.empty()) { #ifdef _WIN32 - HANDLE h_mod_snap = INVALID_HANDLE_VALUE; - h_mod_snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); - if (h_mod_snap != INVALID_HANDLE_VALUE) { - std::stringstream out; - MODULEENTRY32 me32; - me32.dwSize = sizeof(MODULEENTRY32); - if (Module32First(h_mod_snap, &me32)) { - do { - out << me32.szExePath << " ("; - out << get_file_version(me32.szExePath) << ")" << std::endl; - } while (Module32Next(h_mod_snap, &me32)); + HANDLE h_mod_snap = INVALID_HANDLE_VALUE; + h_mod_snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); + if (h_mod_snap != INVALID_HANDLE_VALUE) { + std::stringstream out; + MODULEENTRY32 me32; + me32.dwSize = sizeof(MODULEENTRY32); + if (Module32First(h_mod_snap, &me32)) { + do { + out << me32.szExePath << " ("; + out << get_file_version(me32.szExePath) << ")" << std::endl; + } while (Module32Next(h_mod_snap, &me32)); + } + CloseHandle(h_mod_snap); + m_runtime_libraries = out.str(); + } else { + m_runtime_libraries = ""; } - CloseHandle(h_mod_snap); - m_runtime_libraries = out.str(); - } else { - m_runtime_libraries = ""; - } #else - void* handle = dlopen(nullptr, RTLD_NOW); + void* handle = dlopen(nullptr, RTLD_NOW); - // TODO looks like all library paths are already absolute, do we need search paths here? - // const auto paths = dlinfo_search_path(handle); + // TODO looks like all library paths are already absolute, do we need search paths here? + // const auto paths = dlinfo_search_path(handle); - const auto list = dlinfo_linkmap(handle); + const auto list = dlinfo_linkmap(handle); - std::stringstream out; - for (const auto& lib : list) { - out << lib; - // If the library is a symlink, print link target to get the filename with the full version number. - std::filesystem::path p(lib); - if (std::filesystem::is_symlink(p)) { - p = std::filesystem::canonical(p); - out << " (=> " << p.string() << ")"; + std::stringstream out; + for (const auto& lib : list) { + out << lib; + // If the library is a symlink, print link target to get the filename with the full version number. + std::filesystem::path p(lib); + if (std::filesystem::is_symlink(p)) { + p = std::filesystem::canonical(p); + out << " (=> " << p.string() << ")"; + } + out << std::endl; } - out << std::endl; - } - m_runtime_libraries = out.str(); + m_runtime_libraries = out.str(); #endif + } } void megamol::core::utility::platform::RuntimeInfo::get_os_info() { + if (m_os_info.empty()) { #ifdef _WIN32 - m_os_info = execute("ver"); + m_os_info = execute("ver"); #else - m_os_info = execute("cat /etc/issue"); + m_os_info = execute("cat /etc/issue"); #endif + } } @@ -209,3 +215,80 @@ std::string megamol::core::utility::platform::RuntimeInfo::execute(const std::st return "unable to execute " + cmd; } } + + +void megamol::core::utility::platform::RuntimeInfo::get_smbios_info(bool serial) { + if (smbios_.empty()) { +#ifdef _WIN32 + std::stringstream s; + s << "{" << std::endl; + s << R"("Manufacturer":")" << wmi.get_value("Win32_BaseBoard", "Manufacturer") << "\"," << std::endl; + s << R"("Product":")" << wmi.get_value("Win32_BaseBoard", "Product") << "\"," << std::endl; + s << R"("Version":")" << wmi.get_value("Win32_BaseBoard", "Version") << "\"," << std::endl; + if (serial) + s << R"("SerialNumber":")" << wmi.get_value("Win32_BaseBoard", "SerialNumber") << "\"," << std::endl; + s << "}"; + smbios_ = s.str(); +#else + +#endif + } +} + + +void megamol::core::utility::platform::RuntimeInfo::get_cpu_info() { + if (cpu_.empty()) { +#ifdef _WIN32 + std::stringstream s; + s << "{" << std::endl; + s << R"("Manufacturer":")" << wmi.get_value("Win32_Processor", "Manufacturer") << "\"," << std::endl; + s << R"("Name":")" << wmi.get_value("Win32_Processor", "Name") << "\"," << std::endl; + s << R"("ProcessorId":")" << wmi.get_value("Win32_Processor", "ProcessorId") << "\"," << std::endl; + s << R"("NumberOfCores":")" << wmi.get_value("Win32_Processor", "NumberOfCores") << "\"," << std::endl; + s << R"("NumberOfLogicalProcessors":")" << wmi.get_value("Win32_Processor", "NumberOfLogicalProcessors") + << "\"," << std::endl; + s << R"("AvailableRam":")" << wmi.get_value("Win32_OperatingSystem", "TotalVisibleMemorySize") << "\"," + << std::endl; + s << "}"; + cpu_ = s.str(); +#else + +#endif + } +} + + +void megamol::core::utility::platform::RuntimeInfo::get_gpu_info() { + if (gpu_.empty()) { +#ifdef _WIN32 + std::stringstream s; + s << "{" << std::endl; + s << R"("Name":")" << wmi.get_value("Win32_VideoController", "Name") << "\"," << std::endl; + s << R"("DriverVersion":")" << wmi.get_value("Win32_VideoController", "DriverVersion") << "\"," << std::endl; + s << R"("AdapterRam":")" << wmi.get_value("Win32_VideoController", "AdapterRam") << "\"," << std::endl; + s << "}"; + gpu_ = s.str(); +#else + +#endif + } +} + + +void megamol::core::utility::platform::RuntimeInfo::get_OS_info() { + if (os_.empty()) { +#ifdef _WIN32 + std::stringstream s; + s << "{" << std::endl; + s << R"("Name":")" << wmi.get_value("Win32_ComputerSystem", "Name") << "\"," << std::endl; + s << R"("OSName":")" << wmi.get_value("Win32_OperatingSystem", "Name") << "\"," << std::endl; + s << R"("Manufacturer":")" << wmi.get_value("Win32_OperatingSystem", "Manufacturer") << "\"," << std::endl; + s << R"("Version":")" << wmi.get_value("Win32_OperatingSystem", "Version") << "\"," << std::endl; + s << R"("OSArchitecture":")" << wmi.get_value("Win32_OperatingSystem", "OSArchitecture") << "\"," << std::endl; + s << "}"; + os_ = s.str(); +#else + +#endif + } +} diff --git a/core/src/utility/platform/WMIUtil.cpp b/core/src/utility/platform/WMIUtil.cpp index 8d88a7d2a8..a32fd61898 100644 --- a/core/src/utility/platform/WMIUtil.cpp +++ b/core/src/utility/platform/WMIUtil.cpp @@ -10,21 +10,25 @@ #ifdef _WIN32 +#include +#include + megamol::core::utility::platform::WMIUtil::WMIUtil() { HRESULT hres; // Step 1: -------------------------------------------------- // Initialize COM. ------------------------------------------ - - hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + auto cleanup = wil::CoInitializeEx(COINIT_MULTITHREADED); + //hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED); + /*hres = CoInitializeEx(nullptr, COINIT_MULTITHREADED); if (FAILED(hres)) { megamol::core::utility::log::Log::DefaultLog.WriteWarn( "WMIUtil: Failed to initialize COM library. Is COM already initialized? Error code = %#010X", hres); - } + }*/ // Step 2: -------------------------------------------------- // Set general COM security levels -------------------------- - + hres = CoInitializeSecurity(nullptr, -1, // COM authentication nullptr, // Authentication services @@ -40,22 +44,26 @@ megamol::core::utility::platform::WMIUtil::WMIUtil() { if (FAILED(hres)) { megamol::core::utility::log::Log::DefaultLog.WriteError( "WMIUtil: Failed to initialize security. Error code = %#010X", hres); - CoUninitialize(); + //CoUninitialize(); return; } // Step 3: --------------------------------------------------- // Obtain the initial locator to WMI ------------------------- + auto locator = wil::CoCreateInstance(CLSID_WbemLocator, CLSCTX_INPROC_SERVER); + /*hres = CoCreateInstance( + CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast(&locator));*/ - hres = CoCreateInstance( - CLSID_WbemLocator, nullptr, CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast(&locator)); - - if (FAILED(hres)) { + if (!locator) { + megamol::core::utility::log::Log::DefaultLog.WriteError("WMIUtil: Failed to create IWbemLocator object."); + return; + } + /*if (FAILED(hres)) { megamol::core::utility::log::Log::DefaultLog.WriteError( "WMIUtil: Failed to create IWbemLocator object. Error code = %#010X", hres); CoUninitialize(); return; - } + }*/ // Step 4: ----------------------------------------------------- // Connect to WMI through the IWbemLocator::ConnectServer method @@ -76,9 +84,9 @@ megamol::core::utility::platform::WMIUtil::WMIUtil() { if (FAILED(hres)) { megamol::core::utility::log::Log::DefaultLog.WriteError( "WMIUtil: Could not connect. Error code = %#010X", hres); - locator->Release(); - locator = nullptr; - CoUninitialize(); + //locator->Release(); + //locator = nullptr; + //CoUninitialize(); return; } @@ -86,8 +94,8 @@ megamol::core::utility::platform::WMIUtil::WMIUtil() { // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- - - hres = CoSetProxyBlanket(service, // Indicates the proxy to set + + hres = CoSetProxyBlanket(service.get(), // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx nullptr, // Server principal name @@ -100,23 +108,26 @@ megamol::core::utility::platform::WMIUtil::WMIUtil() { if (FAILED(hres)) { megamol::core::utility::log::Log::DefaultLog.WriteError( "WMIUtil: Could not set proxy blanket. Error code = %#010X", hres); - service->Release(); - service = nullptr; - locator->Release(); - locator = nullptr; - CoUninitialize(); + //service->Release(); + //service = nullptr; + //locator->Release(); + //locator = nullptr; + //CoUninitialize(); return; } + + cleanup.release(); } megamol::core::utility::platform::WMIUtil::~WMIUtil() { // Cleanup // ======== - if (service) - service->Release(); - if (locator) - locator->Release(); + /*if (service) + service->Release();*/ + /*if (locator) + locator->Release();*/ + service.reset(); CoUninitialize(); } @@ -165,12 +176,20 @@ std::string megamol::core::utility::platform::WMIUtil::get_value( // Get the value of the Name property hr = pclsObj->Get(ws_attribute, 0, &vtProp, nullptr, nullptr); - auto wslen = ::SysStringLen(vtProp.bstrVal); - auto len = ::WideCharToMultiByte(CP_ACP, 0, vtProp.bstrVal, wslen, nullptr, 0, nullptr, nullptr); - std::string dblstr(len, '\0'); - len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */, vtProp.bstrVal, wslen /* not necessary NULL-terminated */, - &dblstr[0], len, nullptr, nullptr /* no default char */); - ret = dblstr; + + if (vtProp.vt == VARENUM::VT_BSTR) { + auto wslen = ::SysStringLen(vtProp.bstrVal); + auto len = ::WideCharToMultiByte(CP_ACP, 0, vtProp.bstrVal, wslen, nullptr, 0, nullptr, nullptr); + std::string dblstr(len, '\0'); + len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */, vtProp.bstrVal, + wslen /* not necessary NULL-terminated */, &dblstr[0], len, nullptr, nullptr /* no default char */); + ret = dblstr; + } else if (vtProp.vt == VARENUM::VT_I4) { + ret = std::to_string(vtProp.lVal); + } else { + throw std::runtime_error("WMIUtil: Unsupported ret type"); + } + VariantClear(&vtProp); pclsObj->Release(); From 48652d4b3aa9cbd86bb3e52d412f3647abbfdf5d Mon Sep 17 00:00:00 2001 From: gralkapk Date: Mon, 9 Oct 2023 16:45:52 +0200 Subject: [PATCH 5/8] adapted service --- frontend/resources/include/RuntimeInfo.h | 5 +++ .../RuntimeInfo_Service.cpp | 36 +++++++++++++++++++ .../RuntimeInfo_Service.hpp | 8 +++++ 3 files changed, 49 insertions(+) diff --git a/frontend/resources/include/RuntimeInfo.h b/frontend/resources/include/RuntimeInfo.h index 2ea1040df8..f22528aa4d 100644 --- a/frontend/resources/include/RuntimeInfo.h +++ b/frontend/resources/include/RuntimeInfo.h @@ -8,5 +8,10 @@ struct RuntimeInfo { std::function get_hardware_info; std::function get_os_info; std::function get_runtime_libraries; + + std::function get_smbios_info; + std::function get_cpu_info; + std::function get_gpu_info; + std::function get_OS_info; }; } // namespace megamol::frontend_resources diff --git a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp index 391bbb534a..9df0dc0433 100644 --- a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp +++ b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.cpp @@ -4,6 +4,8 @@ * All rights reserved. */ +#include + // search/replace Template_Service with your class name // you should also delete the FAQ comments in these template files after you read and understood them #include "RuntimeInfo_Service.hpp" @@ -45,8 +47,26 @@ bool RuntimeInfo_Service::init(void* configPtr) { ri_resource_.get_os_info = [&]() { return get_os_info(); }; ri_resource_.get_runtime_libraries = [&]() { return get_runtime_libraries(); }; + ri_resource_.get_smbios_info = [&]() { return get_smbios_info(); }; + ri_resource_.get_cpu_info = [&]() { return get_cpu_info(); }; + ri_resource_.get_gpu_info = [&]() { return get_gpu_info(); }; + ri_resource_.get_OS_info = [&]() { return get_OS_info(); }; + m_providedResourceReferences = {{"RuntimeInfo", ri_resource_}}; + auto t = std::thread([&]() { + //log("(Async) get WMI stuff"); + get_hardware_info(); + get_os_info(); + get_runtime_libraries(); + get_smbios_info(); + get_cpu_info(); + get_gpu_info(); + get_OS_info(); + //log("(Async) finished getting WMI stuff"); + }); + t.detach(); + log("initialized successfully"); return true; } @@ -110,6 +130,22 @@ std::string RuntimeInfo_Service::get_runtime_libraries() { return ri_.GetRuntimeLibraries(); } +std::string RuntimeInfo_Service::get_smbios_info() { + return ri_.GetSMBIOSInfo(); +} + +std::string RuntimeInfo_Service::get_cpu_info() { + return ri_.GetCPUInfo(); +} + +std::string RuntimeInfo_Service::get_gpu_info() { + return ri_.GetGPUInfo(); +} + +std::string RuntimeInfo_Service::get_OS_info() { + return ri_.GetOSInfo(); +} + } // namespace frontend } // namespace megamol diff --git a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp index 7520d034ea..df40d8543d 100644 --- a/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp +++ b/frontend/services/runtimeinfo_service/RuntimeInfo_Service.hpp @@ -145,6 +145,14 @@ class RuntimeInfo_Service final : public AbstractFrontendService { std::string get_runtime_libraries(); + std::string get_smbios_info(); + + std::string get_cpu_info(); + + std::string get_gpu_info(); + + std::string get_OS_info(); + // this can hold references to the resources (i.e. structs) we provide to others, e.g. you may fill this and return it in getProvidedResources() // provided resources will be queried by the system only once, // there is no requirement to store the resources in a vector the whole time, you just need to return such a vector in getProvidedResources() From 2cd8164b19101ff6a44f90fed41265c8b39194dc Mon Sep 17 00:00:00 2001 From: gralkapk Date: Mon, 9 Oct 2023 16:46:06 +0200 Subject: [PATCH 6/8] runtime fix for cinematicview --- plugins/cinematic_gl/src/CinematicView.cpp | 9 +++++++-- plugins/cinematic_gl/src/CinematicView.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/cinematic_gl/src/CinematicView.cpp b/plugins/cinematic_gl/src/CinematicView.cpp index 713ca22ed6..e840b323ec 100644 --- a/plugins/cinematic_gl/src/CinematicView.cpp +++ b/plugins/cinematic_gl/src/CinematicView.cpp @@ -109,8 +109,6 @@ CinematicView::CinematicView() this->addSBSideToNameParam << new param::BoolParam(false); this->MakeSlotAvailable(&this->addSBSideToNameParam); - - ri_ = &frontend_resources.get(); } @@ -533,6 +531,13 @@ ImageWrapper CinematicView::Render(double time, double instanceTime) { } +bool megamol::cinematic_gl::CinematicView::create() { + ri_ = &frontend_resources.get(); + + return View3DGL::create(); +} + + bool CinematicView::render_to_file_setup() { auto ccc = this->keyframeKeeperSlot.CallAs(); diff --git a/plugins/cinematic_gl/src/CinematicView.h b/plugins/cinematic_gl/src/CinematicView.h index d0310136cf..8a6029f55d 100644 --- a/plugins/cinematic_gl/src/CinematicView.h +++ b/plugins/cinematic_gl/src/CinematicView.h @@ -69,6 +69,8 @@ class CinematicView : public mmstd_gl::view::View3DGL { */ ImageWrapper Render(double time, double instanceTime) override; + bool create() override; + private: typedef std::chrono::system_clock::time_point TimePoint_t; From 4ff39070251fcdd343b356e309b18c02a4895ed0 Mon Sep 17 00:00:00 2001 From: MegaMol-Bot Date: Mon, 9 Oct 2023 14:55:21 +0000 Subject: [PATCH 7/8] Format fix. --- .../mmcore/utility/platform/RuntimeInfo.h | 2 +- core/src/utility/platform/WMIUtil.cpp | 20 +++++++++---------- frontend/main/src/main.cpp | 2 +- frontend/resources/include/Screenshots.h | 9 ++++++--- plugins/cinematic_gl/src/CinematicView.h | 2 +- .../include/mmstd_gl/special/ScreenShooter.h | 2 +- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/core/include/mmcore/utility/platform/RuntimeInfo.h b/core/include/mmcore/utility/platform/RuntimeInfo.h index f6b053f4b6..a2591c7c7b 100644 --- a/core/include/mmcore/utility/platform/RuntimeInfo.h +++ b/core/include/mmcore/utility/platform/RuntimeInfo.h @@ -5,8 +5,8 @@ */ #pragma once -#include #include +#include #include "WMIUtil.h" diff --git a/core/src/utility/platform/WMIUtil.cpp b/core/src/utility/platform/WMIUtil.cpp index a32fd61898..c0e202ef84 100644 --- a/core/src/utility/platform/WMIUtil.cpp +++ b/core/src/utility/platform/WMIUtil.cpp @@ -10,8 +10,8 @@ #ifdef _WIN32 -#include #include +#include megamol::core::utility::platform::WMIUtil::WMIUtil() { HRESULT hres; @@ -28,7 +28,7 @@ megamol::core::utility::platform::WMIUtil::WMIUtil() { // Step 2: -------------------------------------------------- // Set general COM security levels -------------------------- - + hres = CoInitializeSecurity(nullptr, -1, // COM authentication nullptr, // Authentication services @@ -94,15 +94,15 @@ megamol::core::utility::platform::WMIUtil::WMIUtil() { // Step 5: -------------------------------------------------- // Set security levels on the proxy ------------------------- - + hres = CoSetProxyBlanket(service.get(), // Indicates the proxy to set - RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx - RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx - nullptr, // Server principal name - RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx - RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx - nullptr, // client identity - EOAC_NONE // proxy capabilities + RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx + RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx + nullptr, // Server principal name + RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx + RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx + nullptr, // client identity + EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { diff --git a/frontend/main/src/main.cpp b/frontend/main/src/main.cpp index b2b8a14f87..abefae8dcb 100644 --- a/frontend/main/src/main.cpp +++ b/frontend/main/src/main.cpp @@ -19,13 +19,13 @@ #include "ProjectLoader_Service.hpp" #include "Remote_Service.hpp" #include "RuntimeConfig.h" +#include "RuntimeInfo_Service.hpp" #include "Screenshot_Service.hpp" #include "VR_Service.hpp" #include "mmcore/LuaAPI.h" #include "mmcore/MegaMolGraph.h" #include "mmcore/factories/PluginRegister.h" #include "mmcore/utility/log/Log.h" -#include "RuntimeInfo_Service.hpp" #ifdef MEGAMOL_USE_TRACY #include diff --git a/frontend/resources/include/Screenshots.h b/frontend/resources/include/Screenshots.h index e3fdb24cef..48a8c70c1a 100644 --- a/frontend/resources/include/Screenshots.h +++ b/frontend/resources/include/Screenshots.h @@ -57,11 +57,13 @@ class IScreenshotSource { class IImageDataWriter { public: - bool write_screenshot(IScreenshotSource const& image_source, std::filesystem::path const& filename, void const* user_ptr = nullptr) const { + bool write_screenshot(IScreenshotSource const& image_source, std::filesystem::path const& filename, + void const* user_ptr = nullptr) const { return this->write_image(image_source.take_screenshot(), filename, user_ptr); } - virtual bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename, void const* user_ptr = nullptr) const = 0; + virtual bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename, + void const* user_ptr = nullptr) const = 0; ~IImageDataWriter() = default; }; @@ -99,7 +101,8 @@ class GLScreenshotSource : public IScreenshotSource { class ScreenshotImageDataToPNGWriter : public IImageDataWriter { public: - bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename, void const* user_ptr = nullptr) const override; + bool write_image(ScreenshotImageData const& image, std::filesystem::path const& filename, + void const* user_ptr = nullptr) const override; }; diff --git a/plugins/cinematic_gl/src/CinematicView.h b/plugins/cinematic_gl/src/CinematicView.h index 8a6029f55d..b6dc1f7eb2 100644 --- a/plugins/cinematic_gl/src/CinematicView.h +++ b/plugins/cinematic_gl/src/CinematicView.h @@ -12,6 +12,7 @@ #include #include "ModuleGraphSubscription.h" +#include "RuntimeInfo.h" #include "cinematic/Keyframe.h" #include "cinematic_gl/CinematicUtils.h" #include "mmcore/CallerSlot.h" @@ -20,7 +21,6 @@ #include "mmstd_gl/renderer/CallRenderViewGL.h" #include "mmstd_gl/view/View3DGL.h" #include "vislib/sys/FastFile.h" -#include "RuntimeInfo.h" namespace megamol::cinematic_gl { diff --git a/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h b/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h index df35be3612..34e945f829 100644 --- a/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h +++ b/plugins/mmstd_gl/include/mmstd_gl/special/ScreenShooter.h @@ -10,12 +10,12 @@ #include +#include "RuntimeInfo.h" #include "mmcore/MegaMolGraph.h" #include "mmcore/Module.h" #include "mmcore/job/AbstractJob.h" #include "mmcore/param/ParamSlot.h" #include "mmstd/view/AbstractView.h" -#include "RuntimeInfo.h" namespace megamol::mmstd_gl::special { From c72f06eab4e6d157917a70ab8054f095fd9853bc Mon Sep 17 00:00:00 2001 From: gralkapk Date: Tue, 10 Oct 2023 11:14:45 +0200 Subject: [PATCH 8/8] some linux info --- core/src/utility/platform/RuntimeInfo.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/core/src/utility/platform/RuntimeInfo.cpp b/core/src/utility/platform/RuntimeInfo.cpp index 6021df3c2b..f5cbac93d6 100644 --- a/core/src/utility/platform/RuntimeInfo.cpp +++ b/core/src/utility/platform/RuntimeInfo.cpp @@ -230,7 +230,7 @@ void megamol::core::utility::platform::RuntimeInfo::get_smbios_info(bool serial) s << "}"; smbios_ = s.str(); #else - + smbios_ = "SMBIOS info not available"; #endif } } @@ -252,7 +252,7 @@ void megamol::core::utility::platform::RuntimeInfo::get_cpu_info() { s << "}"; cpu_ = s.str(); #else - + cpu_ = execute("cat /proc/cpuinfo /proc/meminfo"); #endif } } @@ -269,7 +269,7 @@ void megamol::core::utility::platform::RuntimeInfo::get_gpu_info() { s << "}"; gpu_ = s.str(); #else - + gpu_ = "GPU info not available"; #endif } } @@ -288,7 +288,13 @@ void megamol::core::utility::platform::RuntimeInfo::get_OS_info() { s << "}"; os_ = s.str(); #else - + std::stringstream s; + s << "{" << std::endl; + s << R"("Name":")" << execute("cat /proc/sys/kernel/hostname") << "\"," << std::endl; + s << R"("OSName":")" << execute("cat /etc/issue") << "\"," << std::endl; + s << R"("Version":")" << execute("cat /proc/sys/kernel/osrelease") << "\"," << std::endl; + s << "}"; + os_ = s.str(); #endif } }