From 56a05cc646c01609b3130f18e457c534c130f72b Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 27 Jun 2019 08:46:55 -0400 Subject: [PATCH] Avoid Win startup crash... ... Because of different ordering of file-scope static initializations, visiting TrackInfo.cpp before wxApp is initialized. (This didn't happen on Mac.) This requires other changes to PrefsListener so that safe unbinding is guaranteed by destructors, even if the PrefsListener is destroyed after the global wxApp object. --- src/Prefs.cpp | 30 ++++++++++++---- src/Prefs.h | 4 ++- src/TrackInfo.cpp | 91 +++++++++++++++++++++++++---------------------- 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/Prefs.cpp b/src/Prefs.cpp index 3da5c2d27..808686db9 100755 --- a/src/Prefs.cpp +++ b/src/Prefs.cpp @@ -71,29 +71,45 @@ int gMenusDirty = 0; wxDEFINE_EVENT(EVT_PREFS_UPDATE, wxCommandEvent); -PrefsListener::PrefsListener() +struct PrefsListener::Impl : wxEvtHandler +{ + Impl( PrefsListener &owner ); + ~Impl(); + void OnEvent(wxCommandEvent&); + PrefsListener &mOwner; +}; + +PrefsListener::Impl::Impl( PrefsListener &owner ) + : mOwner{ owner } +{ + wxTheApp->Bind(EVT_PREFS_UPDATE, &PrefsListener::Impl::OnEvent, this); +} + +PrefsListener::Impl::~Impl() +{ +} + +PrefsListener::PrefsListener() + : mpImpl{ std::make_unique( *this ) } { - wxTheApp->Bind(EVT_PREFS_UPDATE, &PrefsListener::OnEvent, this); } PrefsListener::~PrefsListener() { - // Explicit unbinding is needed because this is not a wxEvtHandler - wxTheApp->Unbind(EVT_PREFS_UPDATE, &PrefsListener::OnEvent, this); } void PrefsListener::UpdateSelectedPrefs( int ) { } -void PrefsListener::OnEvent( wxCommandEvent &evt ) +void PrefsListener::Impl::OnEvent( wxCommandEvent &evt ) { evt.Skip(); auto id = evt.GetId(); if (id <= 0) - UpdatePrefs(); + mOwner.UpdatePrefs(); else - UpdateSelectedPrefs( id ); + mOwner.UpdateSelectedPrefs( id ); } #if 0 diff --git a/src/Prefs.h b/src/Prefs.h index e4ebd048b..4cb454e0e 100644 --- a/src/Prefs.h +++ b/src/Prefs.h @@ -33,6 +33,7 @@ #include "../include/audacity/ComponentInterface.h" +#include #include // to inherit wxFileConfig #include // to declare custom event types @@ -182,7 +183,8 @@ protected: virtual void UpdateSelectedPrefs( int id ); private: - void OnEvent(wxCommandEvent&); + struct Impl; + std::unique_ptr mpImpl; }; #endif diff --git a/src/TrackInfo.cpp b/src/TrackInfo.cpp index 24526deff..01f3fc36a 100644 --- a/src/TrackInfo.cpp +++ b/src/TrackInfo.cpp @@ -43,10 +43,56 @@ Paul Licameli split from TrackPanel.cpp #include "ViewInfo.h" #include "tracks/ui/TrackView.h" -static wxString gSoloPref; + +// Subscribe to preference changes to update static variables +struct Settings : PrefsListener { + wxString gSoloPref; + wxFont gFont; + + Settings() + { + UpdatePrefs(); + } + + void UpdatePrefs() override + { + gPrefs->Read(wxT("/GUI/Solo"), &gSoloPref, wxT("Simple")); + + // Calculation of best font size depends on language, so it should be redone in case + // the language preference changed. + + int fontSize = 10; + gFont.Create(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); + + int allowableWidth = + // PRL: was it correct to include the margin? + ( kTrackInfoWidth + kLeftMargin ) + - 2; // 2 to allow for left/right borders + int textWidth; + std::unique_ptr pContext( + wxGraphicsContext::Create() + ); + pContext->SetFont( gFont, *wxBLACK ); + do { + gFont.SetPointSize(fontSize); + double dWidth; + pContext->GetTextExtent( + _("Stereo, 999999Hz"), &dWidth, nullptr ); + textWidth = (wxCoord)( dWidth + 0.5 ); + fontSize--; + } while (textWidth >= allowableWidth); + } +}; + +static Settings &settings() +{ + static Settings theSettings; + return theSettings; +} + bool TrackInfo::HasSoloButton() { - return gSoloPref!=wxT("None"); + return settings().gSoloPref != wxT("None"); } #define RANGE(array) (array), (array) + sizeof(array)/sizeof(*(array)) @@ -398,12 +444,6 @@ void TrackInfo::MinimizeSyncLockDrawFunction } } -namespace { - -wxFont gFont; - -} - void TrackInfo::GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ) { dest.x = rect.x; @@ -508,7 +548,7 @@ void TrackInfo::GetSyncLockIconRect(const wxRect & rect, wxRect &dest) /// \todo Probably should move to 'Utils.cpp'. void TrackInfo::SetTrackInfoFont(wxDC * dc) { - dc->SetFont(gFont); + dc->SetFont(settings().gFont); } //#define USE_BEVELS @@ -521,36 +561,3 @@ unsigned TrackInfo::DefaultTrackHeight( const TCPLines &topLines ) totalTCPLines( commonTrackTCPBottomLines, false ) + 1; return (unsigned) std::max( needed, (int) TrackView::DefaultHeight ); } - -// Subscribe to preference changes to update static variables -static struct MyPrefsListener : PrefsListener { - void UpdatePrefs() override - { - gPrefs->Read(wxT("/GUI/Solo"), &gSoloPref, wxT("Simple")); - - // Calculation of best font size depends on language, so it should be redone in case - // the language preference changed. - - int fontSize = 10; - gFont.Create(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); - - int allowableWidth = - // PRL: was it correct to include the margin? - ( kTrackInfoWidth + kLeftMargin ) - - 2; // 2 to allow for left/right borders - int textWidth; - std::unique_ptr pContext( - wxGraphicsContext::Create() - ); - pContext->SetFont( gFont, *wxBLACK ); - do { - gFont.SetPointSize(fontSize); - double dWidth; - pContext->GetTextExtent( - _("Stereo, 999999Hz"), &dWidth, nullptr ); - textWidth = (wxCoord)( dWidth + 0.5 ); - fontSize--; - } while (textWidth >= allowableWidth); - } -} sPrefsListener; -