diff --git a/include/audacity/EffectAutomationParameters.h b/include/audacity/EffectAutomationParameters.h index 0f6b519a8..a7b99f1c6 100644 --- a/include/audacity/EffectAutomationParameters.h +++ b/include/audacity/EffectAutomationParameters.h @@ -42,6 +42,8 @@ #ifndef __AUDACITY_EFFECTAUTOMATIONPARAMETERS_H__ #define __AUDACITY_EFFECTAUTOMATIONPARAMETERS_H__ +#include + #include #include #include @@ -88,7 +90,8 @@ public: wxString str; if (Read(key, &str)) { - wxString dec = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER); + struct lconv *info = localeconv(); + wxString dec = info ? wxString::FromUTF8(info->decimal_point) : wxT("."); str.Replace(wxT(","), dec); str.Replace(wxT("."), dec); diff --git a/src/AudacityApp.cpp b/src/AudacityApp.cpp index e1fcdbc87..77dc90412 100644 --- a/src/AudacityApp.cpp +++ b/src/AudacityApp.cpp @@ -971,36 +971,24 @@ wxLanguageInfo userLangs[] = void AudacityApp::InitLang( const wxString & lang ) { - if( mLocale ) + if (mLocale) delete mLocale; - wxString canon = lang; - #if defined(__WXMAC__) // This should be reviewed again during the wx3 conversion. - // On OSX, the eventual call to setlocale() will fail to completely - // set the locale causing printf() and kin to still use the period - // as the decimal separator when the locale specifies something - // else. - const wxLanguageInfo *info = wxLocale::FindLanguageInfo(lang); - if (info) { - canon = info->CanonicalName; - } - // On OSX, if the LANG environment variable isn't set when // using a language like Japanese, an assertion will trigger // because conversion to Japanese from "?" doesn't return a // valid length, so make OSX happy by defining/overriding - // the LANG environment variable with what the user has - // chosen. - wxSetEnv(wxT("LANG"), canon); + // the LANG environment variable with U.S. English for now. + wxSetEnv(wxT("LANG"), wxT("en_US.UTF-8")); #endif #if wxCHECK_VERSION(3,0,0) - mLocale = new wxLocale(wxT(""), canon, wxT(""), true); + mLocale = new wxLocale(wxT(""), lang, wxT(""), true); #else - mLocale = new wxLocale(wxT(""), canon, wxT(""), true, true); + mLocale = new wxLocale(wxT(""), lang, wxT(""), true, true); #endif for(unsigned int i=0; iSetDefaultFlags(AudioIONotBusyFlag, AudioIONotBusyFlag); #ifdef EXPERIMENTAL_EFFECT_MANAGEMENT - c->AddItem(wxT("ManageGenerators"), _("Manage Generators..."), FN(OnManageGenerators)); + c->AddItem(wxT("ManageGenerators"), _("Manage..."), FN(OnManageGenerators)); c->AddSeparator(); #endif @@ -1009,7 +1009,7 @@ void AudacityProject::CreateMenusAndCommands() buildMenuLabel.Printf(_("Repeat Last Effect")); #ifdef EXPERIMENTAL_EFFECT_MANAGEMENT - c->AddItem(wxT("ManageEffects"), _("Manage Effects..."), FN(OnManageEffects)); + c->AddItem(wxT("ManageEffects"), _("Manage..."), FN(OnManageEffects)); c->AddSeparator(); #endif @@ -1033,7 +1033,7 @@ void AudacityProject::CreateMenusAndCommands() c->BeginMenu(_("&Analyze")); #ifdef EXPERIMENTAL_EFFECT_MANAGEMENT - c->AddItem(wxT("ManageAnalyzers"), _("Manage Analyzers..."), FN(OnManageAnalyzers)); + c->AddItem(wxT("ManageAnalyzers"), _("Manage..."), FN(OnManageAnalyzers)); c->AddSeparator(); #endif diff --git a/src/PluginManager.cpp b/src/PluginManager.cpp index 4b361206d..aaea17a6a 100644 --- a/src/PluginManager.cpp +++ b/src/PluginManager.cpp @@ -516,25 +516,42 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S) { /*i18n-hint: The dialog shows a list of plugins with check-boxes beside each one.*/ - S.StartStatic(_("Select Plug-ins, click the Enable or Disable button, then click OK."), true); +// S.StartStatic(_("Effects"), true); + S.StartVerticalLay(); { - S.StartHorizontalLay(wxALIGN_LEFT,0 ); + S.StartHorizontalLay(wxEXPAND, 0); { - wxRadioButton* rb; - /* i18n-hint: This is before radio buttons selecting which effects to show */ - S.AddPrompt(_("Show:")); - /* i18n-hint: Radio button to show all effects */ - rb = S.Id(ID_ShowAll).AddRadioButton(_("&All")); - rb->SetName(_("Show all")); - /* i18n-hint: Radio button to show just the currently disabled effects */ - rb = S.Id(ID_ShowDisabled).AddRadioButtonToGroup(_("D&isabled")); - rb->SetName(_("Show disabled")); - /* i18n-hint: Radio button to show just the currently enabled effects */ - rb = S.Id(ID_ShowEnabled).AddRadioButtonToGroup(_("E&nabled")); - rb->SetName(_("Show enabled")); - /* i18n-hint: Radio button to show just the newly discovered effects */ - rb = S.Id(ID_ShowNew).AddRadioButtonToGroup(_("Ne&w")); - rb->SetName(_("Show new")); + S.StartHorizontalLay(wxALIGN_LEFT, 0); + { + S.AddPrompt(_("Select effects, click the Enable or Disable button, then click OK.")); + } + S.EndHorizontalLay(); + + S.StartHorizontalLay(wxCENTER, 1); + { + S.AddSpace(1); + } + S.EndHorizontalLay(); + + S.StartHorizontalLay(wxALIGN_RIGHT, 0); + { + wxRadioButton* rb; + /* i18n-hint: This is before radio buttons selecting which effects to show */ + S.AddPrompt(_("Show:")); + /* i18n-hint: Radio button to show all effects */ + rb = S.Id(ID_ShowAll).AddRadioButton(_("&All")); + rb->SetName(_("Show all")); + /* i18n-hint: Radio button to show just the currently disabled effects */ + rb = S.Id(ID_ShowDisabled).AddRadioButtonToGroup(_("D&isabled")); + rb->SetName(_("Show disabled")); + /* i18n-hint: Radio button to show just the currently enabled effects */ + rb = S.Id(ID_ShowEnabled).AddRadioButtonToGroup(_("E&nabled")); + rb->SetName(_("Show enabled")); + /* i18n-hint: Radio button to show just the newly discovered effects */ + rb = S.Id(ID_ShowNew).AddRadioButtonToGroup(_("Ne&w")); + rb->SetName(_("Show new")); + } + S.EndHorizontalLay(); } S.EndHorizontalLay(); @@ -568,7 +585,8 @@ void PluginRegistrationDialog::PopulateOrExchange(ShuttleGui &S) } S.EndHorizontalLay(); } - S.EndStatic(); +// S.EndStatic(); + S.EndVerticalLay(); S.AddStandardButtons(eOkButton | eCancelButton); } @@ -726,7 +744,7 @@ void PluginRegistrationDialog::RegenerateEffectsList(int filter) if (mEffects->GetItemCount() > 0) { // Make sure first item is selected/focused. - mEffects->SetFocus(); +// mEffects->SetFocus(); mEffects->SetItemState(0, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED|wxLIST_STATE_SELECTED); #if wxUSE_ACCESSIBILITY mAx->SetSelected(0); diff --git a/src/Project.cpp b/src/Project.cpp index c64d0e0ef..9cef7d3c6 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -4730,7 +4730,7 @@ void AudacityProject::AutoSave() wxString projName; if (mFileName.IsEmpty()) - projName = _("New Project"); + projName = wxT("New Project"); else projName = wxFileName(mFileName).GetName(); diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index c88df224d..209eff2ff 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1950,8 +1950,11 @@ void TrackPanel::SetCursorAndTipWhenSelectTool( Track * t, // If not shift-down and not snapping center, then // choose boundaries only in snapping tolerance, - // and may choose center - SelectionBoundary boundary = ChooseBoundary(event, t, r, !bShiftDown, !bShiftDown); + // and may choose center. + // But don't change the cursor when scrubbing. + SelectionBoundary boundary = IsScrubbing() + ? SBNone + : ChooseBoundary(event, t, r, !bShiftDown, !bShiftDown); #ifdef USE_MIDI // The MIDI HitTest will only succeed if we are on a midi track, so diff --git a/src/effects/DtmfGen.cpp b/src/effects/DtmfGen.cpp index 90ba2a300..98b9de60f 100644 --- a/src/effects/DtmfGen.cpp +++ b/src/effects/DtmfGen.cpp @@ -282,6 +282,13 @@ bool EffectDtmf::Startup() return true; } +bool EffectDtmf::Init() +{ + Recalculate(); + + return true; +} + void EffectDtmf::PopulateOrExchange(ShuttleGui & S) { // dialog will be passed values from effect diff --git a/src/effects/DtmfGen.h b/src/effects/DtmfGen.h index 10bfa84c0..0010a973d 100644 --- a/src/effects/DtmfGen.h +++ b/src/effects/DtmfGen.h @@ -52,6 +52,7 @@ public: // Effect implementation virtual bool Startup(); + virtual bool Init(); virtual void PopulateOrExchange(ShuttleGui & S); virtual bool TransferDataFromWindow(); virtual bool TransferDataToWindow(); diff --git a/src/effects/LoadEffects.cpp b/src/effects/LoadEffects.cpp index 82195e543..fc171765b 100644 --- a/src/effects/LoadEffects.cpp +++ b/src/effects/LoadEffects.cpp @@ -129,17 +129,17 @@ EFFECT( WAHWAH, EffectWahwah() ) \ EFFECT( FINDCLIPPING, EffectFindClipping() ) \ NOISEREDUCTION_EFFECT \ - SOUNDTOUCH_EFFECTS + SOUNDTOUCH_EFFECTS \ + EFFECT( AUTODUCK, EffectAutoDuck() ) \ + EFFECT( LEVELLER, EffectLeveller() ) \ + EFFECT( PAULSTRETCH, EffectPaulstretch() ) \ + SBSMS_EFFECTS // // Define the list of effects that do not get autoregistered // #define EXCLUDE_LIST \ - EFFECT( AUTODUCK, EffectAutoDuck() ) \ - EFFECT( LEVELLER, EffectLeveller() ) \ - EFFECT( PAULSTRETCH, EffectPaulstretch() ) \ - CLASSICFILTER_EFFECT \ - SBSMS_EFFECTS + CLASSICFILTER_EFFECT // // Define the EFFECT() macro to generate enum names diff --git a/src/effects/ToneGen.cpp b/src/effects/ToneGen.cpp index dd425bc35..ca64e26c9 100644 --- a/src/effects/ToneGen.cpp +++ b/src/effects/ToneGen.cpp @@ -258,16 +258,16 @@ bool EffectToneGen::GetAutomationParameters(EffectAutomationParameters & parms) parms.Write(KEY_Amplitude, mAmplitude[0]); } - parms.Write(KEY_Waveform, mWaveforms[mWaveform]); - parms.Write(KEY_Interp, mInterpolations[mInterpolation]); + parms.Write(KEY_Waveform, kWaveStrings[mWaveform]); + parms.Write(KEY_Interp, kInterStrings[mInterpolation]); return true; } bool EffectToneGen::SetAutomationParameters(EffectAutomationParameters & parms) { - ReadAndVerifyEnum(Waveform, mWaveforms); - ReadAndVerifyEnum(Interp, mInterpolations); + ReadAndVerifyEnum(Waveform, wxArrayString(kNumWaveforms, kWaveStrings)); + ReadAndVerifyEnum(Interp, wxArrayString(kNumInterpolations, kInterStrings)); if (mChirp) { ReadAndVerifyDouble(StartFreq); diff --git a/src/widgets/numformatter.cpp b/src/widgets/numformatter.cpp index 6d776bf1a..2c6dab828 100644 --- a/src/widgets/numformatter.cpp +++ b/src/widgets/numformatter.cpp @@ -39,77 +39,6 @@ // local helpers // ---------------------------------------------------------------------------- -namespace -{ - -// Contains information about the locale which was used to initialize our -// cached values of the decimal and thousands separators. Notice that it isn't -// enough to store just wxLocale because the user code may call setlocale() -// directly and storing just C locale string is not enough because we can use -// the OS API directly instead of the CRT ones on some platforms. So just store -// both. -class LocaleId -{ -public: - LocaleId() - { -#if wxUSE_INTL - m_wxloc = NULL; -#endif // wxUSE_INTL - m_cloc = NULL; - } - - ~LocaleId() - { - Free(); - } - -#if wxUSE_INTL - // Return true if this is the first time this function is called for this - // object or if the program locale has changed since the last time it was - // called. Otherwise just return false indicating that updating locale- - // dependent information is not necessary. - bool NotInitializedOrHasChanged() - { - wxLocale * const wxloc = wxGetLocale(); - const char * const cloc = setlocale(LC_ALL, NULL); - if ( m_wxloc || m_cloc ) - { - if ( m_wxloc == wxloc && strcmp(m_cloc, cloc) == 0 ) - return false; - - Free(); - } - //else: Not initialized yet. - - m_wxloc = wxloc; - m_cloc = strdup(cloc); - - return true; - } -#endif // wxUSE_INTL - -private: - void Free() - { -#if wxUSE_INTL - free(m_cloc); -#endif // wxUSE_INTL - } - -#if wxUSE_INTL - // Non-owned pointer to wxLocale which was used. - wxLocale *m_wxloc; -#endif // wxUSE_INTL - - // Owned pointer to the C locale string. - char *m_cloc; - -// wxDECLARE_NO_COPY_CLASS(LocaleId); -}; - -} // anonymous namespace - // ============================================================================ // NumberFormatter implementation // ============================================================================ @@ -120,93 +49,35 @@ private: wxChar NumberFormatter::GetDecimalSeparator() { -#if wxUSE_INTL - // Notice that while using static variable here is not MT-safe, the worst - // that can happen is that we redo the initialization if we're called - // concurrently from more than one thread so it's not a real problem. - static wxChar s_decimalSeparator = 0; +#if wxUSE_INTL + struct lconv *info = localeconv(); + wxString s = info ? wxString::FromUTF8(info->decimal_point) : wxT("."); + if (s.empty()) + { + // We really must have something for decimal separator, so fall + // back to the C locale default. + s = wxT("."); + } - // Remember the locale which was current when we initialized, we must redo - // the initialization if the locale changed. - static LocaleId s_localeUsedForInit; - - if ( s_localeUsedForInit.NotInitializedOrHasChanged() ) - { - const wxString - s = wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, wxLOCALE_CAT_NUMBER); - if ( s.empty() ) - { - // We really must have something for decimal separator, so fall - // back to the C locale default. - s_decimalSeparator = '.'; - } - else - { - // To the best of my knowledge there are no locales like this. - wxASSERT_MSG( s.length() == 1, - wxT("Multi-character decimal separator?") ); - - s_decimalSeparator = s[0]; - } - } - - return s_decimalSeparator; + return s[0]; #else // !wxUSE_INTL - return wxT('.'); + return wxT('.'); #endif // wxUSE_INTL/!wxUSE_INTL } bool NumberFormatter::GetThousandsSeparatorIfUsed(wxChar *sep) { #if wxUSE_INTL - static wxChar s_thousandsSeparator = 0; - static LocaleId s_localeUsedForInit; + struct lconv *info = localeconv(); + wxString s = info ? wxString::FromUTF8(info->thousands_sep) : wxT(""); - if ( s_localeUsedForInit.NotInitializedOrHasChanged() ) - { -#if defined(__WXMSW__) - wxUint32 lcid = LOCALE_USER_DEFAULT; + if (s.IsEmpty()) + { + return false; + } - if (wxGetLocale()) - { - const wxLanguageInfo *info = wxLocale::GetLanguageInfo(wxGetLocale()->GetLanguage()); - if (info) - { ; - lcid = MAKELCID(MAKELANGID(info->WinLang, info->WinSublang), - SORT_DEFAULT); - } - } - - wxString s; - wxChar buffer[256]; - buffer[0] = wxT('\0'); - size_t count = GetLocaleInfo(lcid, LOCALE_STHOUSAND, buffer, 256); - if (!count) - s << wxT(","); - else - s << buffer; -#else - wxString - s = wxLocale::GetInfo(wxLOCALE_THOUSANDS_SEP, wxLOCALE_CAT_NUMBER); -#endif - if ( !s.empty() ) - { - wxASSERT_MSG( s.length() == 1, - wxT("Multi-character thousands separator?") ); - - s_thousandsSeparator = s[0]; - } - //else: Unlike above it's perfectly fine for the thousands separator to - // be empty if grouping is not used, so just leave it as 0. - } - - if ( !s_thousandsSeparator ) - return false; - - if ( sep ) - *sep = s_thousandsSeparator; - - return true; + *sep = s[0]; + return true; #else // !wxUSE_INTL wxUnusedVar(sep); return false;