1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Rosegarden
5 A MIDI and audio sequencer and musical notation editor.
6 Copyright 2000-2021 the Rosegarden development team.
7
8 Other copyrights also apply to some parts of this work. Please
9 see the AUTHORS file and individual file headers for details.
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2 of the
14 License, or (at your option) any later version. See the file
15 COPYING included with this distribution for more information.
16 */
17
18
19 #define RG_MODULE_STRING "[StartupTester]"
20
21 #include "StartupTester.h"
22
23 #include "misc/Strings.h"
24 #include "misc/Debug.h"
25 #include "gui/dialogs/LilyPondOptionsDialog.h"
26 #include "gui/editors/notation/NoteFontFactory.h"
27
28 #include "rosegarden-version.h"
29
30 #include <QNetworkAccessManager>
31 #include <QNetworkReply>
32 #include <QProcess>
33 #include <QMutex>
34 #include <QThread>
35 #include <QRegularExpression>
36
37
38 namespace Rosegarden
39 {
40
StartupTester()41 StartupTester::StartupTester() :
42 // m_proc(nullptr),
43 m_ready(false),
44 m_haveAudioFileImporter(false)
45 // m_versionHttpFailed(false)
46 {
47 QUrl url;
48 url.setScheme("http");
49 url.setHost("www.rosegardenmusic.com");
50 url.setPath("/latest-version.txt");
51
52 network = new QNetworkAccessManager(this);
53 network->get(QNetworkRequest(url));
54 RG_DEBUG << "StartupTester::StartupTester(): URL: " << url.toString();
55
56 connect(network, &QNetworkAccessManager::finished,
57 this, &StartupTester::slotNetworkFinished);
58 }
59
~StartupTester()60 StartupTester::~StartupTester()
61 {
62 }
63
64 void
run()65 StartupTester::run() {
66 m_runningMutex.lock();
67 m_ready = true;
68
69 m_haveAudioFileImporter = true;
70 NoteFontFactory::getFontNames(true);
71
72 // unlock this as the very last thing we do in this thread,
73 // so the parent process knows the thread is completed
74 m_runningMutex.unlock();
75 }
76
77 bool
isReady()78 StartupTester::isReady()
79 {
80 while (!m_ready) usleep(10000);
81 if (m_runningMutex.tryLock()) {
82 m_runningMutex.unlock();
83 } else {
84 return false;
85 }
86 return true;
87 }
88
89 #if 0
90 void
91 StartupTester::stdoutReceived()
92 {
93 m_stdoutBuffer.append(m_proc->readAllStandardOutput());
94 }
95
96 void
97 StartupTester::parseStdoutBuffer(QStringList &target)
98 {
99 QRegularExpression re("Required: ([^\n]*)");
100 QRegularExpressionMatch match = re.match(m_stdoutBuffer);
101 if (match.hasMatch()) {
102 target = match.captured(1).split(", ");
103 }
104 }
105 #endif
106
107 bool
haveAudioFileImporter(QStringList * missing)108 StartupTester::haveAudioFileImporter(QStringList *missing)
109 {
110 while (!m_ready)
111 usleep(10000);
112 QMutexLocker locker(&m_audioFileImporterMutex);
113 if (missing) *missing = m_audioFileImporterMissing;
114 return m_haveAudioFileImporter;
115 }
116
117 bool
isVersionNewerThan(QString a,QString b)118 StartupTester::isVersionNewerThan(QString a, QString b)
119 {
120 QRegularExpression re("[._-]");
121 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
122 QStringList alist = a.split(re, Qt::SkipEmptyParts);
123 QStringList blist = b.split(re, Qt::SkipEmptyParts);
124 #else
125 QStringList alist = a.split(re, QString::SkipEmptyParts);
126 QStringList blist = b.split(re, QString::SkipEmptyParts);
127 #endif
128 int ae = alist.size();
129 int be = blist.size();
130 int e = std::max(ae, be);
131 for (int i = 0; i < e; ++i) {
132 int an = 0, bn = 0;
133 if (i < ae) {
134 an = alist[i].toInt();
135 if (an == 0) an = -1; // non-numeric field -> "-pre1" etc
136 }
137 if (i < be) {
138 bn = blist[i].toInt();
139 if (bn == 0) bn = -1;
140 }
141 if (an < bn) return false;
142 if (an > bn) return true;
143 }
144 return false;
145 }
146
147 void
slotNetworkFinished(QNetworkReply * reply)148 StartupTester::slotNetworkFinished(QNetworkReply *reply)
149 {
150 reply->deleteLater();
151 network->deleteLater();
152
153 if (reply->error() != QNetworkReply::NoError) {
154 // m_versionHttpFailed = true;
155 RG_WARNING << "StartupTester::slotNetworkFinished(): Connection failed: " << reply->errorString();
156 return;
157 }
158
159 QByteArray responseData = reply->readAll();
160 QString str = QString::fromUtf8(responseData.data());
161 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
162 QStringList lines = str.split('\n', Qt::SkipEmptyParts);
163 #else
164 QStringList lines = str.split('\n', QString::SkipEmptyParts);
165 #endif
166 if (lines.empty()) return;
167
168 QString latestVersion = lines[0];
169 RG_DEBUG << "StartupTester::slotNetworkFinished(): Comparing current version \"" << VERSION
170 << "\" with latest version \"" << latestVersion << "\"";
171 if (isVersionNewerThan(latestVersion, VERSION)) {
172 emit newerVersionAvailable(latestVersion);
173 }
174 }
175
176 }
177
178
179