Audacity 3.2.0
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | List of all members
UpdateManager Class Referencefinal

A class that managing of updates. More...

#include <UpdateManager.h>

Inheritance diagram for UpdateManager:
[legend]
Collaboration diagram for UpdateManager:
[legend]

Public Member Functions

 UpdateManager ()=default
 
void GetUpdates (bool ignoreNetworkErrors, bool configurableNotification)
 
VersionPatch GetVersionPatch () const
 

Static Public Member Functions

static UpdateManagerGetInstance ()
 
static void Start (bool suppressModal)
 

Private Member Functions

void OnTimer (wxTimerEvent &event)
 
bool IsTimeForUpdatesChecking ()
 Scheduling update time for avoiding multiplying update notifications. More...
 

Private Attributes

UpdateDataParser mUpdateDataParser
 
VersionPatch mVersionPatch
 
wxTimer mTimer
 
std::unique_ptr< BasicUI::ProgressDialogmProgressDialog
 
std::string mAudacityInstallerPath
 
std::ofstream mAudacityInstaller
 
std::mutex mUpdateMutex
 
bool mOnProgress { false }
 

Detailed Description

A class that managing of updates.

Opt-in request and show update dialog by the scheduled time. Have a built-in check that allows avoiding multiplying update notifications when multiple Audacity windows are shown.

Definition at line 33 of file UpdateManager.h.

Constructor & Destructor Documentation

◆ UpdateManager()

UpdateManager::UpdateManager ( )
default

Member Function Documentation

◆ GetInstance()

UpdateManager & UpdateManager::GetInstance ( )
static

Definition at line 53 of file UpdateManager.cpp.

54{
55 static UpdateManager updateManager;
56
57 return updateManager;
58}
A class that managing of updates.
Definition: UpdateManager.h:34

Referenced by Start().

Here is the caller graph for this function:

◆ GetUpdates()

void UpdateManager::GetUpdates ( bool  ignoreNetworkErrors,
bool  configurableNotification 
)

Definition at line 92 of file UpdateManager.cpp.

