LCOV - code coverage report
Current view: top level - muse/framework/global - globalmodule.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 71.0 % 107 76
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "globalmodule.h"
      23              : 
      24              : #include "muse_framework_config.h"
      25              : 
      26              : #include "modularity/ioc.h"
      27              : #include "internal/globalconfiguration.h"
      28              : 
      29              : #include "logger.h"
      30              : #include "logremover.h"
      31              : #include "profiler.h"
      32              : 
      33              : #include "internal/baseapplication.h"
      34              : #include "internal/cryptographichash.h"
      35              : #include "internal/process.h"
      36              : #include "internal/systeminfo.h"
      37              : #include "internal/tickerprovider.h"
      38              : 
      39              : #ifndef NO_QT_SUPPORT
      40              : #include "internal/applicationeventcontroller.h"
      41              : #endif
      42              : 
      43              : #include "runtime.h"
      44              : #include "async/processevents.h"
      45              : 
      46              : #include "settings.h"
      47              : 
      48              : #include "io/dir.h"
      49              : 
      50              : #include "api/internal/apiregister.h"
      51              : #include "api/internal/filesystemapirestriction.h"
      52              : #include "api/iapiregister.h"
      53              : #include "api/logapi.h"
      54              : #include "api/filesystemapi.h"
      55              : #include "api/processapi.h"
      56              : 
      57              : #include "muse_framework_config.h"
      58              : 
      59              : #ifdef MUSE_MODULE_DIAGNOSTICS
      60              : #include "diagnostics/idiagnosticspathsregister.h"
      61              : #endif
      62              : 
      63              : #ifdef Q_OS_WASM
      64              : #include "io/internal/memfilesystem.h"
      65              : #else
      66              : #include "io/internal/filesystem.h"
      67              : #endif
      68              : 
      69              : #ifdef Q_OS_WIN
      70              : #include "platform/win/waitabletimer.h"
      71              : #endif
      72              : 
      73              : #include "log.h"
      74              : 
      75              : using namespace muse;
      76              : using namespace muse::modularity;
      77              : using namespace muse::io;
      78              : 
      79           46 : GlobalModule::GlobalModule()
      80              : {
      81           46 : }
      82              : 
      83          460 : std::string GlobalModule::moduleName() const
      84              : {
      85          920 :     return "global";
      86              : }
      87              : 
      88           46 : void GlobalModule::registerExports()
      89              : {
      90           46 :     m_configuration = std::make_shared<GlobalConfiguration>();
      91           46 :     m_systemInfo = std::make_shared<SystemInfo>();
      92           46 :     m_tickerProvider = std::make_shared<TickerProvider>();
      93              : 
      94           46 :     globalIoc()->registerExport<IGlobalConfiguration>(moduleName(), m_configuration);
      95           46 :     globalIoc()->registerExport<ISystemInfo>(moduleName(), m_systemInfo);
      96           46 :     globalIoc()->registerExport<ICryptographicHash>(moduleName(), new CryptographicHash());
      97           46 :     globalIoc()->registerExport<IProcess>(moduleName(), new Process());
      98           46 :     globalIoc()->registerExport<ITickerProvider>(moduleName(), m_tickerProvider);
      99           46 :     globalIoc()->registerExport<api::IApiRegister>(moduleName(), new api::ApiRegister());
     100           46 :     globalIoc()->registerExport<api::IFileSystemApiRestriction>(moduleName(), new api::FileSystemApiRestriction());
     101              : 
     102              : #ifndef NO_QT_SUPPORT
     103           46 :     m_eventController = std::make_shared<ApplicationEventController>();
     104           46 :     globalIoc()->registerExport<IApplicationEventController>(moduleName(), m_eventController);
     105              : #endif
     106              : 
     107              : #ifdef Q_OS_WASM
     108              :     globalIoc()->registerExport<IFileSystem>(moduleName(), new MemFileSystem());
     109              : #else
     110           46 :     globalIoc()->registerExport<IFileSystem>(moduleName(), new FileSystem());
     111              : #endif
     112           46 : }
     113              : 
     114            0 : void GlobalModule::registerApi()
     115              : {
     116              :     using namespace muse::api;
     117              : 
     118            0 :     auto api = globalIoc()->resolve<IApiRegister>(moduleName());
     119            0 :     if (api) {
     120            0 :         api->regApiCreator(moduleName(), "MuseApi.Log", new ApiCreator<LogApi>());
     121            0 :         api->regApiCreator(moduleName(), "api.process", new ApiCreator<ProcessApi>());
     122            0 :         api->regApiCreator(moduleName(), "MuseApi.FS", new ApiCreator<FileSystemApi>());
     123              :     }
     124              : 
     125              :     // added fs restrictions
     126            0 :     auto fsRestriction = globalIoc()->resolve<api::IFileSystemApiRestriction>(moduleName());
     127            0 :     if (fsRestriction) {
     128            0 :         fsRestriction->addAllowedPathBase("temp", io::Dir::tempPath());
     129            0 :         fsRestriction->addAllowedPathBase("userData", m_configuration->userDataPath());
     130              :     }
     131            0 : }
     132              : 
     133           46 : void GlobalModule::onPreInit(const IApplication::RunMode& mode)
     134              : {
     135           46 :     muse::runtime::mainThreadId(); //! NOTE Needs only call
     136           46 :     muse::runtime::setThreadName("main");
     137              : 
     138              :     //! NOTE: settings must be inited before initialization of any module
     139              :     //! because modules can use settings at the moment of their initialization
     140           46 :     settings()->load();
     141              : 
     142              :     //! --- Setup logger ---
     143              :     using namespace muse::logger;
     144           46 :     Logger* logger = Logger::instance();
     145           46 :     logger->clearDests();
     146              : 
     147              :     //! Console
     148           46 :     if (mode == IApplication::RunMode::GuiApp || muse::runtime::isDebug()) {
     149          138 :         logger->addDest(new ConsoleLogDest(LogLayout("${time} | ${type|5} | ${thread|15} | ${tag|15} | ${message}")));
     150              :     }
     151              : 
     152              :     //! Log file
     153           46 :     io::path_t logFilePath = "none";
     154              : #ifndef MUSE_CONFIGURATION_IS_WEB
     155           46 :     io::path_t logPath = m_configuration->userAppDataPath() + "/logs";
     156           46 :     fileSystem()->makePath(logPath);
     157              : 
     158           46 :     logFilePath = logPath;
     159           46 :     String logFileNamePattern;
     160              : 
     161           46 :     if (mode == IApplication::RunMode::AudioPluginRegistration) {
     162            0 :         logFileNamePattern = u"audiopluginregistration_yyMMdd.log";
     163              : 
     164              :         //! This creates a file named "data/logs/audiopluginregistration_yyMMdd.log"
     165              :         logFilePath += "/audiopluginregistration_"
     166            0 :                        + QDateTime::currentDateTime().toString("yyMMdd")
     167            0 :                        + ".log";
     168              :     } else {
     169           46 :         logFileNamePattern = BaseApplication::appName() + u"_yyMMdd_HHmmss.log";
     170              : 
     171              :         //! This creates a file named "data/logs/AppName_yyMMdd_HHmmss.log"
     172           92 :         logFilePath += u"/" + BaseApplication::appName() + u"_"
     173          184 :                        + String::fromQString(QDateTime::currentDateTime().toString("yyMMdd_HHmmss"))
     174           92 :                        + u".log";
     175              :     }
     176              : 
     177              :     //! Remove old logs
     178           46 :     LogRemover::removeLogs(logPath, 7, logFileNamePattern);
     179              : 
     180              :     FileLogDest* logFile = new FileLogDest(logFilePath.toStdString(),
     181           92 :                                            LogLayout("${datetime} | ${type|5} | ${thread|15} | ${tag|15} | ${message}"));
     182              : 
     183           46 :     logger->addDest(logFile);
     184           46 :     LOGI() << "log path: " << logFilePath;
     185              : #endif // end of not MUSE_CONFIGURATION_IS_WEB
     186              : 
     187           46 :     if (m_loggerLevel) {
     188            0 :         logger->setLevel(m_loggerLevel.value());
     189              :     } else {
     190              : #ifdef MUSE_MODULE_GLOBAL_LOGGER_DEBUGLEVEL
     191           46 :         logger->setLevel(muse::logger::Level::Debug);
     192              : #else
     193              :         logger->setLevel(muse::logger::Level::Normal);
     194              : #endif
     195              :     }
     196              : 
     197           46 :     auto application = globalIoc()->resolve<IApplication>("global");
     198           46 :     if (application) {
     199           92 :         LOGI() << "=== Started " << application->title()
     200           92 :                << " " << application->fullVersion().toString()
     201           46 :                << ", build: " << application->build() << " ===";
     202              :     }
     203              : 
     204              :     //! --- Setup profiler ---
     205              :     using namespace muse::profiler;
     206              :     struct MyPrinter : public Profiler::Printer
     207              :     {
     208            2 :         void printDebug(const std::string& str) override { LOG_STREAM(Logger::DEBG, "Profiler", logger::Color::Magenta)() << str; }
     209           46 :         void printInfo(const std::string& str) override { LOG_STREAM(Logger::INFO, "Profiler", logger::Color::Magenta)() << str; }
     210              :     };
     211              : 
     212           46 :     Profiler::Options profOpt;
     213           46 :     profOpt.stepTimeEnabled = true;
     214           46 :     profOpt.timersEnabled = true;
     215           46 :     profOpt.funcsTimeEnabled = true;
     216           46 :     profOpt.funcsTraceEnabled = false;
     217           46 :     profOpt.funcsMaxThreadCount = 100;
     218           46 :     profOpt.statTopCount = 150;
     219              : 
     220           46 :     Profiler* profiler = Profiler::instance();
     221           46 :     profiler->setup(profOpt, new MyPrinter());
     222              : 
     223              :     //! --- Setup Ticker ---
     224           46 :     m_tickerProvider->start();
     225              : 
     226              :     //! --- Setup Async ---
     227           46 :     const std::thread::id thisThId = std::this_thread::get_id();
     228           46 :     m_asyncTicker.start(1, [thisThId]() {
     229          185 :         async::processMessages(thisThId);
     230          185 :     }, Ticker::Mode::Repeat);
     231              : 
     232              :     //! --- Diagnostics ---
     233              : #ifdef MUSE_MODULE_DIAGNOSTICS
     234           46 :     auto pr = globalIoc()->resolve<muse::diagnostics::IDiagnosticsPathsRegister>(moduleName());
     235           46 :     if (pr) {
     236            0 :         pr->reg("appBinPath", m_configuration->appBinPath());
     237            0 :         pr->reg("appBinDirPath", m_configuration->appBinDirPath());
     238            0 :         pr->reg("appDataPath", m_configuration->appDataPath());
     239            0 :         pr->reg("appConfigPath", m_configuration->appConfigPath());
     240            0 :         pr->reg("userAppDataPath", m_configuration->userAppDataPath());
     241            0 :         pr->reg("userBackupPath", m_configuration->userBackupPath());
     242            0 :         pr->reg("userDataPath", m_configuration->userDataPath());
     243            0 :         pr->reg("log file", logFilePath);
     244            0 :         pr->reg("settings file", settings()->filePath());
     245              :     }
     246              : #endif
     247           46 : }
     248              : 
     249           46 : void GlobalModule::onInit(const IApplication::RunMode&)
     250              : {
     251           46 :     m_configuration->init();
     252           46 :     m_systemInfo->init();
     253              : 
     254           46 :     m_endTimePeriod = false;
     255              : 
     256              : #ifdef Q_OS_WIN
     257              :     WaitableTimer timer;
     258              :     if (m_configuration->highResolutionTimers() || !timer.init()) {
     259              :         // Improves the accuracy of Sleep() on Windows
     260              :         // Without it, errors up to 15 ms are possible, which is critical for the audio thread
     261              :         // and can significantly degrade sound quality
     262              :         // However, this approach may result in higher CPU usage as a trade-off
     263              :         LOGI() << "Use timeBeginPeriod(1)";
     264              :         timeBeginPeriod(1);
     265              :         m_endTimePeriod = true;
     266              :     }
     267              : #endif
     268           46 : }
     269              : 
     270           46 : void GlobalModule::onDeinit()
     271              : {
     272           46 :     m_tickerProvider->stop();
     273           46 :     muse::async::terminate();
     274              : 
     275              : #ifdef Q_OS_WIN
     276              :     if (m_endTimePeriod) {
     277              :         timeEndPeriod(1);
     278              :     }
     279              : #endif
     280           46 : }
     281              : 
     282            0 : void GlobalModule::setLoggerLevel(const muse::logger::Level& level)
     283              : {
     284            0 :     m_loggerLevel = level;
     285            0 : }
     286              : 
     287            0 : IContextSetup* GlobalModule::newContext(const kors::modularity::ContextPtr& ctx) const
     288              : {
     289            0 :     return new GlobalContext(ctx);
     290              : }
     291              : 
     292            0 : void GlobalContext::registerExports()
     293              : {
     294            0 : }
        

Generated by: LCOV version 2.0-1