diff --git a/src/ShuttleGui.cpp b/src/ShuttleGui.cpp index 411508446..7f084590f 100644 --- a/src/ShuttleGui.cpp +++ b/src/ShuttleGui.cpp @@ -1679,30 +1679,6 @@ wxString ShuttleGuiBase::TranslateFromIndex( const int nIn, const wxArrayStringE return wxT(""); } -/// Int-to-Index (choices can be items like e.g 0x400120 ) -int ShuttleGuiBase::TranslateToIndex( const int Value, const std::vector &Choices ) -{ - int n = make_iterator_range(Choices).index( Value ); - if( n == wxNOT_FOUND ) - n=miNoMatchSelector; - miNoMatchSelector = 0; - return n; -} - -/// Index-to-int (choices can be items like e.g 0x400120 ) -int ShuttleGuiBase::TranslateFromIndex( const int nIn, const std::vector &Choices ) -{ - int n = nIn; - if( n== wxNOT_FOUND ) - n=miNoMatchSelector; - miNoMatchSelector = 0; - if( n < (int)Choices.size() ) - { - return Choices[n]; - } - return 0; -} - //-----------------------------------------------------------------------// @@ -1938,37 +1914,6 @@ wxChoice * ShuttleGuiBase::TieChoice( return pChoice; } -/// Variant of the standard TieChoice which does the two step exchange -/// between gui and stack variable and stack variable and shuttle. -/// Difference to previous one is that the Translated choices and default -/// are integers, not Strings. -/// @param Prompt The prompt shown beside the control. -/// @param SettingName The setting name as stored in gPrefs -/// @param Default The default value for this control (translated) -/// @param Choices An array of choices that appear on screen. -/// @param InternalChoices The corresponding values (as an integer array) -wxChoice * ShuttleGuiBase::TieChoice( - const wxString &Prompt, - const wxString &SettingName, - const int Default, - const wxArrayStringEx & Choices, - const std::vector & InternalChoices) -{ - wxChoice * pChoice=(wxChoice*)NULL; - - int TempIndex=0; - int TranslatedInt = Default; - WrappedType WrappedRef( TranslatedInt ); - // Get from prefs does 1 and 2. - // Put to prefs does 2 and 3. - if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef ); // Get Int from Prefs. - if( DoStep(1) ) TempIndex = TranslateToIndex( TranslatedInt, InternalChoices ); // Int to an index. - if( DoStep(2) ) pChoice = TieChoice( Prompt, TempIndex, Choices ); // Get/Put index from GUI. - if( DoStep(3) ) TranslatedInt = TranslateFromIndex( TempIndex, InternalChoices ); // Index to int - if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef ); // Put into Prefs. - return pChoice; -} - /// Variant of the standard TieChoice which does the two step exchange /// between gui and stack variable and stack variable and shuttle. /// The Translated choices and default are integers, not Strings. diff --git a/src/ShuttleGui.h b/src/ShuttleGui.h index f489d1b1e..8153ffcc2 100644 --- a/src/ShuttleGui.h +++ b/src/ShuttleGui.h @@ -183,8 +183,6 @@ public: bool DoStep( int iStep ); int TranslateToIndex( const wxString &Value, const wxArrayStringEx &Choices ); wxString TranslateFromIndex( const int nIn, const wxArrayStringEx &Choices ); - int TranslateToIndex( const int Value, const std::vector &Choices ); - int TranslateFromIndex( const int nIn, const std::vector &Choices ); //-- Tie functions both add controls and also read/write to them. // The ones taking a 'WrappedType' are type-generic and are used by the type specific ones. @@ -246,15 +244,6 @@ public: const wxArrayStringEx &Choices, const wxArrayStringEx & InternalChoices ); - // This overload of TieChoice should no longer be used in Preferences! - // Some uses do remain in export settings dialogs. - virtual wxChoice * TieChoice( - const wxString &Prompt, - const wxString &SettingName, - const int Default, - const wxArrayStringEx & Choices, - const std::vector & InternalChoices ); - // This overload presents what is really a numerical setting as a choice among // commonly used values, but the choice is not necessarily exhaustive. // This behaves just like the previous for building dialogs, but the diff --git a/src/commands/GetInfoCommand.cpp b/src/commands/GetInfoCommand.cpp index 4acf1a242..4a6f8b815 100644 --- a/src/commands/GetInfoCommand.cpp +++ b/src/commands/GetInfoCommand.cpp @@ -213,14 +213,6 @@ public: const wxArrayStringEx &Choices, const wxArrayStringEx & InternalChoices ) override; - // An assertion will be violated if this override is reached! - wxChoice * TieChoice( - const wxString &Prompt, - const wxString &SettingName, - const int Default, - const wxArrayStringEx & Choices, - const std::vector & InternalChoices) override; - wxChoice * TieNumberAsChoice( const wxString &Prompt, const wxString &SettingName, @@ -310,34 +302,6 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice( EndStruct(); return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, InternalChoices ); } -wxChoice * ShuttleGuiGetDefinition::TieChoice( - const wxString &Prompt, - const wxString &SettingName, - const int Default, - const wxArrayStringEx & Choices, - const std::vector & InternalChoices) -{ - // Should no longer come here! - // Choice controls in Preferences that really are exhaustive choices among - // non-numerical options must now encode the internal choices as strings, - // not numbers. - wxASSERT(false); - - // But if we do get here anyway, proceed sub-optimally as before. - StartStruct(); - AddItem( SettingName, "id" ); - AddItem( Prompt, "prompt" ); - AddItem( "enum", "type" ); - AddItem( Default, "default" ); - StartField( "enum" ); - StartArray(); - for( size_t i=0;i AC3BitRateValues{ + 32000, + 40000, + 48000, + 56000, + 64000, + 80000, + 96000, + 112000, + 128000, + 160000, + 192000, + 224000, + 256000, + 320000, + 384000, + 448000, + 512000, + 576000, + 640000, +}; + +} + const int ExportFFmpegAC3Options::iAC3SampleRates[] = { 32000, 44100, 48000, 0 }; ExportFFmpegAC3Options::ExportFFmpegAC3Options(wxWindow *parent, int WXUNUSED(format)) : wxPanelWrapper(parent, wxID_ANY) { - for (unsigned int i=0; i < (sizeof(iAC3BitRates)/sizeof(int)); i++) - { - mBitRateNames.push_back(wxString::Format(_("%i kbps"),iAC3BitRates[i]/1000)); - mBitRateLabels.push_back(iAC3BitRates[i]); - } - ShuttleGui S(this, eIsCreatingFromPrefs); PopulateOrExchange(S); @@ -173,8 +214,13 @@ void ExportFFmpegAC3Options::PopulateOrExchange(ShuttleGui & S) { S.StartMultiColumn(2, wxCENTER); { - S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/AC3BitRate"), - 160000, mBitRateNames, mBitRateLabels); + S.TieNumberAsChoice( + _("Bit Rate:"), + wxT("/FileFormats/AC3BitRate"), + 160000, + AC3BitRateNames, + &AC3BitRateValues + ); } S.EndMultiColumn(); } @@ -264,20 +310,40 @@ bool ExportFFmpegAACOptions::TransferDataFromWindow() // ExportFFmpegAMRNBOptions Class //---------------------------------------------------------------------------- +namespace { + /// Bit Rates supported by libAMR-NB encoder /// Sample Rate is always 8 kHz -int ExportFFmpegAMRNBOptions::iAMRNBBitRate[] = -{ 4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200 }; +const wxArrayStringEx AMRNBBitRateNames +{ + // i18n-hint kbps abbreviates "thousands of bits per second" + XO("4.75 kbps"), + XO("5.15 kbps"), + XO("5.90 kbps"), + XO("6.70 kbps"), + XO("7.40 kbps"), + XO("7.95 kbps"), + XO("10.20 kbps"), + XO("12.20 kbps"), +}; + +const std::vector< int > AMRNBBitRateValues +{ + 4750, + 5150, + 5900, + 6700, + 7400, + 7950, + 10200, + 12200, +}; + +} ExportFFmpegAMRNBOptions::ExportFFmpegAMRNBOptions(wxWindow *parent, int WXUNUSED(format)) : wxPanelWrapper(parent, wxID_ANY) { - for (unsigned int i=0; i < (sizeof(iAMRNBBitRate)/sizeof(int)); i++) - { - mBitRateNames.push_back(wxString::Format(_("%.2f kbps"),(float)iAMRNBBitRate[i]/1000)); - mBitRateLabels.push_back(iAMRNBBitRate[i]); - } - ShuttleGui S(this, eIsCreatingFromPrefs); PopulateOrExchange(S); @@ -299,8 +365,13 @@ void ExportFFmpegAMRNBOptions::PopulateOrExchange(ShuttleGui & S) { S.StartMultiColumn(2, wxCENTER); { - S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/AMRNBBitRate"), - 12200, mBitRateNames, mBitRateLabels); + S.TieNumberAsChoice( + _("Bit Rate:"), + wxT("/FileFormats/AMRNBBitRate"), + 12200, + AMRNBBitRateNames, + &AMRNBBitRateValues + ); } S.EndMultiColumn(); } @@ -335,20 +406,46 @@ bool ExportFFmpegAMRNBOptions::TransferDataFromWindow() const int ExportFFmpegWMAOptions::iWMASampleRates[] = { 8000, 11025, 16000, 22050, 44100, 0}; +namespace { + /// Bit Rates supported by WMA encoder. Setting bit rate to other values will not result in different file size. -const int ExportFFmpegWMAOptions::iWMABitRate[] = -{ 24000, 32000, 40000, 48000, 64000, 80000, 96000, 128000, 160000, 192000, 256000, 320000 }; +const wxArrayStringEx WMABitRateNames +{ + // i18n-hint kbps abbreviates "thousands of bits per second" + XO("24 kbps"), + XO("32 kbps"), + XO("40 kbps"), + XO("48 kbps"), + XO("64 kbps"), + XO("80 kbps"), + XO("96 kbps"), + XO("128 kbps"), + XO("160 kbps"), + XO("192 kbps"), + XO("256 kbps"), + XO("320 kbps"), +}; + +const std::vector< int > WMABitRateValues{ + 24000, + 32000, + 40000, + 48000, + 64000, + 80000, + 96000, + 128000, + 160000, + 192000, + 256000, + 320000, +}; + +} ExportFFmpegWMAOptions::ExportFFmpegWMAOptions(wxWindow *parent, int WXUNUSED(format)) : wxPanelWrapper(parent, wxID_ANY) { - for (unsigned int i=0; i < (sizeof(iWMABitRate)/sizeof(int)); i++) - { - /* i18n-hint: abbreviates thousands of bits per second */ - mBitRateNames.push_back(wxString::Format(_("%i kbps"),iWMABitRate[i]/1000)); - mBitRateLabels.push_back(iWMABitRate[i]); - } - ShuttleGui S(this, eIsCreatingFromPrefs); PopulateOrExchange(S); @@ -370,8 +467,13 @@ void ExportFFmpegWMAOptions::PopulateOrExchange(ShuttleGui & S) { S.StartMultiColumn(2, wxCENTER); { - S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/WMABitRate"), - 128000, mBitRateNames, mBitRateLabels); + S.TieNumberAsChoice( + _("Bit Rate:"), + wxT("/FileFormats/WMABitRate"), + 128000, + WMABitRateNames, + &WMABitRateValues + ); } S.EndMultiColumn(); } @@ -1215,36 +1317,17 @@ CompatibilityEntry ExportFFmpegOptions::CompatibilityList[] = }; /// AAC profiles -int ExportFFmpegOptions::iAACProfileValues[] = { - FF_PROFILE_AAC_LOW, - FF_PROFILE_AAC_MAIN, - /*FF_PROFILE_AAC_SSR,*/ - FF_PROFILE_AAC_LTP -}; - -/// Names of AAC profiles to be displayed -static wxString iAACProfileNames(int index) -{ - static const wxString names[] = { - XO("LC"), - XO("Main"), - /*_("SSR"),*/ //SSR is not supported - XO("LTP") - }; - - class NamesArray final : public TranslatableStringArray +// The FF_PROFILE_* enumeration is defined in the ffmpeg library +// PRL: I cant find where this preference is used! +ChoiceSetting AACProfiles { wxT("/FileFormats/FFmpegAACProfile"), { - void Populate() override - { - for (auto &name : names) - mContents.push_back( wxGetTranslation( name ) ); - } - }; - - static NamesArray theArray; - - return theArray.Get()[ index ]; -} + {wxT("1") /*FF_PROFILE_AAC_LOW*/, XO("LC")}, + {wxT("0") /*FF_PROFILE_AAC_MAIN*/, XO("Main")}, + // {wxT("2") /*FF_PROFILE_AAC_SSR*/, XO("SSR")}, //SSR is not supported + {wxT("3") /*FF_PROFILE_AAC_LTP*/, XO("LTP")}, + }, + 0, // "1" +}; /// List of export types ExposedFormat ExportFFmpegOptions::fmts[] = @@ -1349,30 +1432,18 @@ ApplicableFor ExportFFmpegOptions::apptable[] = {FALSE,FFmpegExportCtrlID(0),AV_CODEC_ID_NONE,NULL} }; -/// Prediction order method - names. Labels are indices of this array. -static wxString PredictionOrderMethodNames(int index) -{ - static const wxString names[] = { - XO("Estimate"), - XO("2-level"), - XO("4-level"), - XO("8-level"), - XO("Full search"), - XO("Log search") - }; +namespace { - class NamesArray final : public TranslatableStringArray - { - void Populate() override - { - for (auto &name : names) - mContents.push_back( wxGetTranslation( name ) ); - } - }; +/// Prediction order method - names. +const wxArrayStringEx PredictionOrderMethodNames { + XO("Estimate"), + XO("2-level"), + XO("4-level"), + XO("8-level"), + XO("Full search"), + XO("Log search"), +}; - static NamesArray theArray; - - return theArray.Get()[ index ]; } @@ -1399,18 +1470,6 @@ ExportFFmpegOptions::ExportFFmpegOptions(wxWindow *parent) FetchFormatList(); FetchCodecList(); - for (unsigned int i = 0; i < 6; i++) - { - mPredictionOrderMethodLabels.push_back(i); - mPredictionOrderMethodNames.push_back(wxString::Format(wxT("%s"),PredictionOrderMethodNames(i))); - } - - for (unsigned int i=0; i < (sizeof(iAACProfileValues)/sizeof(int)); i++) - { - mProfileNames.push_back(wxString::Format(wxT("%s"),iAACProfileNames(i))); - mProfileLabels.push_back(iAACProfileValues[i]); - } - PopulateOrExchange(S); //Select the format that was selected last time this dialog was closed @@ -1549,8 +1608,8 @@ void ExportFFmpegOptions::PopulateOrExchange(ShuttleGui & S) mCutoffSpin = S.Id(FECutoffID).TieSpinCtrl(_("Cutoff:"), wxT("/FileFormats/FFmpegCutOff"), 0, 10000000, 0); mCutoffSpin->SetToolTip(_("Audio cutoff bandwidth (Hz)\nOptional\n0 - automatic")); - mProfileChoice = S.Id(FEProfileID).TieChoice(_("Profile:"), wxT("/FileFormats/FFmpegAACProfile"), - mProfileLabels[0], mProfileNames, mProfileLabels); + mProfileChoice = S.Id(FEProfileID) + .TieChoice(_("Profile:"), AACProfiles); mProfileChoice->SetSizeHints( 100,-1); mProfileChoice->SetToolTip(_("AAC Profile\nLow Complexity - default\nMost players won't play anything other than LC")); @@ -1571,8 +1630,13 @@ void ExportFFmpegOptions::PopulateOrExchange(ShuttleGui & S) mLPCCoeffsPrecisionSpin = S.Id(FELPCCoeffsID).TieSpinCtrl(_("LPC"), wxT("/FileFormats/FFmpegLPCCoefPrec"), 0, 15, 0); mLPCCoeffsPrecisionSpin->SetToolTip(_("LPC coefficients precision\nOptional\n0 - default\nmin - 1\nmax - 15")); - mPredictionOrderMethodChoice = S.Id(FEPredOrderID).TieChoice(_("PdO Method:"), wxT("/FileFormats/FFmpegPredOrderMethod"), - mPredictionOrderMethodLabels[4], mPredictionOrderMethodNames, mPredictionOrderMethodLabels); + mPredictionOrderMethodChoice = S.Id(FEPredOrderID) + .TieNumberAsChoice( + _("PdO Method:"), + wxT("/FileFormats/FFmpegPredOrderMethod"), + 4, // Full search + PredictionOrderMethodNames + ); mPredictionOrderMethodChoice->SetSizeHints( 100,-1); mPredictionOrderMethodChoice->SetToolTip(_("Prediction Order Method\nEstimate - fastest, lower compression\nLog search - slowest, best compression\nFull search - default")); diff --git a/src/export/ExportFFmpegDialogs.h b/src/export/ExportFFmpegDialogs.h index facf03b76..357a196f5 100644 --- a/src/export/ExportFFmpegDialogs.h +++ b/src/export/ExportFFmpegDialogs.h @@ -81,17 +81,12 @@ public: bool TransferDataToWindow() override; bool TransferDataFromWindow() override; - /// Bit Rates supported by AC3 encoder - static const int iAC3BitRates[]; /// Sample Rates supported by AC3 encoder (must end with zero-element) /// It is not used in dialog anymore, but will be required later static const int iAC3SampleRates[]; private: - wxArrayStringEx mBitRateNames; - std::vector mBitRateLabels; - wxChoice *mBitRateChoice; int mBitRateFromChoice; }; @@ -123,13 +118,8 @@ public: bool TransferDataToWindow() override; bool TransferDataFromWindow() override; - static int iAMRNBBitRate[]; - private: - wxArrayStringEx mBitRateNames; - std::vector mBitRateLabels; - wxChoice *mBitRateChoice; int mBitRateFromChoice; }; @@ -146,13 +136,9 @@ public: bool TransferDataFromWindow() override; static const int iWMASampleRates[]; - static const int iWMABitRate[]; private: - wxArrayStringEx mBitRateNames; - std::vector mBitRateLabels; - wxChoice *mBitRateChoice; int mBitRateFromChoice; }; @@ -212,7 +198,6 @@ public: // Static tables static CompatibilityEntry CompatibilityList[]; - static int iAACProfileValues[]; static ExposedFormat fmts[]; static const int iAACSampleRates[]; static ApplicableFor apptable[]; @@ -227,10 +212,6 @@ private: wxArrayString mFormatLongNames; wxArrayStringEx mCodecNames; wxArrayString mCodecLongNames; - wxArrayStringEx mProfileNames; - std::vector mProfileLabels; - wxArrayStringEx mPredictionOrderMethodNames; - std::vector mPredictionOrderMethodLabels; wxChoice *mFormatChoice; wxChoice *mCodecChoice; diff --git a/src/export/ExportMP2.cpp b/src/export/ExportMP2.cpp index 2e07e01d5..3586f9a22 100644 --- a/src/export/ExportMP2.cpp +++ b/src/export/ExportMP2.cpp @@ -75,12 +75,51 @@ // ExportMP2Options //---------------------------------------------------------------------------- -static int iBitrates[] = { - 16, 24, 32, 40, 48, 56, 64, - 80, 96, 112, 128, 160, - 192, 224, 256, 320, 384 +namespace { + +const wxArrayStringEx BitRateNames { + // i18n-hint kbps abbreviates "thousands of bits per second" + XO("16 kbps"), + XO("24 kbps"), + XO("32 kbps"), + XO("40 kbps"), + XO("48 kbps"), + XO("56 kbps"), + XO("64 kbps"), + XO("80 kbps"), + XO("96 kbps"), + XO("112 kbps"), + XO("128 kbps"), + XO("160 kbps"), + XO("192 kbps"), + XO("224 kbps"), + XO("256 kbps"), + XO("320 kbps"), + XO("384 kbps"), }; +const std::vector< int > BitRateValues { + 16, + 24, + 32, + 40, + 48, + 56, + 64, + 80, + 96, + 112, + 128, + 160, + 192, + 224, + 256, + 320, + 384, +}; + +} + class ExportMP2Options final : public wxPanelWrapper { public: @@ -90,10 +129,6 @@ public: void PopulateOrExchange(ShuttleGui & S); bool TransferDataToWindow() override; bool TransferDataFromWindow() override; - -private: - wxArrayStringEx mBitRateNames; - std::vector mBitRateLabels; }; /// @@ -101,12 +136,6 @@ private: ExportMP2Options::ExportMP2Options(wxWindow *parent, int WXUNUSED(format)) : wxPanelWrapper(parent, wxID_ANY) { - for (unsigned int i=0; i < (sizeof(iBitrates)/sizeof(int)); i++) - { - mBitRateNames.push_back(wxString::Format(_("%i kbps"),iBitrates[i])); - mBitRateLabels.push_back(iBitrates[i]); - } - ShuttleGui S(this, eIsCreatingFromPrefs); PopulateOrExchange(S); @@ -130,8 +159,13 @@ void ExportMP2Options::PopulateOrExchange(ShuttleGui & S) { S.StartMultiColumn(2, wxCENTER); { - S.TieChoice(_("Bit Rate:"), wxT("/FileFormats/MP2Bitrate"), - 160, mBitRateNames, mBitRateLabels); + S.TieNumberAsChoice( + _("Bit Rate:"), + wxT("/FileFormats/MP2Bitrate"), + 160, + BitRateNames, + &BitRateValues + ); } S.EndMultiColumn(); } diff --git a/src/export/ExportMP3.cpp b/src/export/ExportMP3.cpp index b71e8f651..17b58d745 100644 --- a/src/export/ExportMP3.cpp +++ b/src/export/ExportMP3.cpp @@ -112,16 +112,7 @@ enum MP3ChannelMode : unsigned { }; enum : int { - QUALITY_0 = 0, - QUALITY_1 = 1, QUALITY_2 = 2, - QUALITY_3 = 3, - QUALITY_4 = 4, - QUALITY_5 = 5, - QUALITY_6 = 6, - QUALITY_7 = 7, - QUALITY_8 = 8, - QUALITY_9 = 9, ROUTINE_FAST = 0, ROUTINE_STANDARD = 1, @@ -132,95 +123,93 @@ enum : int { PRESET_MEDIUM = 3, }; -// Note: The label field is what will be written to preferences and carries -// no numerical significance. It is simply a means to look up a value -// in a table. -// -// The entries should be listed in order you want them to appear in the -// choice dropdown based on the name field. -typedef struct -{ - wxString name; - int label; -} CHOICES; - -static CHOICES fixRates[] = -{ +static const wxArrayStringEx fixRateNames { /* i18n-hint: kbps is the bitrate of the MP3 file, kilobits per second*/ - {wxT(""), 320}, - {wxT(""), 256}, - {wxT(""), 224}, - {wxT(""), 192}, - {wxT(""), 160}, - {wxT(""), 144}, - {wxT(""), 128}, - {wxT(""), 112}, - {wxT(""), 96}, - {wxT(""), 80}, - {wxT(""), 64}, - {wxT(""), 56}, - {wxT(""), 48}, - {wxT(""), 40}, - {wxT(""), 32}, - {wxT(""), 24}, - {wxT(""), 16}, - {wxT(""), 8} + XO("320 kbps"), + XO("256 kbps"), + XO("224 kbps"), + XO("192 kbps"), + XO("160 kbps"), + XO("144 kbps"), + XO("128 kbps"), + XO("112 kbps"), + XO("96 kbps"), + XO("80 kbps"), + XO("64 kbps"), + XO("56 kbps"), + XO("48 kbps"), + XO("40 kbps"), + XO("32 kbps"), + XO("24 kbps"), + XO("16 kbps"), + XO("8 kbps"), }; -static CHOICES varRates[] = -{ - {wxT(""), QUALITY_0}, - {wxT(""), QUALITY_1}, - {wxT(""), QUALITY_2}, - {wxT(""), QUALITY_3}, - {wxT(""), QUALITY_4}, - {wxT(""), QUALITY_5}, - {wxT(""), QUALITY_6}, - {wxT(""), QUALITY_7}, - {wxT(""), QUALITY_8}, - {wxT(""), QUALITY_9} +static const std::vector fixRateValues { + 320, + 256, + 224, + 192, + 160, + 144, + 128, + 112, + 96, + 80, + 64, + 56, + 48, + 40, + 32, + 24, + 16, + 8, }; -static const wxChar *const varRatesNumbers[] = { - wxT("220-260"), - wxT("200-250"), - wxT("170-210"), - wxT("155-195"), - wxT("145-185"), - wxT("110-150"), - wxT("95-135"), - wxT("80-120"), - wxT("65-105"), - wxT("45-85") -}; -static_assert( WXSIZEOF(varRates) == WXSIZEOF(varRatesNumbers), - "size mismatch" ); - -static CHOICES varModes[] = -{ - {wxT(""), ROUTINE_FAST }, - {wxT(""), ROUTINE_STANDARD} +static const wxArrayStringEx varRateNames { + XO("220-260 kbps (Best Quality)"), + XO("200-250 kbps"), + XO("170-210 kbps"), + XO("155-195 kbps"), + XO("145-185 kbps"), + XO("110-150 kbps"), + XO("95-135 kbps"), + XO("80-120 kbps"), + XO("65-105 kbps"), + XO("45-85 kbps (Smaller files)"), }; -static CHOICES setRates[] = -{ - {wxT(""), PRESET_INSANE }, - {wxT(""), PRESET_EXTREME }, - {wxT(""), PRESET_STANDARD}, - {wxT(""), PRESET_MEDIUM } +static const wxArrayStringEx varModeNames { + XO("Fast"), + XO("Standard"), }; -static CHOICES sampRates[] = -{ - {wxT(""), 8000 }, - {wxT(""), 11025 }, - {wxT(""), 12000 }, - {wxT(""), 16000 }, - {wxT(""), 22050 }, - {wxT(""), 24000 }, - {wxT(""), 32000 }, - {wxT(""), 44100 }, - {wxT(""), 48000 } +static const wxArrayStringEx setRateNames { + /* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/ + XO("Insane, 320 kbps"), + XO("Extreme, 220-260 kbps"), + XO("Standard, 170-210 kbps"), + XO("Medium, 145-185 kbps"), +}; + +static const wxArrayStringEx setRateNamesShort { + /* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/ + XO("Insane"), + XO("Extreme"), + XO("Standard"), + XO("Medium"), +}; + +static const std::vector< int > sampRates { + 8000, + 11025, + 12000, + 16000, + 22050, + 24000, + 32000, + 44100, + 48000, }; #define ID_SET 7000 @@ -230,33 +219,6 @@ static CHOICES sampRates[] = #define ID_QUALITY 7004 #define ID_MONO 7005 -static void InitMP3_Statics() -{ - for (size_t i=0; i < WXSIZEOF(fixRates); i++) - fixRates[i].name = wxString::Format(_("%d kbps"), fixRates[i].label); - - varRates[0].name = wxString::Format( - _("%s kbps (Best Quality)"), varRatesNumbers[0] ); - - for (size_t i = 1; i < WXSIZEOF(varRates) - 1; i++) - varRates[i].name = wxString::Format( _("%s kbps"), varRatesNumbers[i] ); - - varRates[9].name = wxString::Format( - _("%s kbps (Smaller files)"), varRatesNumbers[9] ); - - varModes[0].name = _("Fast"); - varModes[1].name = _("Standard"); - - /* i18n-hint: Slightly humorous - as in use an insane precision with MP3.*/ - setRates[0].name = _("Insane, 320 kbps"); - setRates[1].name = _("Extreme, 220-260 kbps"); - setRates[2].name = _("Standard, 170-210 kbps"); - setRates[3].name = _("Medium, 145-185 kbps"); - - for (size_t i=0; i < WXSIZEOF(sampRates); i++) - sampRates[i].name = wxString::Format( wxT("%d"), sampRates[i].label ); -} - class ExportMP3Options final : public wxPanelWrapper { public: @@ -275,10 +237,7 @@ public: void OnQuality(wxCommandEvent& evt); void OnMono(wxCommandEvent& evt); - void LoadNames(CHOICES *choices, int count); - wxArrayString GetNames(CHOICES *choices, int count); - std::vector GetLabels(CHOICES *choices, int count); - int FindIndex(CHOICES *choices, int cnt, int needle, int def); + void LoadNames(const wxArrayStringEx &choices); private: @@ -314,8 +273,6 @@ END_EVENT_TABLE() ExportMP3Options::ExportMP3Options(wxWindow *parent, int WXUNUSED(format)) : wxPanelWrapper(parent, wxID_ANY) { - InitMP3_Statics(); - mSetRate = gPrefs->Read(wxT("/FileFormats/MP3SetRate"), PRESET_STANDARD); mVbrRate = gPrefs->Read(wxT("/FileFormats/MP3VbrRate"), QUALITY_2); mAbrRate = gPrefs->Read(wxT("/FileFormats/MP3AbrRate"), 192); @@ -391,48 +348,48 @@ void ExportMP3Options::PopulateOrExchange(ShuttleGui & S) } S.EndHorizontalLay(); - CHOICES *choices; - int cnt; + const wxArrayStringEx *choices = nullptr; + const std::vector< int > *codes = nullptr; bool enable; int defrate; if (mSET->GetValue()) { - choices = setRates; - cnt = WXSIZEOF(setRates); + choices = &setRateNames; enable = true; defrate = mSetRate; } else if (mVBR->GetValue()) { - choices = varRates; - cnt = WXSIZEOF(varRates); + choices = &varRateNames; enable = true; defrate = mVbrRate; } else if (mABR->GetValue()) { - choices = fixRates; - cnt = WXSIZEOF(fixRates); + choices = &fixRateNames; + codes = &fixRateValues; enable = false; defrate = mAbrRate; } else { mCBR->SetValue(true); - choices = fixRates; - cnt = WXSIZEOF(fixRates); + choices = &fixRateNames; + codes = &fixRateValues; enable = false; defrate = mCbrRate; } - - mRate = S.Id(ID_QUALITY).TieChoice(_("Quality"), - wxT("/FileFormats/MP3Bitrate"), - defrate, - GetNames(choices, cnt), - GetLabels(choices, cnt)); - - mMode = S.TieChoice(_("Variable Speed:"), - wxT("/FileFormats/MP3VarMode"), - ROUTINE_FAST, - GetNames(varModes, WXSIZEOF(varModes)), - GetLabels(varModes, WXSIZEOF(varModes))); + + mRate = S.Id(ID_QUALITY).TieNumberAsChoice( + _("Quality"), + wxT("/FileFormats/MP3Bitrate"), + defrate, + *choices, + codes + ); + + mMode = S.TieNumberAsChoice( + _("Variable Speed:"), + wxT("/FileFormats/MP3VarMode"), + ROUTINE_FAST, + varModeNames ); mMode->Enable(enable); S.AddPrompt(_("Channel Mode:")); @@ -484,13 +441,28 @@ bool ExportMP3Options::TransferDataFromWindow() return true; } +namespace { + +int ValidateValue( int nValues, int value, int defaultValue ) +{ + return (value >= 0 && value < nValues) ? value : defaultValue; +} +int ValidateValue( const std::vector &values, int value, int defaultValue ) +{ + auto start = values.begin(), finish = values.end(), + iter = std::find( start, finish, value ); + return ( iter != finish ) ? value : defaultValue; +} + +} + /// /// void ExportMP3Options::OnSET(wxCommandEvent& WXUNUSED(event)) { - LoadNames(setRates, WXSIZEOF(setRates)); + LoadNames(setRateNames); - mRate->SetSelection(FindIndex(setRates, WXSIZEOF(setRates), mSetRate, 2)); + mRate->SetSelection(ValidateValue(setRateNames.size(), mSetRate, 2)); mRate->Refresh(); mMode->Enable(true); } @@ -499,9 +471,9 @@ void ExportMP3Options::OnSET(wxCommandEvent& WXUNUSED(event)) /// void ExportMP3Options::OnVBR(wxCommandEvent& WXUNUSED(event)) { - LoadNames(varRates, WXSIZEOF(varRates)); + LoadNames(varRateNames); - mRate->SetSelection(FindIndex(varRates, WXSIZEOF(varRates), mVbrRate, 2)); + mRate->SetSelection(ValidateValue(varRateNames.size(), mVbrRate, 2)); mRate->Refresh(); mMode->Enable(true); } @@ -510,9 +482,9 @@ void ExportMP3Options::OnVBR(wxCommandEvent& WXUNUSED(event)) /// void ExportMP3Options::OnABR(wxCommandEvent& WXUNUSED(event)) { - LoadNames(fixRates, WXSIZEOF(fixRates)); + LoadNames(fixRateNames); - mRate->SetSelection(FindIndex(fixRates, WXSIZEOF(fixRates), mAbrRate, 10)); + mRate->SetSelection(ValidateValue(fixRateValues, mAbrRate, 10)); mRate->Refresh(); mMode->Enable(false); } @@ -521,9 +493,9 @@ void ExportMP3Options::OnABR(wxCommandEvent& WXUNUSED(event)) /// void ExportMP3Options::OnCBR(wxCommandEvent& WXUNUSED(event)) { - LoadNames(fixRates, WXSIZEOF(fixRates)); + LoadNames(fixRateNames); - mRate->SetSelection(FindIndex(fixRates, WXSIZEOF(fixRates), mCbrRate, 10)); + mRate->SetSelection(ValidateValue(fixRateValues, mCbrRate, 10)); mRate->Refresh(); mMode->Enable(false); } @@ -533,16 +505,16 @@ void ExportMP3Options::OnQuality(wxCommandEvent& WXUNUSED(event)) int sel = mRate->GetSelection(); if (mSET->GetValue()) { - mSetRate = setRates[sel].label; + mSetRate = sel; } else if (mVBR->GetValue()) { - mVbrRate = varRates[sel].label; + mVbrRate = sel; } else if (mABR->GetValue()) { - mAbrRate = fixRates[sel].label; + mAbrRate = fixRateValues[ sel ]; } else { - mCbrRate = fixRates[sel].label; + mCbrRate = fixRateValues[ sel ]; } } @@ -557,47 +529,11 @@ void ExportMP3Options::OnMono(wxCommandEvent& /*evt*/) gPrefs->Flush(); } -void ExportMP3Options::LoadNames(CHOICES *choices, int count) +void ExportMP3Options::LoadNames(const wxArrayStringEx &names) { mRate->Clear(); - - for (int i = 0; i < count; i++) - { - mRate->Append(choices[i].name); - } -} - -wxArrayString ExportMP3Options::GetNames(CHOICES *choices, int count) -{ - wxArrayString names; - - for (int i = 0; i < count; i++) { - names.push_back(choices[i].name); - } - - return names; -} - -std::vector ExportMP3Options::GetLabels(CHOICES *choices, int count) -{ - std::vector labels; - - for (int i = 0; i < count; i++) { - labels.push_back(choices[i].label); - } - - return labels; -} - -int ExportMP3Options::FindIndex(CHOICES *choices, int cnt, int needle, int def) -{ - for (int i = 0; i < cnt; i++) { - if (choices[i].label == needle) { - return i; - } - } - - return def; + for (const auto &name : names) + mRate->Append( GetCustomTranslation( name ) ); } //---------------------------------------------------------------------------- @@ -1732,8 +1668,6 @@ public: private: - int FindValue(CHOICES *choices, int cnt, int needle, int def); - wxString FindName(CHOICES *choices, int cnt, int needle); int AskResample(int bitrate, int rate, int lowrate, int highrate); unsigned long AddTags(AudacityProject *project, ArrayOf &buffer, bool *endOfFile, const Tags *tags); #ifdef USE_LIBID3TAG @@ -1745,7 +1679,6 @@ private: ExportMP3::ExportMP3() : ExportPlugin() { - InitMP3_Statics(); AddFormat(); SetFormat(wxT("MP3"),0); AddExtension(wxT("mp3"),0); @@ -1840,19 +1773,19 @@ ProgressResult ExportMP3::Export(AudacityProject *project, // Set the bitrate/quality and mode if (rmode == MODE_SET) { - int q = FindValue(setRates, WXSIZEOF(setRates), brate, PRESET_STANDARD); - int r = FindValue(varModes, WXSIZEOF(varModes), vmode, ROUTINE_FAST); + brate = ValidateValue(setRateNames.size(), brate, PRESET_STANDARD); + int r = ValidateValue( varModeNames.size(), vmode, ROUTINE_FAST ); exporter.SetMode(MODE_SET); - exporter.SetQuality(q, r); + exporter.SetQuality(brate, r); } else if (rmode == MODE_VBR) { - int q = FindValue(varRates, WXSIZEOF(varRates), brate, QUALITY_2); - int r = FindValue(varModes, WXSIZEOF(varModes), vmode, ROUTINE_FAST); + brate = ValidateValue( varRateNames.size(), brate, QUALITY_2 ); + int r = ValidateValue( varModeNames.size(), vmode, ROUTINE_FAST ); exporter.SetMode(MODE_VBR); - exporter.SetQuality(q, r); + exporter.SetQuality(brate, r); } else if (rmode == MODE_ABR) { - bitrate = FindValue(fixRates, WXSIZEOF(fixRates), brate, 128); + bitrate = brate = ValidateValue(fixRateValues, brate, 128); exporter.SetMode(MODE_ABR); exporter.SetBitrate(bitrate); @@ -1864,7 +1797,7 @@ ProgressResult ExportMP3::Export(AudacityProject *project, } } else { - bitrate = FindValue(fixRates, WXSIZEOF(fixRates), brate, 128); + bitrate = brate = ValidateValue(fixRateValues, brate, 128); exporter.SetMode(MODE_CBR); exporter.SetBitrate(bitrate); @@ -1877,7 +1810,7 @@ ProgressResult ExportMP3::Export(AudacityProject *project, } // Verify sample rate - if (FindName(sampRates, WXSIZEOF(sampRates), rate).empty() || + if (!make_iterator_range( sampRates ).contains( rate ) || (rate < lowrate) || (rate > highrate)) { rate = AskResample(bitrate, rate, lowrate, highrate); if (rate == 0) { @@ -1949,13 +1882,13 @@ ProgressResult ExportMP3::Export(AudacityProject *project, title.Printf(selectionOnly ? _("Exporting selected audio with %s preset") : _("Exporting the audio with %s preset"), - FindName(setRates, WXSIZEOF(setRates), brate)); + setRateNamesShort[brate]); } else if (rmode == MODE_VBR) { title.Printf(selectionOnly ? _("Exporting selected audio with VBR quality %s") : _("Exporting the audio with VBR quality %s"), - FindName(varRates, WXSIZEOF(varRates), brate)); + varRateNames[brate]); } else { title.Printf(selectionOnly ? @@ -2063,28 +1996,6 @@ wxWindow *ExportMP3::OptionsCreate(wxWindow *parent, int format) return safenew ExportMP3Options(parent, format); } -int ExportMP3::FindValue(CHOICES *choices, int cnt, int needle, int def) -{ - for (int i = 0; i < cnt; i++) { - if (choices[i].label == needle) { - return needle; - } - } - - return def; -} - -wxString ExportMP3::FindName(CHOICES *choices, int cnt, int needle) -{ - for (int i = 0; i < cnt; i++) { - if (choices[i].label == needle) { - return choices[i].name.BeforeFirst(wxT(',')); - } - } - - return wxT(""); -} - int ExportMP3::AskResample(int bitrate, int rate, int lowrate, int highrate) { wxDialogWrapper d(nullptr, wxID_ANY, wxString(_("Invalid sample rate"))); @@ -2114,12 +2025,12 @@ int ExportMP3::AskResample(int bitrate, int rate, int lowrate, int highrate) wxArrayStringEx choices; int selected = -1; - for (size_t i = 0; i < WXSIZEOF(sampRates); i++) { - int label = sampRates[i].label; + for (size_t ii = 0, nn = sampRates.size(); ii < nn; ++ii) { + int label = sampRates[ii]; if (label >= lowrate && label <= highrate) { - choices.push_back(sampRates[i].name); + choices.push_back( wxString::Format( "%d", label ) ); if (label <= rate) { - selected = i; + selected = ii; } } }