93{
94 const audacity::network_manager::Request request("https://updates.audacityteam.org/feed/latest.xml");
96
97 response->setRequestFinishedCallback([response, ignoreNetworkErrors, configurableNotification, this](audacity::network_manager::IResponse*) {
98
99 // We don't' want to duplicate the updates checking if that already launched.
100 {
101 std::lock_guard<std::mutex> lock(mUpdateMutex);
102 if (mOnProgress)
103 {
104 response->abort();
105 return;
106 }
107 mOnProgress = true;
108 }
109
110 using namespace BasicUI;
111 auto gAudioIO = AudioIO::Get();
112 if (response->getError() != audacity::network_manager::NetworkError::NoError)
113 {
114 if (!ignoreNetworkErrors)
115 {
116 gAudioIO->CallAfterRecording([] {ShowErrorDialog( {},
117 XC("Error checking for update", "update dialog"),
118 XC("Unable to connect to Audacity update server.", "update dialog"),
119 wxString(),
120 ErrorDialogOptions{ ErrorDialogType::ModalErrorReport });
121 });
122 }
123
124 mOnProgress = false;
125 return;
126 }
127
129 {
130 if (!ignoreNetworkErrors)
131 {
132 gAudioIO->CallAfterRecording([] {ShowErrorDialog( {},
133 XC("Error checking for update", "update dialog"),
134 XC("Update data was corrupted.", "update dialog"),
135 wxString(),
136 ErrorDialogOptions{ ErrorDialogType::ModalErrorReport });
137 });
138 }
139
140 mOnProgress = false;
141 return;
142 }
143
144#if UPDATE_LOCAL_TESTING == 0
146#endif
147 {
148 gAudioIO->CallAfterRecording([this, ignoreNetworkErrors, configurableNotification] {
149 UpdatePopupDialog dlg(nullptr, mVersionPatch, configurableNotification);
150 const int code = dlg.ShowModal();
151
152 if (code == wxID_YES)
153 {
154 const audacity::network_manager::Request downloadRequest(mVersionPatch.download.ToStdString());
155 auto downloadResponse = audacity::network_manager::NetworkManager::GetInstance().doGet(downloadRequest);
156
157 // Called once, when downloading is real will finish.
158 downloadResponse->setRequestFinishedCallback([downloadResponse, ignoreNetworkErrors, this](audacity::network_manager::IResponse*) {
159 // First - close all opened resources.
160 wxTheApp->CallAfter([this]{ mProgressDialog.reset(); });
161
162 if (mAudacityInstaller.is_open())
163 mAudacityInstaller.close();
164
165 if (downloadResponse->getError() != audacity::network_manager::NetworkError::NoError)
166 {
167 if (!ignoreNetworkErrors)
168 {
169 wxTheApp->CallAfter([] {ShowErrorDialog( {},
170 XC("Error downloading update", "update dialog"),
171 XC("Can't open the Audacity download link.", "update dialog"),
172 wxString(),
173 ErrorDialogOptions{ ErrorDialogType::ModalErrorReport });
174 });
175 }
176
177 mOnProgress = false;
178 return;
179 }
180
181 const wxPlatformInfo& info = wxPlatformInfo::Get();
182 if ((info.GetOperatingSystemId() & wxOS_WINDOWS) ||
183 info.GetOperatingSystemId() & wxOS_MAC)
184 {
185 if (wxFileName(mAudacityInstallerPath).Exists())
186 {
187 std::string cmd = info.GetOperatingSystemId() & wxOS_MAC ? "Open " + mAudacityInstallerPath : mAudacityInstallerPath;
188 wxTheApp->CallAfter([cmd] { wxExecute(cmd, wxEXEC_ASYNC); });
189 }
190 }
191
192 mOnProgress = false;
193 }
194 );
195
196 auto audacityPatchFilename = wxFileName(mVersionPatch.download).GetName();
197
198 mProgressDialog = BasicUI::MakeProgress(XO("Audacity update"), XO("Downloading %s").Format(audacityPatchFilename));
199 wxASSERT(mProgressDialog);
200
201 wxString installerExtension;
202 const wxPlatformInfo& info = wxPlatformInfo::Get();
203 if (info.GetOperatingSystemId() & wxOS_WINDOWS)
204 installerExtension = "exe";
205 else if(info.GetOperatingSystemId() & wxOS_MAC)
206 installerExtension = "dmg";
207
208 mAudacityInstallerPath = wxFileName(
209 wxStandardPaths::Get().GetUserDir(wxStandardPaths::Dir_Downloads), audacityPatchFilename, installerExtension)
210 .GetFullPath()
211 .ToStdString();
212
213 mAudacityInstaller.open(mAudacityInstallerPath, std::ios::binary);
214
215 // Called each time, since downloading for update progress status.
216 downloadResponse->setDownloadProgressCallback(
217 [this](int64_t current, int64_t expected) {
218
219 wxTheApp->CallAfter([this, current, expected]{
220 if(mProgressDialog != nullptr)
221 mProgressDialog->Poll(current, expected);
222 });
223 }
224 );
225
226 // Called each time, since downloading for get data.
227 downloadResponse->setOnDataReceivedCallback([downloadResponse, this](audacity::network_manager::IResponse*) {
228 if (downloadResponse->getError() == audacity::network_manager::NetworkError::NoError)
229 {
230 std::vector<char> buffer(downloadResponse->getBytesAvailable());
231
232 size_t bytes = downloadResponse->readData(buffer.data(), buffer.size());
233
234 if (mAudacityInstaller.is_open())
235 mAudacityInstaller.write(buffer.data(), buffer.size());
236 }
237 }
238 );
239
240 }
241 else if (code == wxID_NO)
242 {
243 mOnProgress = false;
244 }
245 });
246 }
247#if UPDATE_LOCAL_TESTING == 0
248 else // mVersionPatch.version > CurrentBuildVersion()
249 {
250 // That also shows, that updates checking was called manually from menu.
251 if (!configurableNotification)
252 {
253 gAudioIO->CallAfterRecording([] {
254 NoUpdatesAvailableDialog(nullptr).ShowModal();
255 });
256 }
257
258 mOnProgress = false;
259 }
260#endif
261 });
262}
XO("Cut/Copy/Paste")
#define XC(s, c)
Definition: Internat.h:37
static VersionId CurrentBuildVersion()
Return version (VersionId) object with current Audacity build version.
Definition: VersionId.h:46
static AudioIO * Get()
Definition: AudioIO.cpp:126
Abstract base class used in importing a file.
Information dialog about no updates available, that allows to navigate to settings quickly.
bool Parse(const VersionPatch::UpdateDataFormat &updateData, VersionPatch *versionPatch)
Parsing from update data format to VersionPatch fields.
std::unique_ptr< BasicUI::ProgressDialog > mProgressDialog
Definition: UpdateManager.h:56
std::string mAudacityInstallerPath
Definition: UpdateManager.h:58
std::mutex mUpdateMutex
Definition: UpdateManager.h:61
UpdateDataParser mUpdateDataParser
Definition: UpdateManager.h:46
std::ofstream mAudacityInstaller
Definition: UpdateManager.h:59
VersionPatch mVersionPatch
Definition: UpdateManager.h:47
Show dialog window with update information for the user.
Interface, that provides access to the data from the HTTP response.
Definition: IResponse.h:50
ResponsePtr doGet(const Request &request)
void ShowErrorDialog(const WindowPlacement &placement, const TranslatableString &dlogTitle, const TranslatableString &message, const ManualPageID &helpPage, const ErrorDialogOptions &options={})
Show an error dialog with a link to the manual for further help.
Definition: BasicUI.h:262
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:196
std::unique_ptr< ProgressDialog > MakeProgress(const TranslatableString &title, const TranslatableString &message, unsigned flags=(ProgressShowStop|ProgressShowCancel), const TranslatableString &remainingLabelText={})
Create and display a progress dialog.
Definition: BasicUI.h:292
Options for variations of error dialogs; the default is for modal dialogs.
Definition: BasicUI.h:52
VersionId version
Definition: VersionPatch.h:20
std::string UpdateDataFormat
Definition: VersionPatch.h:16
wxString download
Definition: VersionPatch.h:22

