View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001428 | OpenMPT | Installer and Update | public | 2021-03-01 15:31 | 2024-10-10 08:16 |
Reporter | manx | Assigned To | Saga Musix | ||
Priority | low | Severity | minor | Reproducibility | have not tried |
Status | resolved | Resolution | fixed | ||
Product Version | OpenMPT 1.30.00.* (old testing) | ||||
Target Version | OpenMPT 1.30.01.00 / libopenmpt 0.6.0 (upgrade first) | Fixed in Version | OpenMPT 1.30.01.00 / libopenmpt 0.6.0 (upgrade first) | ||
Summary | 0001428: Avoid modal update notifcation dialog | ||||
Description | Instead, we should display a yellow/orange/red notification field in top right corner of the toolbar. Necessary infrastructure already exists and new code needs to just plug into 2 places already marked with
| ||||
Tags | No tags attached. | ||||
Has the bug occurred in previous versions? | |||||
Tested code revision (in case you know it) | |||||
I moved some of the logic when to show what into CUpdateCheck, which has better access to the actual information which has to be shown. This should now in all cases correctly show the ToolTip, and fall back to showing a modal dialog if the Toolbar is invisible. update-nonmodal-v4.patch (18,297 bytes)
Index: common/versionNumber.h =================================================================== --- common/versionNumber.h (revision 15514) +++ common/versionNumber.h (working copy) @@ -18,6 +18,6 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 30 #define VER_MINOR 00 -#define VER_MINORMINOR 47 +#define VER_MINORMINOR 46 OPENMPT_NAMESPACE_END Index: mptrack/Mainbar.cpp =================================================================== --- mptrack/Mainbar.cpp (revision 15514) +++ mptrack/Mainbar.cpp (working copy) @@ -132,7 +132,7 @@ // Play Command #define PLAYCMD_INDEX 10 #define TOOLBAR_IMAGE_PAUSE 8 -#define TOOLBAR_IMAGE_PLAY 12 +#define TOOLBAR_IMAGE_PLAY 13 // Base octave #define EDITOCTAVE_INDEX 13 #define EDITOCTAVE_WIDTH SCALEWIDTH(55) @@ -177,7 +177,7 @@ #define SPINRPB_WIDTH SCALEWIDTH(16) #define SPINRPB_HEIGHT (EDITRPB_HEIGHT) // VU Meters -#define VUMETER_INDEX (SPINRPB_INDEX+5) +#define VUMETER_INDEX (SPINRPB_INDEX+6) #define VUMETER_WIDTH SCALEWIDTH(255) #define VUMETER_HEIGHT SCALEHEIGHT(19) @@ -215,6 +215,7 @@ ID_SEPARATOR, ID_VIEW_OPTIONS, ID_PANIC, + ID_INTERNETUPDATE, ID_SEPARATOR, ID_SEPARATOR, // VU Meter }; @@ -339,6 +340,9 @@ SetBaseOctave(4); SetCurrentSong(nullptr); EnableDocking(CBRS_ALIGN_ANY); + + GetToolBarCtrl().SetState(ID_INTERNETUPDATE, TBSTATE_HIDDEN); + return TRUE; } @@ -454,8 +458,110 @@ } + +BEGIN_MESSAGE_MAP(UpdateToolTip, CToolTipCtrl) + ON_WM_LBUTTONUP() + ON_NOTIFY_REFLECT(TTN_POP, &UpdateToolTip::OnPop) + ON_NOTIFY_REFLECT(TTN_SHOW, &UpdateToolTip::OnShow) + ON_NOTIFY_REFLECT(TTN_LINKCLICK, &UpdateToolTip::OnLinkClick) +END_MESSAGE_MAP() + + +bool UpdateToolTip::ShowUpdate(CWnd &parent, const CString &newVersion, const CRect rectClient, const CPoint ptScreen, const int buttonID) +{ + if(m_hWnd) + DestroyWindow(); + Create(&parent, TTS_NOPREFIX | TTS_BALLOON | TTS_CLOSE | TTS_NOFADE); + + CString message = MPT_CFORMAT("OpenMPT {} has been released.\n<a>Click here to see what's new.</a>")(newVersion); + TOOLINFO ti{}; + ti.cbSize = TTTOOLINFO_V1_SIZE; + ti.uFlags = TTF_TRACK | TTF_PARSELINKS; + ti.hwnd = parent; + ti.lpszText = message.GetBuffer(); + ti.uId = buttonID; + ti.rect = rectClient; + if(!SendMessage(TTM_ADDTOOL, 0, reinterpret_cast<LPARAM>(&ti))) + return false; + + SetTitle(TTI_INFO, _T("Update Available")); + SendMessage(TTM_TRACKPOSITION, 0, static_cast<LPARAM>(MAKELONG(ptScreen.x, ptScreen.y))); + SendMessage(TTM_TRACKACTIVATE, TRUE, reinterpret_cast<LPARAM>(&ti)); + return true; +} + + +void UpdateToolTip::SetResult(PopAction action) +{ + m_popAction = action; + SendMessage(TTM_TRACKACTIVATE, FALSE, 0); + if(action != PopAction::CloseButton && action != PopAction::Undetermined) + CMainFrame::GetMainFrame()->SendMessage(WM_MOD_UPDATENOTIFY, static_cast<WPARAM>(action)); +} + + +void UpdateToolTip::OnLButtonUp(UINT nFlags, CPoint point) +{ + CToolTipCtrl::OnLButtonUp(nFlags, point); + if(m_popAction == PopAction::Undetermined) + { + SetResult(m_popAction); + } +} + + +void UpdateToolTip::OnPop(NMHDR *pNMHDR, LRESULT *) +{ + if(pNMHDR->idFrom == UINT_PTR(-1)) + SetResult(PopAction::CloseButton); +} + + +void UpdateToolTip::OnShow(NMHDR *, LRESULT *) +{ + m_popAction = PopAction::Undetermined; +} + + +void UpdateToolTip::OnLinkClick(NMHDR *, LRESULT *) +{ + SetResult(PopAction::ClickLink); +} + + +bool CMainToolBar::ShowUpdateInfo(const CString &newVersion) +{ + GetToolBarCtrl().SetState(ID_INTERNETUPDATE, TBSTATE_ENABLED); + if(m_bVertical) + SetVertical(); + else + SetHorizontal(); + + CRect rect; + GetToolBarCtrl().GetRect(ID_INTERNETUPDATE, &rect); + CPoint pt = rect.CenterPoint(); + ClientToScreen(&pt); + CMainFrame::GetMainFrame()->GetWindowRect(rect); + LimitMax(pt.x, rect.right); + + if(IsVisible()) + { + return m_tooltip.ShowUpdate(*this, newVersion, rect, pt, ID_INTERNETUPDATE); + } else + { + return false; + } +} + + BOOL CMainToolBar::SetCurrentSong(CSoundFile *pSndFile) { + static CSoundFile *sndFile = nullptr; + if(pSndFile != sndFile) + { + sndFile = pSndFile; + } + // Update Info if(pSndFile) { @@ -699,6 +805,7 @@ case ID_PLAYER_PLAYFROMSTART: s = _T("Play From Start"); cmd = kcPlaySongFromStart; break; case ID_VIEW_OPTIONS: s = _T("Setup"); cmd = kcViewOptions; break; case ID_PANIC: s = _T("Stop all hanging VSTi and sample voices"); cmd = kcPanic; break; + case ID_INTERNETUPDATE: s = _T("A new update is available."); break; } if(s == nullptr) Index: mptrack/Mainbar.h =================================================================== --- mptrack/Mainbar.h (revision 15514) +++ mptrack/Mainbar.h (working copy) @@ -48,6 +48,32 @@ class CModTree; class CMainFrame; +class UpdateToolTip : public CToolTipCtrl +{ +public: + enum class PopAction + { + Undetermined, + CloseButton, + ClickLink, + ClickBubble, + }; +protected: + PopAction m_popAction = PopAction::Undetermined; + +public: + bool ShowUpdate(CWnd &parent, const CString &newVersion, const CRect rectClient, const CPoint ptScreen, const int buttonID); + +protected: + void SetResult(PopAction action); + + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnPop(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnShow(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnLinkClick(NMHDR *pNMHDR, LRESULT *pResult); + DECLARE_MESSAGE_MAP() +}; + class CToolBarEx: public CToolBar { protected: @@ -74,6 +100,7 @@ class CMainToolBar: public CToolBarEx { protected: + UpdateToolTip m_tooltip; CImageListEx m_ImageList, m_ImageListDisabled; CStatic m_EditTempo, m_EditSpeed, m_EditOctave, m_EditRowsPerBeat; CStatic m_StaticTempo, m_StaticSpeed, m_StaticRowsPerBeat; @@ -110,6 +137,8 @@ BOOL SetBaseOctave(UINT nOctave); BOOL SetCurrentSong(CSoundFile *pModDoc); + bool ShowUpdateInfo(const CString &newVersion); + protected: //{{AFX_MSG(CMainToolBar) afx_msg void OnVScroll(UINT, UINT, CScrollBar *); Index: mptrack/MainFrm.cpp =================================================================== --- mptrack/MainFrm.cpp (revision 15514) +++ mptrack/MainFrm.cpp (working copy) @@ -104,6 +104,7 @@ ON_MESSAGE(WM_MOD_MIDIMAPPING, &CMainFrame::OnViewMIDIMapping) ON_MESSAGE(WM_MOD_UPDATEVIEWS, &CMainFrame::OnUpdateViews) ON_MESSAGE(WM_MOD_SETMODIFIED, &CMainFrame::OnSetModified) + ON_MESSAGE(WM_MOD_UPDATENOTIFY, &CMainFrame::OnToolbarUpdateIndicatorClick) ON_COMMAND(ID_INTERNETUPDATE, &CMainFrame::OnInternetUpdate) ON_COMMAND(ID_HELP_SHOWSETTINGSFOLDER, &CMainFrame::OnShowSettingsFolder) #if defined(MPT_ENABLE_UPDATE) @@ -2605,13 +2606,22 @@ #if defined(MPT_ENABLE_UPDATE) +bool CMainFrame::ShowUpdateIndicator(const CString &releaseVersion, const CString &releaseDate, const CString &releaseURL) +{ + return m_wndToolBar.ShowUpdateInfo(releaseVersion); +} + + LRESULT CMainFrame::OnUpdateCheckStart(WPARAM wparam, LPARAM lparam) { - bool isAutoUpdate = CUpdateCheck::IsAutoUpdateFromMessage(wparam, lparam); + const bool isAutoUpdate = CUpdateCheck::IsAutoUpdateFromMessage(wparam, lparam); CString updateText = _T("Checking for updates..."); if(isAutoUpdate) { - SetHelpText(updateText); + if(!CanShowUpdateIndicator()) + { + SetHelpText(updateText); + } } else if(m_UpdateOptionsDialog) { m_UpdateOptionsDialog->SetDlgItemText(IDC_LASTUPDATE, updateText); @@ -2642,7 +2652,10 @@ CString updateText = MPT_CFORMAT("Checking for updates... {}%")(lparam); if(isAutoUpdate) { - SetHelpText(updateText); + if(!CanShowUpdateIndicator()) + { + SetHelpText(updateText); + } } else if(m_UpdateOptionsDialog) { m_UpdateOptionsDialog->SetDlgItemText(IDC_LASTUPDATE, updateText); @@ -2667,7 +2680,10 @@ CString updateText = _T("Checking for updates... Canceled."); if(isAutoUpdate) { - SetHelpText(updateText); + if(!CanShowUpdateIndicator()) + { + SetHelpText(updateText); + } } else if(m_UpdateOptionsDialog) { m_UpdateOptionsDialog->SetDlgItemText(IDC_LASTUPDATE, updateText); @@ -2682,7 +2698,10 @@ } if(isAutoUpdate) { - SetHelpText(_T("")); + if(!CanShowUpdateIndicator()) + { + SetHelpText(_T("")); + } } else if(m_UpdateOptionsDialog) { // nothing @@ -2696,11 +2715,15 @@ LRESULT CMainFrame::OnUpdateCheckFailure(WPARAM wparam, LPARAM lparam) { - bool isAutoUpdate = CUpdateCheck::IsAutoUpdateFromMessage(wparam, lparam); - CString updateText = MPT_CFORMAT("Checking for updates failed: {}")(CUpdateCheck::GetFailureMessage(wparam, lparam)); + const bool isAutoUpdate = CUpdateCheck::IsAutoUpdateFromMessage(wparam, lparam); + const CUpdateCheck::Error &error = CUpdateCheck::MessageAsError(wparam, lparam); + CString updateText = MPT_CFORMAT("Checking for updates failed: {}")(mpt::get_exception_text<mpt::ustring>(error)); if(isAutoUpdate) { - SetHelpText(updateText); + if(!CanShowUpdateIndicator()) + { + SetHelpText(updateText); + } } else if(m_UpdateOptionsDialog) { m_UpdateOptionsDialog->SetDlgItemText(IDC_LASTUPDATE, updateText); @@ -2713,10 +2736,13 @@ g_UpdateCheckProgressDialog = nullptr; } } - CUpdateCheck::ShowFailureGUI(wparam, lparam); + CUpdateCheck::ShowFailureGUI(isAutoUpdate, error); if(isAutoUpdate) { - SetHelpText(_T("")); + if(!CanShowUpdateIndicator()) + { + SetHelpText(_T("")); + } } else if(m_UpdateOptionsDialog) { // nothing @@ -2730,14 +2756,16 @@ LRESULT CMainFrame::OnUpdateCheckSuccess(WPARAM wparam, LPARAM lparam) { - CUpdateCheck::AcknowledgeSuccess(wparam, lparam); - bool isAutoUpdate = CUpdateCheck::IsAutoUpdateFromMessage(wparam, lparam); + const bool isAutoUpdate = CUpdateCheck::IsAutoUpdateFromMessage(wparam, lparam); + const CUpdateCheck::Result & result = CUpdateCheck::MessageAsResult(wparam, lparam); + CUpdateCheck::AcknowledgeSuccess(result); CString updateText = _T("Checking for updates... Done."); - // TODO: - // UpdateToolbarUpdateIndicator(CUpdateCheck::ResultFromMessage(wparam, lparam)); if(isAutoUpdate) { - SetHelpText(updateText); + if(!CanShowUpdateIndicator()) + { + SetHelpText(updateText); + } } else if(m_UpdateOptionsDialog) { m_UpdateOptionsDialog->SetDlgItemText(IDC_LASTUPDATE, updateText); @@ -2750,25 +2778,28 @@ g_UpdateCheckProgressDialog = nullptr; } } - CUpdateCheck::ShowSuccessGUI(wparam, lparam); + CUpdateCheck::ShowSuccessGUI(isAutoUpdate, result); if(isAutoUpdate) { - SetHelpText(_T("")); + if(!CanShowUpdateIndicator()) + { + SetHelpText(_T("")); + } } else if(m_UpdateOptionsDialog) { // nothing } else { - // nothing + SetHelpText(_T("")); } return TRUE; } -void CMainFrame::OnToolbarUpdateIndicatorClick() +LPARAM CMainFrame::OnToolbarUpdateIndicatorClick(WPARAM, LPARAM) { - // TODO CUpdateCheck::DoManualUpdateCheck(); + return 0; } Index: mptrack/Mainfrm.h =================================================================== --- mptrack/Mainfrm.h (revision 15514) +++ mptrack/Mainfrm.h (working copy) @@ -61,6 +61,7 @@ WM_MOD_SETMODIFIED, WM_MOD_MDIACTIVATE, WM_MOD_MDIDEACTIVATE, + WM_MOD_UPDATENOTIFY, }; enum @@ -402,6 +403,11 @@ static CInputHandler* GetInputHandler() { return m_InputHandler; } void SetElapsedTime(double t) { m_dwTimeSec = static_cast<CSoundFile::samplecount_t>(t); } +#if defined(MPT_ENABLE_UPDATE) + bool CanShowUpdateIndicator() const { return m_wndToolBar.IsVisible(); } + bool ShowUpdateIndicator(const CString &releaseVersion, const CString &releaseDate, const CString &releaseURL); +#endif // MPT_ENABLE_UPDATE + CModTree *GetUpperTreeview() { return m_wndTree.m_pModTree; } CModTree *GetLowerTreeview() { return m_wndTree.m_pModTreeData; } bool SetTreeSoundfile(FileReader &file) { return m_wndTree.SetTreeSoundfile(file); } @@ -546,7 +552,7 @@ afx_msg LRESULT OnUpdateCheckCanceled(WPARAM wparam, LPARAM lparam); afx_msg LRESULT OnUpdateCheckFailure(WPARAM wparam, LPARAM lparam); afx_msg LRESULT OnUpdateCheckSuccess(WPARAM wparam, LPARAM lparam); - afx_msg void OnToolbarUpdateIndicatorClick(); + afx_msg LRESULT OnToolbarUpdateIndicatorClick(WPARAM wparam, LPARAM lparam); #endif // MPT_ENABLE_UPDATE afx_msg void OnHelp(); afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD_PTR dwData); Index: mptrack/res/main_toolbar.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: mptrack/UpdateCheck.cpp =================================================================== --- mptrack/UpdateCheck.cpp (revision 15514) +++ mptrack/UpdateCheck.cpp (working copy) @@ -1000,17 +1000,15 @@ } -CUpdateCheck::Result CUpdateCheck::ResultFromMessage(WPARAM /*wparam*/ , LPARAM lparam) +const CUpdateCheck::Result &CUpdateCheck::MessageAsResult(WPARAM /* wparam */ , LPARAM lparam) { - const CUpdateCheck::Result &result = *reinterpret_cast<CUpdateCheck::Result*>(lparam); - return result; + return *reinterpret_cast<CUpdateCheck::Result*>(lparam); } -CUpdateCheck::Error CUpdateCheck::ErrorFromMessage(WPARAM /*wparam*/ , LPARAM lparam) +const CUpdateCheck::Error &CUpdateCheck::MessageAsError(WPARAM /* wparam */ , LPARAM lparam) { - const CUpdateCheck::Error &error = *reinterpret_cast<CUpdateCheck::Error*>(lparam); - return error; + return *reinterpret_cast<CUpdateCheck::Error*>(lparam); } @@ -1471,10 +1469,8 @@ }; -void CUpdateCheck::AcknowledgeSuccess(WPARAM wparam, LPARAM lparam) +void CUpdateCheck::AcknowledgeSuccess(const CUpdateCheck::Result &result) { - MPT_UNREFERENCED_PARAMETER(wparam); - const CUpdateCheck::Result& result = *reinterpret_cast<CUpdateCheck::Result*>(lparam); if(result.CheckTime != time_t{}) { TrackerSettings::Instance().UpdateLastUpdateCheck = mpt::Date::Unix(result.CheckTime); @@ -1482,11 +1478,10 @@ } -void CUpdateCheck::ShowSuccessGUI(WPARAM wparam, LPARAM lparam) +void CUpdateCheck::ShowSuccessGUI(const bool &autoUpdate, const CUpdateCheck::Result &result) { - const CUpdateCheck::Result &result = *reinterpret_cast<CUpdateCheck::Result*>(lparam); - bool autoUpdate = wparam != 0; + bool modal = !autoUpdate || !CMainFrame::GetMainFrame()->CanShowUpdateIndicator(); #if MPT_UPDATE_LEGACY @@ -1494,14 +1489,24 @@ { if(result.UpdateAvailable && (!autoUpdate || result.Version != TrackerSettings::Instance().UpdateIgnoreVersion)) { - UpdateDialog dlg(result.Version, result.Date, result.URL); - if(dlg.DoModal() == IDOK) + if(!CMainFrame::GetMainFrame()->ShowUpdateIndicator(result.Version, result.Date, result.URL)) { - CTrackApp::OpenURL(result.URL); + modal = true; } + if(modal) + { + UpdateDialog dlg(result.Version, result.Date, result.URL); + if(dlg.DoModal() == IDOK) + { + CTrackApp::OpenURL(result.URL); + } + } } else if(!result.UpdateAvailable && !autoUpdate) { - Reporting::Information(U_("You already have the latest version of OpenMPT installed."), U_("OpenMPT Internet Update")); + if(modal) + { + Reporting::Information(U_("You already have the latest version of OpenMPT installed."), U_("OpenMPT Internet Update")); + } } return; } @@ -1515,7 +1520,10 @@ { if(!autoUpdate) { - Reporting::Information(U_("You already have the latest version of OpenMPT installed."), U_("OpenMPT Update")); + if(modal) + { + Reporting::Information(U_("You already have the latest version of OpenMPT installed."), U_("OpenMPT Update")); + } } return; } @@ -1537,6 +1545,7 @@ } else { + const TCHAR *action = _T("&View Announcement"); const bool canInstall = !updateInfo.download.empty() && versionInfo.downloads[updateInfo.download].can_autoupdate && (Version::Current() >= Version::Parse(versionInfo.downloads[updateInfo.download].autoupdate_minversion)); const bool canDownload = !canInstall && !updateInfo.download.empty() && !versionInfo.downloads[updateInfo.download].download_url.empty(); @@ -1548,6 +1557,20 @@ action = _T("&Download Now"); } + if(!CMainFrame::GetMainFrame()->ShowUpdateIndicator( + mpt::ToCString(versionInfo.version), + mpt::ToCString(versionInfo.date), + mpt::ToCString(versionInfo.changelog_url))) + { + // on failure to show tooltip, continue and show modal dialog + modal = true; + } + + if(!modal) + { + return; + } + UpdateDialog dlg( mpt::ToCString(versionInfo.version), mpt::ToCString(versionInfo.date), @@ -1576,19 +1599,8 @@ } -mpt::ustring CUpdateCheck::GetFailureMessage(WPARAM wparam, LPARAM lparam) +void CUpdateCheck::ShowFailureGUI(const bool &autoUpdate, const CUpdateCheck::Error &error) { - MPT_UNREFERENCED_PARAMETER(wparam); - const CUpdateCheck::Error &error = *reinterpret_cast<CUpdateCheck::Error*>(lparam); - return mpt::get_exception_text<mpt::ustring>(error); -} - - - -void CUpdateCheck::ShowFailureGUI(WPARAM wparam, LPARAM lparam) -{ - const CUpdateCheck::Error &error = *reinterpret_cast<CUpdateCheck::Error*>(lparam); - bool autoUpdate = wparam != 0; if(!autoUpdate) { Reporting::Error(mpt::get_exception_text<mpt::ustring>(error), U_("OpenMPT Update Error")); Index: mptrack/UpdateCheck.h =================================================================== --- mptrack/UpdateCheck.h (revision 15514) +++ mptrack/UpdateCheck.h (working copy) @@ -128,16 +128,14 @@ static bool IsAutoUpdateFromMessage(WPARAM wparam, LPARAM lparam); - static CUpdateCheck::Result ResultFromMessage(WPARAM wparam, LPARAM lparam); - static CUpdateCheck::Error ErrorFromMessage(WPARAM wparam, LPARAM lparam); + static const CUpdateCheck::Result &MessageAsResult(WPARAM wparam, LPARAM lparam); + static const CUpdateCheck::Error &MessageAsError(WPARAM wparam, LPARAM lparam); - static void AcknowledgeSuccess(WPARAM wparam, LPARAM lparam); + static void AcknowledgeSuccess(const CUpdateCheck::Result &result); - static void ShowSuccessGUI(WPARAM wparam, LPARAM lparam); - static void ShowFailureGUI(WPARAM wparam, LPARAM lparam); + static void ShowSuccessGUI(const bool &autoUpdate, const CUpdateCheck::Result &result); + static void ShowFailureGUI(const bool &autoUpdate, const CUpdateCheck::Error &error); - static mpt::ustring GetFailureMessage(WPARAM wparam, LPARAM lparam); - public: #if MPT_UPDATE_LEGACY |
|
Implemented in r15711. Some finetuning may still be done later (e.g. choose whether the link in the bubble should open |
|
Date Modified | Username | Field | Change |
---|---|---|---|
2021-03-01 15:31 | manx | New Issue | |
2021-03-01 15:31 | manx | Status | new => assigned |
2021-03-01 15:31 | manx | Assigned To | => Saga Musix |
2021-03-01 15:32 | manx | Relationship added | related to 0001011 |
2021-08-08 11:39 | manx | Note Added: 0004835 | |
2021-08-08 11:39 | manx | File Added: update-nonmodal-v4.patch | |
2021-09-21 16:51 | Saga Musix | Note Added: 0004876 | |
2021-09-21 16:51 | Saga Musix | Status | assigned => resolved |
2021-09-21 16:51 | Saga Musix | Resolution | open => fixed |
2021-09-21 16:51 | Saga Musix | Fixed in Version | => OpenMPT 1.30.01.00 / libopenmpt 0.6.0 (upgrade first) |
2024-10-10 08:16 | manx | Category | Accessibility => Installer and Update |