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 : }
|