References CurrentBuildVersion(), audacity::network_manager::NetworkManager::doGet(), VersionPatch::download, AudioIO::Get(), BasicUI::Get(), audacity::network_manager::NetworkManager::GetInstance(), BasicUI::MakeProgress(), mAudacityInstaller, mAudacityInstallerPath, mOnProgress, mProgressDialog, mUpdateDataParser, mUpdateMutex, mVersionPatch, audacity::network_manager::NoError, UpdateDataParser::Parse(), BasicUI::ShowErrorDialog(), VersionPatch::version, XC, and XO().

Referenced by OnTimer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetVersionPatch()

VersionPatch UpdateManager::GetVersionPatch ( ) const

Definition at line 87 of file UpdateManager.cpp.

88{
89 return mVersionPatch;
90}

References mVersionPatch.

◆ IsTimeForUpdatesChecking()

bool UpdateManager::IsTimeForUpdatesChecking ( )
private

Scheduling update time for avoiding multiplying update notifications.

Definition at line 280 of file UpdateManager.cpp.

281{
282 // We use atoll here, so there is no need to handle the exception,
283 // if prefsUpdateScheduledTime is corrupted.
284 // atoll will return 0 on failure, which suits us well.
285 const TimePoint nextUpdatesCheckingTime(std::chrono::milliseconds(
286 atoll(gPrefs->Read(prefsUpdateScheduledTime, "0").c_str())));
287
288 // Get current time
289 const TimePoint currentTime = Clock::now();
290
291 // If next update time 0 or less then current time -> show update dialog,
292 // else this condition allow us to avoid from duplicating update notifications.
293 if (nextUpdatesCheckingTime < currentTime)
294 {
295
296 // Round down the nextUpdatesChecking time to a day.
297 // This is required to ensure, that update is
298 // checked daily
299 using DayDuration =
300 std::chrono::duration<int32_t, std::ratio<60 * 60 * 24>>;
301
302 const auto postponeUpdateUntil =
303 std::chrono::time_point_cast<DayDuration>(
304 currentTime) + DayDuration(1);
305
306 const std::chrono::milliseconds postponeUpdateUntilMS(
307 postponeUpdateUntil.time_since_epoch());
308
309 gPrefs->Write(
311 wxString(std::to_string(postponeUpdateUntilMS.count())));
312
313 gPrefs->Flush();
314
315 return true;
316 }
317
318 return false;
319}
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
static const char * prefsUpdateScheduledTime
Clock::time_point TimePoint
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
virtual bool Read(const wxString &key, bool *value) const =0

