LCOV - code coverage report
Current view: top level - src/musesounds/internal - musesamplercheckstatusservice.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 98.2 % 56 55
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) 2025 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              : 
      23              : #include "musesamplercheckstatusservice.h"
      24              : 
      25              : #include <QBuffer>
      26              : 
      27              : #include "global/serialization/json.h"
      28              : #include "global/types/version.h"
      29              : 
      30              : using namespace muse;
      31              : using namespace mu::musesounds;
      32              : using namespace muse::network;
      33              : using namespace muse::async;
      34              : 
      35            5 : static RetVal<Version> parseVersion(const QByteArray& json)
      36              : {
      37            5 :     std::string err;
      38            5 :     const ByteArray ba = ByteArray::fromQByteArrayNoCopy(json);
      39            5 :     const JsonDocument doc = JsonDocument::fromJson(ba, &err);
      40            5 :     if (!err.empty() || !doc.isObject()) {
      41            1 :         return RetVal<Version>::make_ret(int(Ret::Code::UnknownError), err);
      42              :     }
      43              : 
      44            4 :     const JsonObject rootObj = doc.rootObject();
      45           12 :     const JsonObject dataObj = rootObj.value("data").toObject();
      46           12 :     const JsonObject productObj = dataObj.value("product").toObject();
      47           12 :     const JsonArray assetsArray = productObj.value("assets").toArray();
      48              : 
      49            4 :     if (assetsArray.empty()) {
      50            2 :         return RetVal<Version>::make_ret(int(Ret::Code::UnknownError), "Invalid JSON format");
      51              :     }
      52              : 
      53            3 :     const JsonObject firstAsset = assetsArray.at(0).toObject();
      54            9 :     const String versionStr = firstAsset.value("version").toString();
      55            3 :     const Version version(versionStr);
      56              : 
      57            3 :     return RetVal<Version>::make_ok(version);
      58            5 : }
      59              : 
      60            2 : bool MuseSamplerCheckStatusService::libInitFailed() const
      61              : {
      62            2 :     return museSampler() && museSampler()->initFailed();
      63              : }
      64              : 
      65            2 : bool MuseSamplerCheckStatusService::canCheckForUpdate() const
      66              : {
      67            2 :     return museSampler() && !museSampler()->version().isNull();
      68              : }
      69              : 
      70            3 : bool MuseSamplerCheckStatusService::incompatibleLocalVersion() const
      71              : {
      72            3 :     if (!museSampler()) {
      73            0 :         return true;
      74              :     }
      75              : 
      76            3 :     return museSampler()->version() < museSamplerConfiguration()->minSupportedVersion();
      77              : }
      78              : 
      79            8 : Promise<RetVal<bool> > MuseSamplerCheckStatusService::checkForUpdate()
      80              : {
      81            8 :     const Version localVersion = museSampler() ? museSampler()->version() : Version();
      82              : 
      83           16 :     return Promise<RetVal<bool> >([this, localVersion](auto resolve, auto) {
      84            8 :         if (localVersion.isNull()) {
      85            1 :             RetVal<bool> result;
      86            1 :             result.ret = Ret(int(Ret::Code::UnknownError), "Unable to obtain the local MuseSampler version");
      87            1 :             result.val = false;
      88            1 :             return resolve(result);
      89            1 :         }
      90              : 
      91            7 :         auto queryBuffer = std::make_shared<QBuffer>();
      92            7 :         queryBuffer->setData(configuration()->getMuseSamplerVersionQuery().toUtf8());
      93            7 :         auto receivedData = std::make_shared<QBuffer>();
      94              : 
      95            7 :         if (!m_networkManager) {
      96            7 :             m_networkManager = networkManagerCreator()->makeNetworkManager();
      97              :         }
      98              : 
      99           14 :         RetVal<Progress> progress = m_networkManager->post(configuration()->checkForMuseSamplerUpdateUrl(),
     100              :                                                            queryBuffer, receivedData,
     101           14 :                                                            configuration()->headers());
     102            7 :         if (!progress.ret) {
     103            1 :             return resolve(RetVal<bool>::make_ret(progress.ret));
     104              :         }
     105              : 
     106           12 :         progress.val.finished().onReceive(this, [receivedData, localVersion, resolve](const ProgressResult& res) {
     107            6 :             RetVal<bool> result = RetVal<bool>::make_ok(false);
     108              : 
     109            6 :             if (res.ret) {
     110            5 :                 const RetVal<Version> version = parseVersion(receivedData->data());
     111            5 :                 result.ret = version.ret;
     112            5 :                 result.val = localVersion < version.val;
     113            5 :             } else {
     114            1 :                 result.ret = res.ret;
     115              :             }
     116              : 
     117            6 :             (void)resolve(result);
     118            6 :         });
     119              : 
     120            6 :         return Promise<RetVal<bool> >::dummy_result();
     121           31 :     });
     122            8 : }
        

Generated by: LCOV version 2.0-1