From: <man...@us...> - 2015-06-30 08:48:07
|
Revision: 5385 http://sourceforge.net/p/modplug/code/5385 Author: manxorist Date: 2015-06-30 08:47:59 +0000 (Tue, 30 Jun 2015) Log Message: ----------- [Ref] Update Check: Avoid duplicating the settings state. [Ref] Update Check: Convert error handling in update thread to exceptions. [Ref] Update Check: Move the UI handling of update check to the main thread. The async update worker thread now sends WM_APP messages to the main window upon completion or error. [Fix] Update Check: Having moved UI handling of the update check to the main thread, we can safely update the last check time setting on completion and hook into the setting change notification from the update settings page. This means, the displayed last check time in the settings window gets updated in real time now. [Ref] Update Check: Do not use explicit new and delete. [Ref] Update Check: Limit to one running update check thread at a single time. Thread safety does not require this, but we certainly do not want to eat up resources due to network problems when the user repeatedly checks for updates. Modified Paths: -------------- trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Settings.h trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/mptrack/UpdateCheck.cpp trunk/OpenMPT/mptrack/UpdateCheck.h trunk/OpenMPT/mptrack/WelcomeDialog.cpp Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2015-06-30 08:47:59 UTC (rev 5385) @@ -106,6 +106,9 @@ ON_MESSAGE(WM_MOD_KEYCOMMAND, OnCustomKeyMsg) ON_COMMAND(ID_INTERNETUPDATE, OnInternetUpdate) ON_COMMAND(ID_HELP_SHOWSETTINGSFOLDER, OnShowSettingsFolder) + ON_MESSAGE(MPT_WM_APP_UPDATECHECK_PROGRESS, OnUpdateCheckProgress) + ON_MESSAGE(MPT_WM_APP_UPDATECHECK_SUCCESS, OnUpdateCheckSuccess) + ON_MESSAGE(MPT_WM_APP_UPDATECHECK_FAILURE, OnUpdateCheckFailure) ON_COMMAND(ID_HELPSHOW, OnHelp) ON_COMMAND_RANGE(ID_MRU_LIST_FIRST, ID_MRU_LIST_LAST, OnOpenMRUItem) @@ -2610,7 +2613,7 @@ void CMainFrame::OnInternetUpdate() //--------------------------------- { - CUpdateCheck::DoUpdateCheck(false); + CUpdateCheck::DoManualUpdateCheck(); } @@ -2621,6 +2624,32 @@ } +LRESULT CMainFrame::OnUpdateCheckProgress(WPARAM wparam, LPARAM lparam) +//--------------------------------------------------------------------- +{ + MPT_UNREFERENCED_PARAMETER(wparam); + MPT_UNREFERENCED_PARAMETER(lparam); + return TRUE; +} + + +LRESULT CMainFrame::OnUpdateCheckSuccess(WPARAM wparam, LPARAM lparam) +//-------------------------------------------------------------------- +{ + TrackerSettings::Instance().UpdateLastUpdateCheck = mpt::Date::Unix(CUpdateCheck::ResultFromMessage(wparam, lparam).CheckTime); + CUpdateCheck::ShowSuccessGUI(wparam, lparam); + return TRUE; +} + + +LRESULT CMainFrame::OnUpdateCheckFailure(WPARAM wparam, LPARAM lparam) +//-------------------------------------------------------------------- +{ + CUpdateCheck::ShowFailureGUI(wparam, lparam); + return TRUE; +} + + void CMainFrame::OnHelp() //----------------------- { Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2015-06-30 08:47:59 UTC (rev 5385) @@ -55,6 +55,13 @@ enum { + MPT_WM_APP_UPDATECHECK_PROGRESS = WM_APP + 1, + MPT_WM_APP_UPDATECHECK_SUCCESS = WM_APP + 2, + MPT_WM_APP_UPDATECHECK_FAILURE = WM_APP + 3, +}; + +enum +{ CTRLMSG_BASE=0, CTRLMSG_SETVIEWWND, CTRLMSG_ACTIVATEPAGE, @@ -609,6 +616,9 @@ afx_msg void OnViewEditHistory(); afx_msg void OnInternetUpdate(); afx_msg void OnShowSettingsFolder(); + afx_msg LRESULT OnUpdateCheckProgress(WPARAM wparam, LPARAM lparam); + afx_msg LRESULT OnUpdateCheckSuccess(WPARAM wparam, LPARAM lparam); + afx_msg LRESULT OnUpdateCheckFailure(WPARAM wparam, LPARAM lparam); afx_msg void OnHelp(); afx_msg void OnDropFiles(HDROP hDropInfo); //}}AFX_MSG Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2015-06-30 08:47:59 UTC (rev 5385) @@ -1053,10 +1053,7 @@ { // Update check - if(CUpdateCheck::GetUpdateCheckPeriod() != 0) - { - CUpdateCheck::DoUpdateCheck(true); - } + CUpdateCheck::DoAutoUpdateCheck(); // Open settings if the previous execution was with an earlier version. if(TrackerSettings::Instance().ShowSettingsOnNewVersion && (TrackerSettings::Instance().PreviousSettingsVersion < MptVersion::num)) Modified: trunk/OpenMPT/mptrack/Settings.h =================================================================== --- trunk/OpenMPT/mptrack/Settings.h 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/Settings.h 2015-06-30 08:47:59 UTC (rev 5385) @@ -479,10 +479,12 @@ } }; -inline bool operator < (const SettingPath &left, const SettingPath &right) -{ - return left.compare(right) < 0; -} +inline bool operator < (const SettingPath &left, const SettingPath &right) { return left.compare(right) < 0; } +inline bool operator <= (const SettingPath &left, const SettingPath &right) { return left.compare(right) <= 0; } +inline bool operator > (const SettingPath &left, const SettingPath &right) { return left.compare(right) > 0; } +inline bool operator >= (const SettingPath &left, const SettingPath &right) { return left.compare(right) >= 0; } +inline bool operator == (const SettingPath &left, const SettingPath &right) { return left.compare(right) == 0; } +inline bool operator != (const SettingPath &left, const SettingPath &right) { return left.compare(right) != 0; } class ISettingsBackend @@ -850,4 +852,45 @@ }; +#if defined(MPT_SETTINGS_CACHE) + +class SettingChangedNotifyGuard +{ +private: + SettingsContainer &conf; + SettingPath m_Path; + bool m_Registered; + ISettingChanged *m_Handler; +public: + SettingChangedNotifyGuard(SettingsContainer &conf, const SettingPath &path) + : conf(conf) + , m_Path(path) + , m_Registered(false) + , m_Handler(nullptr) + { + return; + } + void Register(ISettingChanged *handler) + { + if(m_Registered) + { + return; + } + m_Handler = handler; + conf.Register(m_Handler, m_Path); + m_Registered = true; + } + ~SettingChangedNotifyGuard() + { + if(m_Registered) + { + conf.UnRegister(m_Handler, m_Path); + m_Registered = false; + } + } +}; + +#endif // MPT_SETTINGS_CACHE + + OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2015-06-30 08:47:59 UTC (rev 5385) @@ -310,10 +310,10 @@ , pluginProjectPath(conf, "VST Plugins", "ProjectPath", std::wstring()) // Update , UpdateLastUpdateCheck(conf, "Update", "LastUpdateCheck", mpt::Date::Unix(time_t())) - , UpdateUpdateCheckPeriod(conf, "Update", "UpdateCheckPeriod", CUpdateCheck::GetUpdateCheckPeriod()) - , UpdateUpdateURL(conf, "Update", "UpdateURL", CUpdateCheck::GetUpdateURL()) - , UpdateSendGUID(conf, "Update", "SendGUID", CUpdateCheck::GetSendGUID()) - , UpdateShowUpdateHint(conf, "Update", "ShowUpdateHint", CUpdateCheck::GetShowUpdateHint()) + , UpdateUpdateCheckPeriod(conf, "Update", "UpdateCheckPeriod", 7) + , UpdateUpdateURL(conf, "Update", "UpdateURL", CUpdateCheck::defaultUpdateURL) + , UpdateSendGUID(conf, "Update", "SendGUID", true) + , UpdateShowUpdateHint(conf, "Update", "ShowUpdateHint", true) { // Effects @@ -386,9 +386,6 @@ PatternClipboard::SetClipboardSize(conf.Read<int32>("Pattern Editor", "NumClipboards", mpt::saturate_cast<int32>(PatternClipboard::GetClipboardSize()))); - // Update - CUpdateCheck::SetUpdateSettings(UpdateLastUpdateCheck.Get(), UpdateUpdateCheckPeriod, UpdateUpdateURL, UpdateSendGUID, UpdateShowUpdateHint); - // Chords LoadChords(Chords); @@ -941,15 +938,6 @@ conf.Write<int32>("Pattern Editor", "NumClipboards", mpt::saturate_cast<int32>(PatternClipboard::GetClipboardSize())); - // Update - { - UpdateLastUpdateCheck = mpt::Date::Unix(CUpdateCheck::GetLastUpdateCheck()); - UpdateUpdateCheckPeriod = CUpdateCheck::GetUpdateCheckPeriod(); - UpdateUpdateURL = CUpdateCheck::GetUpdateURL(); - UpdateSendGUID = CUpdateCheck::GetSendGUID(); - UpdateShowUpdateHint = CUpdateCheck::GetShowUpdateHint(); - } - // Effects #ifndef NO_DSP conf.Write<int32>("Effects", "XBassDepth", m_DSPSettings.m_nXBassDepth); Modified: trunk/OpenMPT/mptrack/UpdateCheck.cpp =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.cpp 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/UpdateCheck.cpp 2015-06-30 08:47:59 UTC (rev 5385) @@ -16,74 +16,108 @@ #include "TrackerSettings.h" // Setup dialog stuff #include "Mainfrm.h" +#include "../common/thread.h" OPENMPT_NAMESPACE_BEGIN -const CString CUpdateCheck::defaultUpdateURL = "http://update.openmpt.org/check/$VERSION/$GUID"; +const TCHAR *const CUpdateCheck::defaultUpdateURL = _T("http://update.openmpt.org/check/$VERSION/$GUID"); -// Static configuration variables -time_t CUpdateCheck::lastUpdateCheck = 0; -int CUpdateCheck::updateCheckPeriod = 7; -CString CUpdateCheck::updateBaseURL = CUpdateCheck::defaultUpdateURL; -bool CUpdateCheck::sendGUID = true; -bool CUpdateCheck::showUpdateHint = true; +mpt::atomic_int32_t CUpdateCheck::s_InstanceCount; -// Start update check -void CUpdateCheck::DoUpdateCheck(bool autoUpdate) -//----------------------------------------------- +int32 CUpdateCheck::GetNumCurrentRunningInstances() +//------------------------------------------------- { - CUpdateCheck *that = new (std::nothrow) CUpdateCheck(autoUpdate); - if(that != nullptr) - { - mpt::thread(MPT_DELEGATE(CUpdateCheck, UpdateThread, that)).detach(); - } + return s_InstanceCount.load(); } -// Run update check (independent thread) -void CUpdateCheck::UpdateThread() -//------------------------------- +// Start update check +void CUpdateCheck::StartUpdateCheckAsync(bool isAutoUpdate) +//--------------------------------------------------------- { - if(isAutoUpdate) { - mpt::SetCurrentThreadPriority(mpt::ThreadPriorityLower); - } - - const time_t now = time(nullptr); - - if(isAutoUpdate) - { + int updateCheckPeriod = TrackerSettings::Instance().UpdateUpdateCheckPeriod; + if(updateCheckPeriod == 0) + { + return; + } // Do we actually need to run the update check right now? - if(CUpdateCheck::updateCheckPeriod == 0 || difftime(now, CUpdateCheck::lastUpdateCheck) < (double)(CUpdateCheck::updateCheckPeriod * 86400)) + const time_t now = time(nullptr); + if(difftime(now, TrackerSettings::Instance().UpdateLastUpdateCheck.Get()) < (double)(updateCheckPeriod * 86400)) { - Terminate(); return; } // Never ran update checks before, so we notify the user of automatic update checks. - if(CUpdateCheck::showUpdateHint) + if(TrackerSettings::Instance().UpdateShowUpdateHint) { - CUpdateCheck::showUpdateHint = false; + TrackerSettings::Instance().UpdateShowUpdateHint = false; CString msg; - msg.Format(_T("OpenMPT would like to check for updates now, proceed?\n\nNote: In the future, OpenMPT will check for updates every %d days. If you do not want this, you can disable update checks in the setup."), CUpdateCheck::updateCheckPeriod); + msg.Format(_T("OpenMPT would like to check for updates now, proceed?\n\nNote: In the future, OpenMPT will check for updates every %d days. If you do not want this, you can disable update checks in the setup."), TrackerSettings::Instance().UpdateUpdateCheckPeriod.Get()); if(Reporting::Confirm(msg, "OpenMPT Internet Update") == cnfNo) { - CUpdateCheck::lastUpdateCheck = now; - Terminate(); + TrackerSettings::Instance().UpdateLastUpdateCheck = mpt::Date::Unix(now); return; } - } } - CUpdateCheck::showUpdateHint = false; + TrackerSettings::Instance().UpdateShowUpdateHint = false; + int32 expected = 0; + if(!s_InstanceCount.compare_exchange_strong(expected, 1)) + { + return; + } + + CUpdateCheck::Settings settings; + settings.window = CMainFrame::GetMainFrame(); + settings.msgProgress = MPT_WM_APP_UPDATECHECK_PROGRESS; + settings.msgSuccess = MPT_WM_APP_UPDATECHECK_SUCCESS; + settings.msgFailure = MPT_WM_APP_UPDATECHECK_FAILURE; + settings.autoUpdate = isAutoUpdate; + settings.updateBaseURL = TrackerSettings::Instance().UpdateUpdateURL; + settings.guidString = (TrackerSettings::Instance().UpdateSendGUID ? mpt::ToCString(TrackerSettings::Instance().gcsInstallGUID.Get()) : _T("anonymous")); + mpt::thread(CUpdateCheck::ThreadFunc(settings)).detach(); +} + + +CUpdateCheck::ThreadFunc::ThreadFunc(const CUpdateCheck::Settings &settings) +//-------------------------------------------------------------------------- + : settings(settings) +{ + return; +} + + +void CUpdateCheck::ThreadFunc::operator () () +//------------------------------------------- +{ + mpt::SetCurrentThreadPriority(settings.autoUpdate ? mpt::ThreadPriorityLower : mpt::ThreadPriorityNormal); + CUpdateCheck().CheckForUpdate(settings); +} + + +CUpdateCheck::CUpdateCheck() +//-------------------------- + : internetHandle(nullptr) + , connectionHandle(nullptr) +{ + return; +} + + +// Run update check (independent thread) +CUpdateCheck::Result CUpdateCheck::SearchUpdate(const CUpdateCheck::Settings &settings) +//------------------------------------------------------------------------------------- +{ + // Prepare UA / URL strings... const CString userAgent = CString(_T("OpenMPT ")) + MptVersion::str; - CString updateURL = CUpdateCheck::updateBaseURL; + CString updateURL = settings.updateBaseURL; CString versionStr = MptVersion::str; #ifdef _WIN64 versionStr.Append(_T("-win64")); @@ -100,20 +134,18 @@ #error "Platform-specific identifier missing" #endif updateURL.Replace(_T("$VERSION"), versionStr); - updateURL.Replace(_T("$GUID"), GetSendGUID() ? mpt::ToCString(TrackerSettings::Instance().gcsInstallGUID.Get()) : _T("anonymous")); + updateURL.Replace(_T("$GUID"), settings.guidString); // Establish a connection. internetHandle = InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if(internetHandle == NULL) { - Die("Could not start update check:\n", GetLastError()); - return; + throw CUpdateCheck::Error("Could not start update check:\n", GetLastError()); } connectionHandle = InternetOpenUrl(internetHandle, updateURL, NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI, 0); if(connectionHandle == NULL) { - Die("Could not establish connection:\n", GetLastError()); - return; + throw CUpdateCheck::Error("Could not establish connection:\n", GetLastError()); } // Retrieve HTTP status code. @@ -121,58 +153,47 @@ DWORD length = sizeof(statusCodeHTTP); if(HttpQueryInfo(connectionHandle, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&statusCodeHTTP, &length, NULL) == FALSE) { - Die("Could not retrieve HTTP header information:\n", GetLastError()); - return; + throw CUpdateCheck::Error("Could not retrieve HTTP header information:\n", GetLastError()); } if(statusCodeHTTP >= 400) { CString error; error.Format(_T("Version information could not be found on the server (HTTP status code %d). Maybe your version of OpenMPT is too old!"), statusCodeHTTP); - Die(error); - return; + throw CUpdateCheck::Error(error); } // Download data. std::string resultBuffer = ""; - char *downloadBuffer = new char[DOWNLOAD_BUFFER_SIZE]; - DWORD availableSize, bytesRead; + DWORD bytesRead = 0; do { // Query number of available bytes to download + DWORD availableSize = 0; if(InternetQueryDataAvailable(connectionHandle, &availableSize, 0, NULL) == FALSE) { - delete[] downloadBuffer; - Die("Error while downloading update information data:\n", GetLastError()); - return; + throw CUpdateCheck::Error("Error while downloading update information data:\n", GetLastError()); } LimitMax(availableSize, (DWORD)DOWNLOAD_BUFFER_SIZE); // Put downloaded bytes into our buffer + char downloadBuffer[DOWNLOAD_BUFFER_SIZE]; if(InternetReadFile(connectionHandle, downloadBuffer, availableSize, &bytesRead) == FALSE) { - delete[] downloadBuffer; - Die("Error while downloading update information data:\n", GetLastError()); - return; + throw CUpdateCheck::Error("Error while downloading update information data:\n", GetLastError()); } + resultBuffer.append(downloadBuffer, downloadBuffer + bytesRead); - resultBuffer.append(downloadBuffer, downloadBuffer + availableSize); Sleep(1); - } while(bytesRead != 0); - delete[] downloadBuffer; + // Now, evaluate the downloaded data. + CUpdateCheck::Result result; + result.UpdateAvailable = false; + result.CheckTime = time(nullptr); CString resultData = mpt::ToCString(mpt::CharsetUTF8, resultBuffer); - // Now, evaluate the downloaded data. - if(!resultData.CompareNoCase(_T("noupdate"))) + if(resultData.CompareNoCase(_T("noupdate")) != 0) { - if(!isAutoUpdate) - { - Reporting::Information("You already have the latest version of OpenMPT installed.", "OpenMPT Internet Update"); - } - } else - { - CString releaseVersion, releaseDate, releaseURL; CString token; int parseStep = 0, parsePos = 0; while((token = resultData.Tokenize(_T("\n"), parsePos)) != "") @@ -183,74 +204,133 @@ case 0: if(token.CompareNoCase(_T("update")) != 0) { - Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); - return; + throw CUpdateCheck::Error("Could not understand server response. Maybe your version of OpenMPT is too old!"); } break; case 1: - releaseVersion = token; + result.Version = token; break; case 2: - releaseDate = token; + result.Date = token; break; case 3: - releaseURL = token; + result.URL = token; break; } } - if(parseStep >= 4) + if(parseStep < 4) { - resultData.Format(_T("A new version is available!\nOpenMPT %s has been released on %s. Would you like to visit %s for more information?"), releaseVersion, releaseDate, releaseURL); - if(Reporting::Confirm(resultData, "OpenMPT Internet Update") == cnfYes) - { - CTrackApp::OpenURL(releaseURL); - } - } else - { - Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); - return; + throw CUpdateCheck::Error("Could not understand server response. Maybe your version of OpenMPT is too old!"); } + result.UpdateAvailable = true; } + return result; +} - CUpdateCheck::lastUpdateCheck = now; - Terminate(); +void CUpdateCheck::CheckForUpdate(const CUpdateCheck::Settings &settings) +//----------------------------------------------------------------------- +{ + // \xEDncremented before starting the thread + MPT_ASSERT(s_InstanceCount.load() >= 1); + CUpdateCheck::Result result; + settings.window->SendMessage(settings.msgProgress, settings.autoUpdate ? 1 : 0, s_InstanceCount.load()); + try + { + result = SearchUpdate(settings); + } catch(const CUpdateCheck::Error &e) + { + settings.window->SendMessage(settings.msgFailure, settings.autoUpdate ? 1 : 0, reinterpret_cast<LPARAM>(&e)); + s_InstanceCount.fetch_sub(1); + MPT_ASSERT(s_InstanceCount.load() >= 0); + return; + } + settings.window->SendMessage(settings.msgSuccess, settings.autoUpdate ? 1 : 0, reinterpret_cast<LPARAM>(&result)); + s_InstanceCount.fetch_sub(1); + MPT_ASSERT(s_InstanceCount.load() >= 0); } -// Die with error message -void CUpdateCheck::Die(CString errorMessage) -//------------------------------------------ +CUpdateCheck::Result CUpdateCheck::ResultFromMessage(WPARAM /*wparam*/ , LPARAM lparam) +//------------------------------------------------------------------------------------- { - if(!isAutoUpdate) + const CUpdateCheck::Result &result = *reinterpret_cast<CUpdateCheck::Result*>(lparam); + return result; +} + + +CUpdateCheck::Error CUpdateCheck::ErrorFromMessage(WPARAM /*wparam*/ , LPARAM lparam) +//----------------------------------------------------------------------------------- +{ + const CUpdateCheck::Error &error = *reinterpret_cast<CUpdateCheck::Error*>(lparam); + return error; +} + + +void CUpdateCheck::ShowSuccessGUI(WPARAM wparam, LPARAM lparam) +//------------------------------------------------------------- +{ + const CUpdateCheck::Result &result = *reinterpret_cast<CUpdateCheck::Result*>(lparam); + bool autoUpdate = (wparam ? true : false); + if(result.UpdateAvailable) { - Reporting::Error(errorMessage, "OpenMPT Internet Update Error"); + if(Reporting::Confirm( + MPT_UFORMAT("A new version is available!\nOpenMPT %1 has been released on %2. Would you like to visit %3 for more information?" + , result.Version, result.Date, result.URL + ), MPT_USTRING("OpenMPT Internet Update")) == cnfYes) + { + CTrackApp::OpenURL(result.URL); + } + } else if(!autoUpdate) + { + Reporting::Information(MPT_USTRING("You already have the latest version of OpenMPT installed."), MPT_USTRING("OpenMPT Internet Update")); } - Terminate(); } -// Die with WinINet error message -void CUpdateCheck::Die(CString errorMessage, DWORD errorCode) -//----------------------------------------------------------- +void CUpdateCheck::ShowFailureGUI(WPARAM wparam, LPARAM lparam) +//------------------------------------------------------------- { - if(!isAutoUpdate) + const CUpdateCheck::Error &error = *reinterpret_cast<CUpdateCheck::Error*>(lparam); + bool autoUpdate = (wparam ? true : false); + if(!autoUpdate) { - void *lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - GetModuleHandle(TEXT("wininet.dll")), errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); - - errorMessage.Append((LPTSTR)lpMsgBuf); - LocalFree(lpMsgBuf); + Reporting::Error(mpt::ToUnicode(mpt::CharsetUTF8, error.what() ? std::string(error.what()) : std::string()), MPT_USTRING("OpenMPT Internet Update Error")); } - Die(errorMessage); } -// Kill update object -void CUpdateCheck::Terminate() -//---------------------------- +CUpdateCheck::Error::Error(CString errorMessage) +//---------------------------------------------- + : std::runtime_error(mpt::ToCharset(mpt::CharsetUTF8, errorMessage)) { + return; +} + + +CUpdateCheck::Error::Error(CString errorMessage, DWORD errorCode) +//--------------------------------------------------------------- + : std::runtime_error(mpt::ToCharset(mpt::CharsetUTF8, FormatErrorCode(errorMessage, errorCode))) +{ + return; +} + + +CString CUpdateCheck::Error::FormatErrorCode(CString errorMessage, DWORD errorCode) +//--------------------------------------------------------------------------------- +{ + void *lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + GetModuleHandle(TEXT("wininet.dll")), errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); + errorMessage.Append((LPTSTR)lpMsgBuf); + LocalFree(lpMsgBuf); + return errorMessage; +} + + +CUpdateCheck::~CUpdateCheck() +//--------------------------- +{ if(connectionHandle != nullptr) { InternetCloseHandle(connectionHandle); @@ -261,7 +341,6 @@ InternetCloseHandle(internetHandle); internetHandle = nullptr; } - delete this; } @@ -280,43 +359,70 @@ END_MESSAGE_MAP() +CUpdateSetupDlg::CUpdateSetupDlg() +//-------------------------------- + : CPropertyPage(IDD_OPTIONS_UPDATE) + , m_SettingChangedNotifyGuard(theApp.GetSettings(), TrackerSettings::Instance().UpdateLastUpdateCheck.GetPath()) +{ + return; +} + + BOOL CUpdateSetupDlg::OnInitDialog() //---------------------------------- { CPropertyPage::OnInitDialog(); int radioID = 0; - switch(CUpdateCheck::GetUpdateCheckPeriod()) + int periodDays = TrackerSettings::Instance().UpdateUpdateCheckPeriod; + if(periodDays >= 30) { - case 0: radioID = IDC_RADIO1; break; - case 1: radioID = IDC_RADIO2; break; - case 7: radioID = IDC_RADIO3; break; - case 31: radioID = IDC_RADIO4; break; + radioID = IDC_RADIO4; + } else if(periodDays >= 7) + { + radioID = IDC_RADIO3; + } else if(periodDays >= 1) + { + radioID = IDC_RADIO2; + } else + { + radioID = IDC_RADIO1; } CheckRadioButton(IDC_RADIO1, IDC_RADIO4, radioID); - CheckDlgButton(IDC_CHECK1, CUpdateCheck::GetSendGUID() ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemText(IDC_EDIT1, CUpdateCheck::GetUpdateURL()); + CheckDlgButton(IDC_CHECK1, TrackerSettings::Instance().UpdateSendGUID ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemText(IDC_EDIT1, TrackerSettings::Instance().UpdateUpdateURL.Get()); - const time_t t = CUpdateCheck::GetLastUpdateCheck(); - if(t > 0) + m_SettingChangedNotifyGuard.Register(this); + SettingChanged(TrackerSettings::Instance().UpdateLastUpdateCheck.GetPath()); + + return TRUE; +} + + +void CUpdateSetupDlg::SettingChanged(const SettingPath &changedPath) +//------------------------------------------------------------------ +{ + if(changedPath == TrackerSettings::Instance().UpdateLastUpdateCheck.GetPath()) { - CString updateText; - const tm* const lastUpdate = localtime(&t); - if(lastUpdate != nullptr) + const time_t t = TrackerSettings::Instance().UpdateLastUpdateCheck.Get(); + if(t > 0) { - updateText.Format(_T("The last successful update check was run on %04d-%02d-%02d, %02d:%02d."), lastUpdate->tm_year + 1900, lastUpdate->tm_mon + 1, lastUpdate->tm_mday, lastUpdate->tm_hour, lastUpdate->tm_min); - SetDlgItemText(IDC_LASTUPDATE, updateText); + CString updateText; + const tm* const lastUpdate = localtime(&t); + if(lastUpdate != nullptr) + { + updateText.Format(_T("The last successful update check was run on %04d-%02d-%02d, %02d:%02d."), lastUpdate->tm_year + 1900, lastUpdate->tm_mon + 1, lastUpdate->tm_mday, lastUpdate->tm_hour, lastUpdate->tm_min); + SetDlgItemText(IDC_LASTUPDATE, updateText); + } } } - - return TRUE; } void CUpdateSetupDlg::OnOK() //-------------------------- { - int updateCheckPeriod = CUpdateCheck::GetUpdateCheckPeriod(); + int updateCheckPeriod = TrackerSettings::Instance().UpdateUpdateCheckPeriod; if(IsDlgButtonChecked(IDC_RADIO1)) updateCheckPeriod = 0; if(IsDlgButtonChecked(IDC_RADIO2)) updateCheckPeriod = 1; if(IsDlgButtonChecked(IDC_RADIO3)) updateCheckPeriod = 7; @@ -324,7 +430,10 @@ CString updateURL; GetDlgItemText(IDC_EDIT1, updateURL); - CUpdateCheck::SetUpdateSettings(CUpdateCheck::GetLastUpdateCheck(), updateCheckPeriod, updateURL, IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED, CUpdateCheck::GetShowUpdateHint()); + + TrackerSettings::Instance().UpdateUpdateCheckPeriod = updateCheckPeriod; + TrackerSettings::Instance().UpdateUpdateURL = updateURL; + TrackerSettings::Instance().UpdateSendGUID = (IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED); CPropertyPage::OnOK(); } Modified: trunk/OpenMPT/mptrack/UpdateCheck.h =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.h 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/UpdateCheck.h 2015-06-30 08:47:59 UTC (rev 5385) @@ -13,62 +13,109 @@ #include <WinInet.h> #include <time.h> +#include "../common/mptAtomic.h" #include "resource.h" -#include "../common/thread.h" +#include "Settings.h" OPENMPT_NAMESPACE_BEGIN -#define DOWNLOAD_BUFFER_SIZE 256 +#define DOWNLOAD_BUFFER_SIZE 4096 //================ class CUpdateCheck //================ { + +private: + + static mpt::atomic_int32_t s_InstanceCount; + public: - static const CString defaultUpdateURL; + static const TCHAR *const defaultUpdateURL; - static void DoUpdateCheck(bool autoUpdate); + int32 GetNumCurrentRunningInstances(); - static time_t GetLastUpdateCheck() { return lastUpdateCheck; }; - static int GetUpdateCheckPeriod() { return updateCheckPeriod; }; - static CString GetUpdateURL() { return updateBaseURL; }; - static bool GetSendGUID() { return sendGUID; } - static bool GetShowUpdateHint() { return showUpdateHint; }; - static void SetUpdateSettings(time_t last, int period, CString url, bool sendID, bool showHint) - { lastUpdateCheck = last; updateCheckPeriod = period; updateBaseURL = url; sendGUID = sendID; showUpdateHint = showHint; }; + static void DoAutoUpdateCheck() { StartUpdateCheckAsync(true); } + static void DoManualUpdateCheck() { StartUpdateCheckAsync(false); } +public: + + struct Settings + { + CWnd *window; + UINT msgProgress; + UINT msgSuccess; + UINT msgFailure; + bool autoUpdate; + CString updateBaseURL; // URL where the version check should be made. + CString guidString; // Send GUID to collect basic stats or "anonymous" + }; + + class Error + : public std::runtime_error + { + public: + Error(CString errorMessage); + Error(CString errorMessage, DWORD errorCode); + protected: + static CString FormatErrorCode(CString errorMessage, DWORD errorCode); + }; + + struct Result + { + time_t CheckTime; + bool UpdateAvailable; + CString Version; + CString Date; + CString URL; + Result() + : CheckTime(time_t()) + , UpdateAvailable(false) + { + return; + } + }; + + static CUpdateCheck::Result ResultFromMessage(WPARAM wparam, LPARAM lparam); + static CUpdateCheck::Error ErrorFromMessage(WPARAM wparam, LPARAM lparam); + + static void ShowSuccessGUI(WPARAM wparam, LPARAM lparam); + static void ShowFailureGUI(WPARAM wparam, LPARAM lparam); + protected: - // Static configuration variables - static time_t lastUpdateCheck; // Time of last successful update check - static int updateCheckPeriod; // Check for updates every x days - static CString updateBaseURL; // URL where the version check should be made. - static bool sendGUID; // Send GUID to collect basic stats - static bool showUpdateHint; // Show hint on first automatic update + static void StartUpdateCheckAsync(bool autoUpdate); - bool isAutoUpdate; // Are we running an automatic update check? + struct ThreadFunc + { + CUpdateCheck::Settings settings; + ThreadFunc(const CUpdateCheck::Settings &settings); + void operator () (); + }; // Runtime resource handles - HINTERNET internetHandle, connectionHandle; + HINTERNET internetHandle; + HINTERNET connectionHandle; - // Force creation via "new" as we're using "delete this". Use CUpdateCheck::DoUpdateCheck to create an object. - CUpdateCheck(bool autoUpdate) : internetHandle(nullptr), connectionHandle(nullptr), isAutoUpdate(autoUpdate) { } + CUpdateCheck(); + + void CheckForUpdate(const CUpdateCheck::Settings &settings); - void UpdateThread(); - void Die(CString errorMessage); - void Die(CString errorMessage, DWORD errorCode); - void Terminate(); + CUpdateCheck::Result SearchUpdate(const CUpdateCheck::Settings &settings); // may throw + + ~CUpdateCheck(); + }; //========================================= class CUpdateSetupDlg: public CPropertyPage //========================================= + , public ISettingChanged { public: - CUpdateSetupDlg():CPropertyPage(IDD_OPTIONS_UPDATE) - { }; + CUpdateSetupDlg(); protected: virtual BOOL OnInitDialog(); @@ -77,7 +124,11 @@ afx_msg void OnSettingsChanged() { SetModified(TRUE); } afx_msg void OnCheckNow(); afx_msg void OnResetURL(); + virtual void SettingChanged(const SettingPath &changedPath); DECLARE_MESSAGE_MAP() + +private: + SettingChangedNotifyGuard m_SettingChangedNotifyGuard; }; Modified: trunk/OpenMPT/mptrack/WelcomeDialog.cpp =================================================================== --- trunk/OpenMPT/mptrack/WelcomeDialog.cpp 2015-06-29 14:59:24 UTC (rev 5384) +++ trunk/OpenMPT/mptrack/WelcomeDialog.cpp 2015-06-30 08:47:59 UTC (rev 5385) @@ -149,7 +149,7 @@ CDialog::OnOK(); bool runUpdates = IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED; - CUpdateCheck::SetUpdateSettings(0, runUpdates ? 7 : 0, CUpdateCheck::GetUpdateURL(), CUpdateCheck::GetSendGUID(), CUpdateCheck::GetShowUpdateHint()); + TrackerSettings::Instance().UpdateUpdateCheckPeriod = (runUpdates ? 7 : 0); if(IsDlgButtonChecked(IDC_CHECK2) != BST_UNCHECKED) { FontSetting font = TrackerSettings::Instance().patternFont; @@ -167,7 +167,7 @@ } if(runUpdates) { - CUpdateCheck::DoUpdateCheck(true); + CUpdateCheck::DoAutoUpdateCheck(); } CMainFrame::GetMainFrame()->PostMessage(WM_MOD_INVALIDATEPATTERNS, HINT_MPTOPTIONS); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |