Index: common/versionNumber.h =================================================================== --- common/versionNumber.h (revision 10676) +++ common/versionNumber.h (working copy) @@ -21,7 +21,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 28 #define VER_MINOR 00 -#define VER_MINORMINOR 28 +#define VER_MINORMINOR 29 //Numerical value of the version. #define MPT_VERSION_CURRENT MAKE_VERSION_NUMERIC(VER_MAJORMAJOR,VER_MAJOR,VER_MINOR,VER_MINORMINOR) Index: mptrack/mptrack.rc =================================================================== --- mptrack/mptrack.rc (revision 10676) +++ mptrack/mptrack.rc (working copy) @@ -244,22 +244,25 @@ CAPTION "Update" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - GROUPBOX "Check for Updates",IDC_STATIC,6,6,276,66 - CONTROL "&Never",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,12,18,240,8 - CONTROL "&Daily",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,12,30,240,8 - CONTROL "&Weekly (recommended)",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,12,42,240,8 - CONTROL "&Monthly",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,12,54,240,8 - GROUPBOX "Privacy Settings",IDC_STATIC,6,78,276,54 - CONTROL "&Allow us to collect basic update statistics",IDC_CHECK1, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,90,246,12 - LTEXT "If enabled, a randomized user ID is created and transmitted with every update check. This ID can not be linked to you or your computer in any way.",IDC_STATIC,12,102,264,24 - GROUPBOX "Advanced Settings",IDC_STATIC,6,138,276,60 - LTEXT "&Update server URL:",IDC_STATIC,12,150,186,8 - EDITTEXT IDC_EDIT1,12,162,264,12,ES_AUTOHSCROLL - PUSHBUTTON "&Reset",IDC_BUTTON2,222,146,54,12 - LTEXT "Do not change this unless you are absolutely sure of what you are doing.",IDC_STATIC,12,180,264,12 - PUSHBUTTON "&Check for Updates",IDC_BUTTON1,6,204,84,18 - LTEXT "",IDC_LASTUPDATE,6,228,276,48 + CONTROL "Enable online Update &Check",IDC_CHECK_UPDATEENABLED, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,6,105,10 + GROUPBOX "Update Channel",IDC_STATIC_UDATECHANNEL,6,18,276,54 + CONTROL "release: official stable released versions only (recommended)",IDC_RADIO1, + "Button",BS_AUTORADIOBUTTON,12,30,211,10 + CONTROL "next: previews of the next official stable release",IDC_RADIO2, + "Button",BS_AUTORADIOBUTTON,12,42,171,10 + CONTROL "development: bleeding-edge development versions",IDC_RADIO3, + "Button",BS_AUTORADIOBUTTON,12,54,179,10 + GROUPBOX "Check for Updates",IDC_STATIC_UPDATECHECK,6,72,276,48 + LTEXT "&Automatically check on program start:",IDC_STATIC_UPDATEFREQUENCY,12,84,126,12,SS_CENTERIMAGE + COMBOBOX IDC_COMBO_UPDATEFREQUENCY,138,84,42,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Check now",IDC_BUTTON1,222,84,54,12 + LTEXT "",IDC_LASTUPDATE,12,102,264,12 + GROUPBOX "Privacy Settings",IDC_STATIC_UPDATEPRIVACY,6,120,276,156 + CONTROL "&Allow OpenMPT to collect basic statistics about your system configuration",IDC_CHECK1, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,132,264,12 + LTEXT "",IDC_STATIC_UPDATEPRIVACYTEXT,12,144,264,36 + EDITTEXT IDC_EDIT_STATISTICS,12,180,264,90,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL END IDD_CLOSEDOCUMENTS DIALOGEX 0, 0, 370, 197 @@ -881,7 +884,12 @@ 0 END +IDD_OPTIONS_UPDATE AFX_DIALOG_LAYOUT +BEGIN + 0 +END + ///////////////////////////////////////////////////////////////////////////// // // Dialog Info Index: mptrack/resource.h =================================================================== --- mptrack/resource.h (revision 10676) +++ mptrack/resource.h (working copy) @@ -973,6 +973,13 @@ #define IDC_BUTTON_TUNING_REMOVE 2501 #define IDC_STATIC_WINE_RTAUDIO 2502 #define IDC_COMBO_WINE_RTAUDIO 2503 +#define IDC_STATIC_UPDATECHECK 2504 +#define IDC_STATIC_UPDATEPRIVACY 2505 +#define IDC_STATIC_UDATECHANNEL 2506 +#define IDC_COMBO_UPDATEFREQUENCY 2507 +#define IDC_STATIC_UPDATEFREQUENCY 2508 +#define IDC_CHECK_UPDATEENABLED 2509 +#define IDC_STATIC_UPDATEPRIVACYTEXT 2510 #define ID_FILE_NEWMOD 32771 #define ID_FILE_NEWXM 32772 #define ID_FILE_NEWS3M 32773 @@ -1267,9 +1274,9 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 542 +#define _APS_NEXT_RESOURCE_VALUE 543 #define _APS_NEXT_COMMAND_VALUE 44646 -#define _APS_NEXT_CONTROL_VALUE 2504 +#define _APS_NEXT_CONTROL_VALUE 2511 #define _APS_NEXT_SYMED_VALUE 901 #endif #endif Index: mptrack/TrackerSettings.cpp =================================================================== --- mptrack/TrackerSettings.cpp (revision 10676) +++ mptrack/TrackerSettings.cpp (working copy) @@ -331,9 +331,16 @@ , vstHostVendorString(conf, MPT_USTRING("VST Plugins"), MPT_USTRING("HostVendorString"), "OpenMPT project") , vstHostVendorVersion(conf, MPT_USTRING("VST Plugins"), MPT_USTRING("HostVendorVersion"), Version::Current().GetRawVersion()) // Update + , UpdateEnabled(conf, MPT_USTRING("Update"), MPT_USTRING("Enabled"), true) , UpdateLastUpdateCheck(conf, MPT_USTRING("Update"), MPT_USTRING("LastUpdateCheck"), mpt::Date::Unix(time_t())) - , UpdateUpdateCheckPeriod(conf, MPT_USTRING("Update"), MPT_USTRING("UpdateCheckPeriod"), 7) - , UpdateUpdateURL(conf, MPT_USTRING("Update"), MPT_USTRING("UpdateURL"), CUpdateCheck::GetDefaultUpdateURL()) + , UpdateUpdateCheckPeriod_DEPRECATED(conf, MPT_USTRING("Update"), MPT_USTRING("UpdateCheckPeriod"), 7) + , UpdateIntervalDays(conf, MPT_USTRING("Update"), MPT_USTRING("UpdateCheckPeriodDays"), 7) + , UpdateChannel(conf, MPT_USTRING("Update"), MPT_USTRING("Channel"), UpdateChannelRelease) + , UpdateUpdateURL_DEPRECATED(conf, MPT_USTRING("Update"), MPT_USTRING("UpdateURL"), CUpdateCheck::GetDefaultChannelReleaseURL()) + , UpdateChannelReleaseURL(conf, MPT_USTRING("Update"), MPT_USTRING("ChannelReleaseURL"), CUpdateCheck::GetDefaultChannelReleaseURL()) + , UpdateChannelNextURL(conf, MPT_USTRING("Update"), MPT_USTRING("ChannelStableURL"), CUpdateCheck::GetDefaultChannelNextURL()) + , UpdateChannelDevelopmentURL(conf, MPT_USTRING("Update"), MPT_USTRING("ChannelDevelopmentURL"), CUpdateCheck::GetDefaultChannelDevelopmentURL()) + , UpdateAPIURL(conf, MPT_USTRING("Update"), MPT_USTRING("APIURL"), CUpdateCheck::GetDefaultAPIURL()) , UpdateSendGUID(conf, MPT_USTRING("Update"), MPT_USTRING("SendGUID"), true) , UpdateShowUpdateHint(conf, MPT_USTRING("Update"), MPT_USTRING("ShowUpdateHint"), true) , UpdateSuggestDifferentBuildVariant(conf, MPT_USTRING("Update"), MPT_USTRING("SuggestDifferentBuildVariant"), true) @@ -644,6 +651,45 @@ m_dwPatternSetup &= ~0x200; } + // Update + if(storedVersion < MAKE_VERSION_NUMERIC(1,28,00,29)) + { + if(UpdateUpdateCheckPeriod_DEPRECATED <= 0) + { + UpdateEnabled = true; + UpdateIntervalDays = -1; + } else + { + UpdateEnabled = true; + UpdateIntervalDays = UpdateUpdateCheckPeriod_DEPRECATED.Get(); + } + if(UpdateUpdateURL_DEPRECATED.Get() == MPT_USTRING("")) + { + UpdateChannel = UpdateChannelRelease; + } else if(UpdateUpdateURL_DEPRECATED.Get() == MPT_USTRING("http://www.soal.org/openmpt/OpenMPTversionCheck.php5")) + { + UpdateChannel = UpdateChannelRelease; + } else if(UpdateUpdateURL_DEPRECATED.Get() == MPT_USTRING("http://update.openmpt.org/check/$VERSION/$GUID")) + { + UpdateChannel = UpdateChannelRelease; + } else if(UpdateUpdateURL_DEPRECATED.Get() == MPT_USTRING("https://update.openmpt.org/check/$VERSION/$GUID")) + { + UpdateChannel = UpdateChannelRelease; + } else if(UpdateUpdateURL_DEPRECATED.Get() == MPT_USTRING("http://update.openmpt.org/check/testing/$VERSION/$GUID")) + { + UpdateChannel = UpdateChannelDevelopment; + } else if(UpdateUpdateURL_DEPRECATED.Get() == MPT_USTRING("https://update.openmpt.org/check/testing/$VERSION/$GUID")) + { + UpdateChannel = UpdateChannelDevelopment; + } else + { + UpdateChannel = UpdateChannelDevelopment; + UpdateChannelDevelopmentURL = UpdateUpdateURL_DEPRECATED.Get(); + } + conf.Forget(UpdateUpdateCheckPeriod_DEPRECATED.GetPath()); + conf.Forget(UpdateUpdateURL_DEPRECATED.GetPath()); + } + // Effects #ifndef NO_EQ FixupEQ(m_EqSettings); Index: mptrack/TrackerSettings.h =================================================================== --- mptrack/TrackerSettings.h (revision 10676) +++ mptrack/TrackerSettings.h (working copy) @@ -817,9 +817,16 @@ // Update + Setting UpdateEnabled; Setting UpdateLastUpdateCheck; - Setting UpdateUpdateCheckPeriod; - Setting UpdateUpdateURL; + Setting UpdateUpdateCheckPeriod_DEPRECATED; + Setting UpdateIntervalDays; + Setting UpdateChannel; + Setting UpdateUpdateURL_DEPRECATED; + Setting UpdateChannelReleaseURL; + Setting UpdateChannelNextURL; + Setting UpdateChannelDevelopmentURL; + Setting UpdateAPIURL; Setting UpdateSendGUID; Setting UpdateShowUpdateHint; Setting UpdateSuggestDifferentBuildVariant; Index: mptrack/UpdateCheck.cpp =================================================================== --- mptrack/UpdateCheck.cpp (revision 10676) +++ mptrack/UpdateCheck.cpp (working copy) @@ -13,6 +13,7 @@ #include "BuildVariants.h" #include "../common/version.h" #include "../common/misc_util.h" +#include "../common/mptStringBuffer.h" #include "Mptrack.h" #include "TrackerSettings.h" // Setup dialog stuff @@ -19,6 +20,7 @@ #include "Mainfrm.h" #include "../common/mptThread.h" #include "HTTP.h" +#include "../misc/JSON.h" OPENMPT_NAMESPACE_BEGIN @@ -84,12 +86,28 @@ -mpt::ustring CUpdateCheck::GetDefaultUpdateURL() +mpt::ustring CUpdateCheck::GetDefaultChannelReleaseURL() { return MPT_USTRING("https://update.openmpt.org/check/$VERSION/$GUID"); } +mpt::ustring CUpdateCheck::GetDefaultChannelNextURL() +{ + return MPT_USTRING("https://update.openmpt.org/check/next/$VERSION/$GUID"); +} +mpt::ustring CUpdateCheck::GetDefaultChannelDevelopmentURL() +{ + return MPT_USTRING("https://update.openmpt.org/check/testing/$VERSION/$GUID"); +} + + +mpt::ustring CUpdateCheck::GetDefaultAPIURL() +{ + return MPT_USTRING("https://update.openmpt.org/api/v3/"); +} + + std::atomic CUpdateCheck::s_InstanceCount(0); @@ -104,11 +122,15 @@ { if(isAutoUpdate) { - int updateCheckPeriod = TrackerSettings::Instance().UpdateUpdateCheckPeriod; - if(updateCheckPeriod == 0) + if(!TrackerSettings::Instance().UpdateEnabled) { return; } + int updateCheckPeriod = TrackerSettings::Instance().UpdateIntervalDays; + if(updateCheckPeriod < 0) + { + updateCheckPeriod = 0; + } // Do we actually need to run the update check right now? const time_t now = time(nullptr); if(difftime(now, TrackerSettings::Instance().UpdateLastUpdateCheck.Get()) < (double)(updateCheckPeriod * 86400)) @@ -121,7 +143,7 @@ { 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 %u days. If you do not want this, you can disable update checks in the setup."), TrackerSettings::Instance().UpdateUpdateCheckPeriod.Get()); + msg.Format(_T("OpenMPT would like to check for updates now, proceed?\n\nNote: In the future, OpenMPT will check for updates every %u days. If you do not want this, you can disable update checks in the setup."), TrackerSettings::Instance().UpdateIntervalDays.Get()); if(Reporting::Confirm(msg, _T("OpenMPT Internet Update")) == cnfNo) { TrackerSettings::Instance().UpdateLastUpdateCheck = mpt::Date::Unix(now); @@ -128,6 +150,15 @@ return; } } + } else + { + if(!TrackerSettings::Instance().UpdateEnabled) + { + if(Reporting::Confirm(_T("Update Check is disabled. Do you want to check anyway?"), _T("OpenMPT Internet Update")) != cnfYes) + { + return; + } + } } TrackerSettings::Instance().UpdateShowUpdateHint = false; @@ -137,22 +168,33 @@ 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.sendStatistics = TrackerSettings::Instance().UpdateSendGUID; - settings.statisticsUUID = TrackerSettings::Instance().VersionInstallGUID; - settings.suggestDifferentBuilds = TrackerSettings::Instance().UpdateSuggestDifferentBuildVariant; - std::thread(CUpdateCheck::ThreadFunc(settings)).detach(); + CUpdateCheck::Context context; + context.window = CMainFrame::GetMainFrame(); + context.msgProgress = MPT_WM_APP_UPDATECHECK_PROGRESS; + context.msgSuccess = MPT_WM_APP_UPDATECHECK_SUCCESS; + context.msgFailure = MPT_WM_APP_UPDATECHECK_FAILURE; + context.autoUpdate = isAutoUpdate; + std::thread(CUpdateCheck::ThreadFunc(CUpdateCheck::Settings(), context)).detach(); } -CUpdateCheck::ThreadFunc::ThreadFunc(const CUpdateCheck::Settings &settings) +CUpdateCheck::Settings::Settings() + : periodDays(TrackerSettings::Instance().UpdateIntervalDays) + , channel(TrackerSettings::Instance().UpdateChannel) + , channelReleaseURL(TrackerSettings::Instance().UpdateChannelReleaseURL) + , channelNextURL(TrackerSettings::Instance().UpdateChannelNextURL) + , channelDevelopmentURL(TrackerSettings::Instance().UpdateChannelDevelopmentURL) + , apiURL(TrackerSettings::Instance().UpdateAPIURL) + , sendStatistics(TrackerSettings::Instance().UpdateSendGUID) + , statisticsUUID(TrackerSettings::Instance().VersionInstallGUID) + , suggestDifferentBuilds(TrackerSettings::Instance().UpdateSuggestDifferentBuildVariant) +{ +} + + +CUpdateCheck::ThreadFunc::ThreadFunc(const CUpdateCheck::Settings &settings, const CUpdateCheck::Context &context) : settings(settings) + , context(context) { return; } @@ -160,27 +202,104 @@ void CUpdateCheck::ThreadFunc::operator () () { - mpt::SetCurrentThreadPriority(settings.autoUpdate ? mpt::ThreadPriorityLower : mpt::ThreadPriorityNormal); - CUpdateCheck::CheckForUpdate(settings); + mpt::SetCurrentThreadPriority(context.autoUpdate ? mpt::ThreadPriorityLower : mpt::ThreadPriorityNormal); + CUpdateCheck::CheckForUpdate(settings, context); } -// Run update check (independent thread) -CUpdateCheck::Result CUpdateCheck::SearchUpdate(const CUpdateCheck::Settings &settings) +std::string CUpdateCheck::GetStatisticsDataV3(const Settings &settings) { - - HTTP::InternetSession internet(Version::Current().GetOpenMPTVersionString()); + JSON::value j; + j["OpenMPT"]["Version"] = mpt::ufmt::val(Version::Current()); + j["OpenMPT"]["BuildVariant"] = BuildVariants().GuessCurrentBuildName(); + j["OpenMPT"]["Architecture"] = mpt::Windows::Name(mpt::Windows::GetProcessArchitecture()); + j["Update"]["PeriodDays"] = settings.periodDays; + j["System"]["Windows"]["Version"]["Name"] = mpt::Windows::Version::Current().GetName(); + j["System"]["Windows"]["Version"]["Major"] = mpt::Windows::Version::Current().GetSystem().Major; + j["System"]["Windows"]["Version"]["Minor"] = mpt::Windows::Version::Current().GetSystem().Minor; + j["System"]["Windows"]["ServicePack"]["Major"] = mpt::Windows::Version::Current().GetServicePack().Major; + j["System"]["Windows"]["ServicePack"]["Minor"] = mpt::Windows::Version::Current().GetServicePack().Minor; + j["System"]["Windows"]["Build"] = mpt::Windows::Version::Current().GetBuild(); + j["System"]["Windows"]["IsWine"] = mpt::Windows::IsWine(); + if(mpt::Windows::IsWine()) + { + mpt::Wine::VersionContext v; + j["System"]["Windows"]["Wine"]["Version"]["Raw"] = v.RawVersion(); + if(v.Version().IsValid()) + { + j["System"]["Windows"]["Wine"]["Version"]["Major"] = v.Version().GetMajor(); + j["System"]["Windows"]["Wine"]["Version"]["Minor"] = v.Version().GetMinor(); + j["System"]["Windows"]["Wine"]["Version"]["Update"] = v.Version().GetUpdate(); + } + j["System"]["Windows"]["Wine"]["HostSysName"] = v.RawHostSysName(); + } + j["System"]["Architecture"] = mpt::Windows::Name(mpt::Windows::GetHostArchitecture()); + MEMORYSTATUSEX memoryStatus; + MemsetZero(memoryStatus); + memoryStatus.dwLength = sizeof(MEMORYSTATUSEX); + if(GlobalMemoryStatusEx(&memoryStatus) != 0) + { + j["System"]["Memory"] = memoryStatus.ullTotalPhys / 1024 / 1024; + } + #ifdef ENABLE_ASM + j["System"]["Processor"]["Vendor"] = std::string(mpt::String::ReadAutoBuf(ProcVendorID)); + j["System"]["Processor"]["Brand"] = std::string(mpt::String::ReadAutoBuf(ProcBrandID)); + j["System"]["Processor"]["Family"] = ProcFamily; + j["System"]["Processor"]["Model"] = ProcModel; + j["System"]["Processor"]["Stepping"] = ProcStepping; + j["System"]["Processor"]["Features"]["tsc"] = ((GetRealProcSupport() & PROCSUPPORT_TSC) ? true : false); + j["System"]["Processor"]["Features"]["cmov"] = ((GetRealProcSupport() & PROCSUPPORT_CMOV) ? true : false); + j["System"]["Processor"]["Features"]["mmx"] = ((GetRealProcSupport() & PROCSUPPORT_MMX) ? true : false); + j["System"]["Processor"]["Features"]["mmxext"] = ((GetRealProcSupport() & PROCSUPPORT_AMD_MMXEXT) ? true : false); + j["System"]["Processor"]["Features"]["3dnow"] = ((GetRealProcSupport() & PROCSUPPORT_AMD_3DNOW) ? true : false); + j["System"]["Processor"]["Features"]["3dnowext"] = ((GetRealProcSupport() & PROCSUPPORT_AMD_3DNOWEXT) ? true : false); + j["System"]["Processor"]["Features"]["sse"] = ((GetRealProcSupport() & PROCSUPPORT_SSE) ? true : false); + j["System"]["Processor"]["Features"]["sse2"] = ((GetRealProcSupport() & PROCSUPPORT_SSE2) ? true : false); + j["System"]["Processor"]["Features"]["sse3"] = ((GetRealProcSupport() & PROCSUPPORT_SSE3) ? true : false); + j["System"]["Processor"]["Features"]["ssse3"] = ((GetRealProcSupport() & PROCSUPPORT_SSSE3) ? true : false); + j["System"]["Processor"]["Features"]["sse4_1"] = ((GetRealProcSupport() & PROCSUPPORT_SSE4_1) ? true : false); + j["System"]["Processor"]["Features"]["sse4_2"] = ((GetRealProcSupport() & PROCSUPPORT_SSE4_2) ? true : false); + #endif + return j.dump(1, '\t'); +} - mpt::ustring updateURL = settings.updateBaseURL; - if(updateURL.empty()) + +mpt::ustring CUpdateCheck::GetUpdateURLV2(const CUpdateCheck::Settings &settings) +{ + mpt::ustring updateURL; + if(settings.channel == UpdateChannelRelease) { - updateURL = GetDefaultUpdateURL(); + updateURL = settings.channelReleaseURL; + if(updateURL.empty()) + { + updateURL = GetDefaultChannelReleaseURL(); + } + } else if(settings.channel == UpdateChannelNext) + { + updateURL = settings.channelNextURL; + if(updateURL.empty()) + { + updateURL = GetDefaultChannelNextURL(); + } + } else if(settings.channel == UpdateChannelDevelopment) + { + updateURL = settings.channelDevelopmentURL; + if(updateURL.empty()) + { + updateURL = GetDefaultChannelDevelopmentURL(); + } + } else + { + updateURL = settings.channelReleaseURL; + if(updateURL.empty()) + { + updateURL = GetDefaultChannelReleaseURL(); + } } if(updateURL.find(MPT_USTRING("://")) == mpt::ustring::npos) { updateURL = MPT_USTRING("https://") + updateURL; } - // Build update URL updateURL = mpt::String::Replace(updateURL, MPT_USTRING("$VERSION"), mpt::uformat(MPT_USTRING("%1-%2-%3")) ( Version::Current() @@ -188,15 +307,44 @@ , settings.sendStatistics ? mpt::Windows::Version::Current().GetNameShort() : MPT_USTRING("unknown") )); updateURL = mpt::String::Replace(updateURL, MPT_USTRING("$GUID"), settings.sendStatistics ? mpt::ufmt::val(settings.statisticsUUID) : MPT_USTRING("anonymous")); + return updateURL; +} + +// Run update check (independent thread) +CUpdateCheck::Result CUpdateCheck::SearchUpdate(const CUpdateCheck::Settings &settings) +{ + + HTTP::InternetSession internet(Version::Current().GetOpenMPTVersionString()); + // Establish a connection. HTTP::Request request; - request.SetURI(ParseURI(updateURL)); + request.SetURI(ParseURI(GetUpdateURLV2(settings))); request.method = HTTP::Method::Get; request.flags = HTTP::NoCache; HTTP::Result resultHTTP = internet(request.InsecureTLSDowngradeWindowsXP()); + if(settings.sendStatistics) + { + HTTP::Request requestStatistics; + if(settings.statisticsUUID.IsValid()) + { + requestStatistics.SetURI(ParseURI(settings.apiURL + mpt::format(MPT_USTRING("statistics/%1"))(settings.statisticsUUID))); + requestStatistics.method = HTTP::Method::Put; + } else + { + requestStatistics.SetURI(ParseURI(settings.apiURL + MPT_USTRING("statistics/"))); + requestStatistics.method = HTTP::Method::Post; + } + requestStatistics.dataMimeType = HTTP::MimeType::JSON(); + requestStatistics.acceptMimeTypes = HTTP::MimeTypes::JSON(); + std::string jsondata = GetStatisticsDataV3(settings); + MPT_LOG(LogInformation, "Update", mpt::ToUnicode(mpt::CharsetUTF8, jsondata)); + requestStatistics.data = mpt::byte_cast(mpt::as_span(jsondata)); + internet(requestStatistics.InsecureTLSDowngradeWindowsXP()); + } + // Retrieve HTTP status code. if(resultHTTP.Status >= 400) { @@ -244,12 +392,12 @@ } -void CUpdateCheck::CheckForUpdate(const CUpdateCheck::Settings &settings) +void CUpdateCheck::CheckForUpdate(const CUpdateCheck::Settings &settings, const CUpdateCheck::Context &context) { // íncremented 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()); + context.window->SendMessage(context.msgProgress, context.autoUpdate ? 1 : 0, s_InstanceCount.load()); try { try @@ -264,12 +412,12 @@ } } catch(const CUpdateCheck::Error &e) { - settings.window->SendMessage(settings.msgFailure, settings.autoUpdate ? 1 : 0, reinterpret_cast(&e)); + context.window->SendMessage(context.msgFailure, context.autoUpdate ? 1 : 0, reinterpret_cast(&e)); s_InstanceCount.fetch_sub(1); MPT_ASSERT(s_InstanceCount.load() >= 0); return; } - settings.window->SendMessage(settings.msgSuccess, settings.autoUpdate ? 1 : 0, reinterpret_cast(&result)); + context.window->SendMessage(context.msgSuccess, context.autoUpdate ? 1 : 0, reinterpret_cast(&result)); s_InstanceCount.fetch_sub(1); MPT_ASSERT(s_InstanceCount.load() >= 0); } @@ -347,14 +495,13 @@ // CUpdateSetupDlg BEGIN_MESSAGE_MAP(CUpdateSetupDlg, CPropertyPage) - ON_COMMAND(IDC_BUTTON1, &CUpdateSetupDlg::OnCheckNow) - ON_COMMAND(IDC_BUTTON2, &CUpdateSetupDlg::OnResetURL) - ON_COMMAND(IDC_RADIO1, &CUpdateSetupDlg::OnSettingsChanged) - ON_COMMAND(IDC_RADIO2, &CUpdateSetupDlg::OnSettingsChanged) - ON_COMMAND(IDC_RADIO3, &CUpdateSetupDlg::OnSettingsChanged) - ON_COMMAND(IDC_RADIO4, &CUpdateSetupDlg::OnSettingsChanged) - ON_COMMAND(IDC_CHECK1, &CUpdateSetupDlg::OnSettingsChanged) - ON_EN_CHANGE(IDC_EDIT1, &CUpdateSetupDlg::OnSettingsChanged) + ON_COMMAND(IDC_CHECK_UPDATEENABLED, &CUpdateSetupDlg::OnSettingsChanged) + ON_COMMAND(IDC_RADIO1, &CUpdateSetupDlg::OnSettingsChanged) + ON_COMMAND(IDC_RADIO2, &CUpdateSetupDlg::OnSettingsChanged) + ON_COMMAND(IDC_RADIO3, &CUpdateSetupDlg::OnSettingsChanged) + ON_COMMAND(IDC_BUTTON1, &CUpdateSetupDlg::OnCheckNow) + ON_CBN_SELCHANGE(IDC_COMBO_UPDATEFREQUENCY, &CUpdateSetupDlg::OnSettingsChanged) + ON_COMMAND(IDC_CHECK1, &CUpdateSetupDlg::OnSettingsChanged) END_MESSAGE_MAP() @@ -366,29 +513,82 @@ } +void CUpdateSetupDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_COMBO_UPDATEFREQUENCY, m_CbnUpdateFrequency); +} + + BOOL CUpdateSetupDlg::OnInitDialog() { CPropertyPage::OnInitDialog(); + CheckDlgButton(IDC_CHECK_UPDATEENABLED, TrackerSettings::Instance().UpdateEnabled ? BST_CHECKED : BST_UNCHECKED); + int radioID = 0; - int periodDays = TrackerSettings::Instance().UpdateUpdateCheckPeriod; - if(periodDays >= 30) + int updateChannel = TrackerSettings::Instance().UpdateChannel; + if(updateChannel == UpdateChannelRelease) { - radioID = IDC_RADIO4; - } else if(periodDays >= 7) + radioID = IDC_RADIO1; + } else if(updateChannel == UpdateChannelNext) { + radioID = IDC_RADIO2; + } else if(updateChannel == UpdateChannelDevelopment) + { radioID = IDC_RADIO3; - } else if(periodDays >= 1) - { - radioID = IDC_RADIO2; } else { radioID = IDC_RADIO1; } - CheckRadioButton(IDC_RADIO1, IDC_RADIO4, radioID); + CheckRadioButton(IDC_RADIO1, IDC_RADIO3, radioID); + + int32 periodDays = TrackerSettings::Instance().UpdateIntervalDays; + int ndx; + + ndx = m_CbnUpdateFrequency.AddString(_T("always")); + m_CbnUpdateFrequency.SetItemData(ndx, 0); + if(periodDays >= 30) + { + m_CbnUpdateFrequency.SetCurSel(ndx); + } + + ndx = m_CbnUpdateFrequency.AddString(_T("daily")); + m_CbnUpdateFrequency.SetItemData(ndx, 1); + if(periodDays >= 30) + { + m_CbnUpdateFrequency.SetCurSel(ndx); + } + + ndx = m_CbnUpdateFrequency.AddString(_T("weekly")); + m_CbnUpdateFrequency.SetItemData(ndx, 7); + if(periodDays >= 7) + { + m_CbnUpdateFrequency.SetCurSel(ndx); + } + + ndx = m_CbnUpdateFrequency.AddString(_T("monthly")); + m_CbnUpdateFrequency.SetItemData(ndx, 30); + if(periodDays >= 0) + { + m_CbnUpdateFrequency.SetCurSel(ndx); + } + + ndx = m_CbnUpdateFrequency.AddString(_T("never")); + m_CbnUpdateFrequency.SetItemData(ndx, ~(DWORD_PTR)0); + if(periodDays < 0) + { + m_CbnUpdateFrequency.SetCurSel(ndx); + } + CheckDlgButton(IDC_CHECK1, TrackerSettings::Instance().UpdateSendGUID ? BST_CHECKED : BST_UNCHECKED); - SetDlgItemText(IDC_EDIT1, mpt::ToCString(TrackerSettings::Instance().UpdateUpdateURL.Get())); + GetDlgItem(IDC_STATIC_UPDATEPRIVACYTEXT)->SetWindowText(_T("A randomized user ID is created and transmitted alongside. This ID can only be linked to you or your computer by this very ID, which is stored solely on your computer. OpenMPT will use this information to gather usage statistics and to plan removal of support for older systems. The following information will be sent:")); + + UpdateStatistics(); + + EnableDisableDialog(); + m_SettingChangedNotifyGuard.Register(this); SettingChanged(TrackerSettings::Instance().UpdateLastUpdateCheck.GetPath()); @@ -396,6 +596,43 @@ } +void CUpdateSetupDlg::UpdateStatistics() +{ + CUpdateCheck::Settings settings; + + int updateChannel = TrackerSettings::Instance().UpdateChannel; + if(IsDlgButtonChecked(IDC_RADIO1)) updateChannel = UpdateChannelRelease; + if(IsDlgButtonChecked(IDC_RADIO2)) updateChannel = UpdateChannelNext; + if(IsDlgButtonChecked(IDC_RADIO3)) updateChannel = UpdateChannelDevelopment; + + int updateCheckPeriod = (m_CbnUpdateFrequency.GetItemData(m_CbnUpdateFrequency.GetCurSel()) == ~(DWORD_PTR)0) ? -1 : static_cast(m_CbnUpdateFrequency.GetItemData(m_CbnUpdateFrequency.GetCurSel())); + + CString updateURL; + GetDlgItemText(IDC_EDIT1, updateURL); + + settings.periodDays = updateCheckPeriod; + settings.channel = updateChannel; + settings.sendStatistics = (IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED); + + mpt::ustring statistics; + statistics += MPT_USTRING("GET ") + CUpdateCheck::GetUpdateURLV2(settings) + MPT_ULITERAL("\n"); + statistics += MPT_ULITERAL("\n"); + if(settings.sendStatistics) + { + if(settings.statisticsUUID.IsValid()) + { + statistics += MPT_USTRING("PUT ") + settings.apiURL + mpt::format(MPT_USTRING("statistics/%1"))(settings.statisticsUUID) + MPT_ULITERAL("\n"); + } else + { + statistics += MPT_USTRING("POST ") + settings.apiURL + MPT_USTRING("statistics/") + MPT_ULITERAL("\n"); + } + statistics += mpt::String::Replace(mpt::ToUnicode(mpt::CharsetUTF8, CUpdateCheck::GetStatisticsDataV3(settings)), MPT_USTRING("\t"), MPT_USTRING(" ")); + statistics += MPT_ULITERAL("\n"); + } + SetDlgItemText(IDC_EDIT_STATISTICS, mpt::ToCString(mpt::String::Replace(statistics, MPT_USTRING("\n"), MPT_USTRING("\r\n")))); +} + + void CUpdateSetupDlg::SettingChanged(const SettingPath &changedPath) { if(changedPath == TrackerSettings::Instance().UpdateLastUpdateCheck.GetPath()) @@ -420,19 +657,42 @@ } +void CUpdateSetupDlg::EnableDisableDialog() +{ + + /* + BOOL status = ((IsDlgButtonChecked(IDC_CHECK_UPDATEENABLED) != BST_UNCHECKED) ? TRUE : FALSE); + */ + + GetDlgItem(IDC_CHECK_UPDATEENABLED)->EnableWindow(FALSE); + GetDlgItem(IDC_RADIO2)->EnableWindow(FALSE); + +} + + +void CUpdateSetupDlg::OnSettingsChanged() +{ + EnableDisableDialog(); + UpdateStatistics(); + SetModified(TRUE); +} + + void CUpdateSetupDlg::OnOK() { - int updateCheckPeriod = TrackerSettings::Instance().UpdateUpdateCheckPeriod; - if(IsDlgButtonChecked(IDC_RADIO1)) updateCheckPeriod = 0; - if(IsDlgButtonChecked(IDC_RADIO2)) updateCheckPeriod = 1; - if(IsDlgButtonChecked(IDC_RADIO3)) updateCheckPeriod = 7; - if(IsDlgButtonChecked(IDC_RADIO4)) updateCheckPeriod = 31; + int updateChannel = TrackerSettings::Instance().UpdateChannel; + if(IsDlgButtonChecked(IDC_RADIO1)) updateChannel = UpdateChannelRelease; + if(IsDlgButtonChecked(IDC_RADIO2)) updateChannel = UpdateChannelNext; + if(IsDlgButtonChecked(IDC_RADIO3)) updateChannel = UpdateChannelDevelopment; + int updateCheckPeriod = (m_CbnUpdateFrequency.GetItemData(m_CbnUpdateFrequency.GetCurSel()) == ~(DWORD_PTR)0) ? static_cast(m_CbnUpdateFrequency.GetItemData(m_CbnUpdateFrequency.GetCurSel())) : -1; + CString updateURL; GetDlgItemText(IDC_EDIT1, updateURL); - TrackerSettings::Instance().UpdateUpdateCheckPeriod = updateCheckPeriod; - TrackerSettings::Instance().UpdateUpdateURL = mpt::ToUnicode(updateURL); + TrackerSettings::Instance().UpdateEnabled = (IsDlgButtonChecked(IDC_CHECK_UPDATEENABLED) != BST_UNCHECKED); + TrackerSettings::Instance().UpdateIntervalDays = updateCheckPeriod; + TrackerSettings::Instance().UpdateChannel = updateChannel; TrackerSettings::Instance().UpdateSendGUID = (IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED); CPropertyPage::OnOK(); @@ -452,10 +712,4 @@ } -void CUpdateSetupDlg::OnResetURL() -{ - SetDlgItemText(IDC_EDIT1, mpt::ToCString(CUpdateCheck::GetDefaultUpdateURL())); -} - - OPENMPT_NAMESPACE_END Index: mptrack/UpdateCheck.h =================================================================== --- mptrack/UpdateCheck.h (revision 10676) +++ mptrack/UpdateCheck.h (working copy) @@ -24,6 +24,13 @@ OPENMPT_NAMESPACE_BEGIN +enum UpdateChannel +{ + UpdateChannelRelease = 1, + UpdateChannelNext = 2, + UpdateChannelDevelopment = 3, +}; + class CUpdateCheck { @@ -33,7 +40,11 @@ public: - static mpt::ustring GetDefaultUpdateURL(); + static mpt::ustring GetDefaultChannelReleaseURL(); + static mpt::ustring GetDefaultChannelNextURL(); + static mpt::ustring GetDefaultChannelDevelopmentURL(); + + static mpt::ustring GetDefaultAPIURL(); int32 GetNumCurrentRunningInstances(); @@ -42,7 +53,7 @@ public: - struct Settings + struct Context { CWnd *window; UINT msgProgress; @@ -49,10 +60,20 @@ UINT msgSuccess; UINT msgFailure; bool autoUpdate; - mpt::ustring updateBaseURL; // URL where the version check should be made. + }; + + struct Settings + { + int32 periodDays; + uint32 channel; + mpt::ustring channelReleaseURL; + mpt::ustring channelNextURL; + mpt::ustring channelDevelopmentURL; + mpt::ustring apiURL; bool sendStatistics; mpt::UUID statisticsUUID; bool suggestDifferentBuilds; + Settings(); }; class Error @@ -86,6 +107,14 @@ static void ShowSuccessGUI(WPARAM wparam, LPARAM lparam); static void ShowFailureGUI(WPARAM wparam, LPARAM lparam); +public: + + // v2 + static mpt::ustring GetUpdateURLV2(const Settings &settings); + + // v3 + static std::string GetStatisticsDataV3(const Settings &settings); // UTF8 + protected: static void StartUpdateCheckAsync(bool autoUpdate); @@ -93,11 +122,12 @@ struct ThreadFunc { CUpdateCheck::Settings settings; - ThreadFunc(const CUpdateCheck::Settings &settings); + CUpdateCheck::Context context; + ThreadFunc(const CUpdateCheck::Settings &settings, const CUpdateCheck::Context &context); void operator () (); }; - static void CheckForUpdate(const CUpdateCheck::Settings &settings); + static void CheckForUpdate(const CUpdateCheck::Settings &settings, const CUpdateCheck::Context &context); static CUpdateCheck::Result SearchUpdate(const CUpdateCheck::Settings &settings); // may throw @@ -111,17 +141,20 @@ CUpdateSetupDlg(); protected: + virtual void DoDataExchange(CDataExchange *pDX); virtual BOOL OnInitDialog(); virtual void OnOK(); virtual BOOL OnSetActive(); - afx_msg void OnSettingsChanged() { SetModified(TRUE); } + afx_msg void OnSettingsChanged(); afx_msg void OnCheckNow(); - afx_msg void OnResetURL(); virtual void SettingChanged(const SettingPath &changedPath); + void EnableDisableDialog(); + void UpdateStatistics(); DECLARE_MESSAGE_MAP() private: SettingChangedNotifyGuard m_SettingChangedNotifyGuard; + CComboBox m_CbnUpdateFrequency; }; Index: mptrack/WelcomeDialog.cpp =================================================================== --- mptrack/WelcomeDialog.cpp (revision 10676) +++ mptrack/WelcomeDialog.cpp (working copy) @@ -147,7 +147,7 @@ CDialog::OnOK(); bool runUpdates = IsDlgButtonChecked(IDC_CHECK1) != BST_UNCHECKED; - TrackerSettings::Instance().UpdateUpdateCheckPeriod = (runUpdates ? 7 : 0); + TrackerSettings::Instance().UpdateIntervalDays = (runUpdates ? 7 : 0); if(IsDlgButtonChecked(IDC_CHECK2) != BST_UNCHECKED) { FontSetting font = TrackerSettings::Instance().patternFont;