References audacity::BasicSettings::Flush(), gPrefs, prefsUpdateScheduledTime, audacity::BasicSettings::Read(), and audacity::BasicSettings::Write().

Referenced by OnTimer().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ OnTimer()

void UpdateManager::OnTimer ( wxTimerEvent &  event)
private

Definition at line 264 of file UpdateManager.cpp.

265{
266 bool updatesCheckingEnabled = DefaultUpdatesCheckingFlag->Read();
267
268#if UPDATE_LOCAL_TESTING == 0
269 if (updatesCheckingEnabled && IsTimeForUpdatesChecking())
270#endif
271 {
272 GetUpdates(true, true);
273 }
274
275 mTimer.StartOnce(std::chrono::duration_cast<std::chrono::milliseconds>(
277 .count());
278}
StickySetting< BoolSetting > DefaultUpdatesCheckingFlag
Definition: Prefs.cpp:63
constexpr Duration updatesCheckInterval
void GetUpdates(bool ignoreNetworkErrors, bool configurableNotification)
wxTimer mTimer
Definition: UpdateManager.h:49
bool IsTimeForUpdatesChecking()
Scheduling update time for avoiding multiplying update notifications.

References DefaultUpdatesCheckingFlag, GetUpdates(), IsTimeForUpdatesChecking(), mTimer, and updatesCheckInterval.

Here is the call graph for this function:

◆ Start()

void UpdateManager::Start ( bool  suppressModal)
static

Definition at line 60 of file UpdateManager.cpp.

61{
62 auto& instance = GetInstance();
63
64 // Show the dialog only once.
65 if (!suppressModal && !prefUpdatesNoticeShown.Read())
66 {
67 // DefaultUpdatesCheckingFlag survives the "Reset Preferences"
68 // action, so check, if the updates were previously disabled as well.
70 {
71 UpdateNoticeDialog notice(nullptr);
72
73 notice.ShowModal();
74 }
75
77 gPrefs->Flush();
78 }
79
80 static std::once_flag flag;
81 std::call_once(flag, [&instance] {
82 instance.mTimer.SetOwner(&instance, ID_TIMER);
83 instance.mTimer.StartOnce(1);
84 });
85}
@ ID_TIMER
static BoolSetting prefUpdatesNoticeShown(wxT("/Update/UpdateNoticeShown"), false)
static std::once_flag flag
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:259
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
static UpdateManager & GetInstance()
Dialog, that notifies the users about automatic updates checking.

References DefaultUpdatesCheckingFlag, flag, audacity::BasicSettings::Flush(), GetInstance(), gPrefs, ID_TIMER, prefUpdatesNoticeShown, Setting< T >::Read(), and Setting< T >::Write().

Referenced by AudacityApp::InitPart2().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mAudacityInstaller

std::ofstream UpdateManager::mAudacityInstaller
private

Definition at line 59 of file UpdateManager.h.

Referenced by GetUpdates().

◆ mAudacityInstallerPath

std::string UpdateManager::mAudacityInstallerPath
private

Definition at line 58 of file UpdateManager.h.

Referenced by GetUpdates().

◆ mOnProgress

bool UpdateManager::mOnProgress { false }
private

Definition at line 62 of file UpdateManager.h.

Referenced by GetUpdates().

◆ mProgressDialog

std::unique_ptr<BasicUI::ProgressDialog> UpdateManager::mProgressDialog
private

Definition at line 56 of file UpdateManager.h.

Referenced by GetUpdates().

◆ mTimer

wxTimer UpdateManager::mTimer
private

Definition at line 49 of file UpdateManager.h.

Referenced by OnTimer().

◆ mUpdateDataParser

UpdateDataParser UpdateManager::mUpdateDataParser
private

Definition at line 46 of file UpdateManager.h.

Referenced by GetUpdates().

◆ mUpdateMutex

std::mutex UpdateManager::mUpdateMutex
private

Definition at line 61 of file UpdateManager.h.

Referenced by GetUpdates().

◆ mVersionPatch

VersionPatch UpdateManager::mVersionPatch
private

Definition at line 47 of file UpdateManager.h.

Referenced by GetUpdates(), and GetVersionPatch().


The documentation for this class was generated from the following files: