1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-15 08:07:41 +02:00

Non-quantitative enum preferences persist as strings not numbers...

... The one unusual choice control in Preferences that really is quantitative
is for sample rate in Quality.  And that one is changed to be treated as
not an enum preference.
This commit is contained in:
Paul Licameli 2018-03-25 14:11:37 -04:00
commit 0798681317
29 changed files with 662 additions and 263 deletions

View File

@ -184,12 +184,12 @@ inline size_t limitSampleBufferSize( size_t bufferSize, sampleCount limit )
// ----------------------------------------------------------------------------
// Supported sample formats
// ----------------------------------------------------------------------------
typedef enum
enum sampleFormat : unsigned
{
int16Sample = 0x00020001,
int24Sample = 0x00040001,
floatSample = 0x0004000F
} sampleFormat;
};
// ----------------------------------------------------------------------------
// Provide the number of bytes a specific sample will take

View File

@ -447,6 +447,7 @@ TimeTrack and AudioIOListener and whether the playback is looped.
#include "WaveTrack.h"
#include "AutoRecovery.h"
#include "prefs/QualityPrefs.h"
#include "toolbars/ControlToolBar.h"
#include "widgets/Meter.h"
#include "widgets/ErrorDialog.h"
@ -1825,8 +1826,7 @@ void AudioIO::StartMonitoring(double sampleRate)
bool success;
long captureChannels;
sampleFormat captureFormat = (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
auto captureFormat = QualityPrefs::SampleFormatChoice();
gPrefs->Read(wxT("/AudioIO/RecordChannels"), &captureChannels, 2L);
gPrefs->Read(wxT("/AudioIO/SWPlaythrough"), &mSoftwarePlaythrough, false);
int playbackChannels = 0;

View File

@ -325,17 +325,17 @@ void Dither::Apply(enum DitherType ditherType,
// We must do dithering
switch (ditherType)
{
case none:
case DitherType::none:
DITHER(NoDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
break;
case rectangle:
case DitherType::rectangle:
DITHER(RectangleDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
break;
case triangle:
case DitherType::triangle:
Reset(); // reset dither filter for this NEW conversion
DITHER(TriangleDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
break;
case shaped:
case DitherType::shaped:
Reset(); // reset dither filter for this NEW conversion
DITHER(ShapedDither, dest, destFormat, destStride, source, sourceFormat, sourceStride, len);
break;

View File

@ -13,15 +13,16 @@
#include "SampleFormat.h"
/// These ditherers are currently available:
enum class DitherType : unsigned {
none = 0, rectangle = 1, triangle = 2, shaped = 3 };
class Dither
{
public:
/// Default constructor
Dither();
/// These ditherers are currently available:
enum DitherType { none = 0, rectangle = 1, triangle = 2, shaped = 3};
/// Reset state of the dither.
void Reset();

View File

@ -6817,10 +6817,8 @@ void AudacityProject::OnZoomToggle(const CommandContext &WXUNUSED(context) )
// const double origWidth = GetScreenEndTime() - origLeft;
// Choose the zoom that is most different to the current zoom.
double Zoom1 = GetZoomOfPref(
wxT("/GUI/ZoomPreset1"), WaveTrack::kZoomDefault );
double Zoom2 = GetZoomOfPref(
wxT("/GUI/ZoomPreset2"), WaveTrack::kZoom4To1 );
double Zoom1 = GetZoomOfPreset( TracksPrefs::Zoom1Choice() );
double Zoom2 = GetZoomOfPreset( TracksPrefs::Zoom2Choice() );
double Z = mViewInfo.GetZoom();// Current Zoom.
double ChosenZoom = abs(log(Zoom1 / Z)) > abs(log( Z / Zoom2)) ? Zoom1:Zoom2;

View File

@ -341,3 +341,90 @@ void FinishPreferences()
gPrefs = NULL;
}
}
//////////
wxString EnumSetting::Read() const
{
const auto &defaultValue = Default().Internal();
wxString value;
if ( !gPrefs->Read(mKey, &value, defaultValue) )
if (!mMigrated) {
const_cast<EnumSetting*>(this)->Migrate( value );
mMigrated = true;
}
// Remap to default if the string is not known -- this avoids surprises
// in case we try to interpret config files from future versions
auto index = Find( value );
if ( index >= mnSymbols )
value = defaultValue;
return value;
}
size_t EnumSetting::Find( const wxString &value ) const
{
return size_t(
std::find( begin(), end(), IdentInterfaceSymbol{ value, {} } )
- mSymbols );
}
void EnumSetting::Migrate( wxString &value )
{
}
bool EnumSetting::Write( const wxString &value )
{
auto index = Find( value );
if (index >= mnSymbols)
return false;
auto result = gPrefs->Write( mKey, value );
mMigrated = true;
return result;
}
int EncodedEnumSetting::ReadInt() const
{
if (!mIntValues)
return 0;
auto index = Find( Read() );
wxASSERT( index < mnSymbols );
return mIntValues[ index ];
}
size_t EncodedEnumSetting::FindInt( int code ) const
{
if (!mIntValues)
return mnSymbols;
return size_t(
std::find( mIntValues, mIntValues + mnSymbols, code )
- mIntValues );
}
void EncodedEnumSetting::Migrate( wxString &value )
{
int intValue = 0;
if ( !mOldKey.empty() &&
gPrefs->Read(mOldKey, &intValue, 0) ) {
// Make the migration, only once and persistently.
// Do not DELETE the old key -- let that be read if user downgrades
// Audacity. But further changes will be stored only to the NEW key
// and won't be seen then.
auto index = FindInt( intValue );
if ( index >= mnSymbols )
index = mDefaultSymbol;
value = mSymbols[index].Internal();
Write(value);
gPrefs->Flush();
}
}
bool EncodedEnumSetting::WriteInt( int code ) // you flush gPrefs afterward
{
auto index = FindInt( code );
if ( index >= mnSymbols )
return false;
return Write( mSymbols[index].Internal() );
}

View File

@ -30,6 +30,7 @@
#define __AUDACITY_PREFS__
#include "Audacity.h"
#include "../include/audacity/IdentInterface.h"
#include <wx/config.h>
#include <wx/fileconf.h>
@ -40,4 +41,84 @@ void FinishPreferences();
extern AUDACITY_DLL_API wxFileConfig *gPrefs;
extern int gMenusDirty;
// Packages a table of user-visible choices each with an internal code string,
// a preference key path,
// and a default choice
class EnumSetting
{
public:
EnumSetting(
const wxString &key,
const IdentInterfaceSymbol symbols[], size_t nSymbols,
size_t defaultSymbol
)
: mKey{ key }
, mSymbols{ symbols }
, mnSymbols{ nSymbols }
, mDefaultSymbol{ defaultSymbol }
{
wxASSERT( defaultSymbol < nSymbols );
}
const wxString &Key() const { return mKey; }
const IdentInterfaceSymbol &Default() const
{ return mSymbols[mDefaultSymbol]; }
const IdentInterfaceSymbol *begin() const { return mSymbols; }
const IdentInterfaceSymbol *end() const { return mSymbols + mnSymbols; }
wxString Read() const;
bool Write( const wxString &value ); // you flush gPrefs afterward
protected:
size_t Find( const wxString &value ) const;
virtual void Migrate( wxString& );
const wxString mKey;
const IdentInterfaceSymbol *mSymbols;
const size_t mnSymbols;
// stores an internal value
mutable bool mMigrated { false };
const size_t mDefaultSymbol;
};
// Extends EnumSetting with a corresponding table of integer codes
// (generally not equal to their table positions),
// and optionally an old preference key path that stored integer codes, to be
// migrated into one that stores internal string values instead
class EncodedEnumSetting : public EnumSetting
{
public:
EncodedEnumSetting(
const wxString &key,
const IdentInterfaceSymbol symbols[], size_t nSymbols,
size_t defaultSymbol,
const int intValues[] = nullptr, // must have same size as symbols
const wxString &oldKey = {}
)
: EnumSetting{ key, symbols, nSymbols, defaultSymbol }
, mIntValues{ intValues }
, mOldKey{ oldKey }
{
wxASSERT( mIntValues );
}
// Read and write the encoded values
virtual int ReadInt() const;
bool WriteInt( int code ); // you flush gPrefs afterward
protected:
size_t FindInt( int code ) const;
void Migrate( wxString& ) override;
private:
const int *mIntValues;
const wxString mOldKey;
};
#endif

View File

@ -166,6 +166,8 @@ scroll information. It also has some status flags.
#include "commands/CommandType.h"
#include "commands/CommandContext.h"
#include "prefs/QualityPrefs.h"
#include "../images/AudacityLogoAlpha.xpm"
std::shared_ptr<TrackList> AudacityProject::msClipboard{ TrackList::Create() };
@ -917,8 +919,7 @@ AudacityProject::AudacityProject(wxWindow * parent, wxWindowID id,
mViewInfo(0.0, 1.0, ZoomInfo::GetDefaultZoom()),
mbLoadedFromAup( false ),
mRate((double) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"), AudioIO::GetOptimalSupportedSampleRate())),
mDefaultFormat((sampleFormat) gPrefs->
Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample)),
mDefaultFormat(QualityPrefs::SampleFormatChoice()),
mSnapTo(gPrefs->Read(wxT("/SnapTo"), SNAP_OFF)),
mSelectionFormat(gPrefs->Read(wxT("/SelectionFormat"), wxT(""))),
mFrequencySelectionFormatName(gPrefs->Read(wxT("/FrequencySelectionFormatName"), wxT(""))),
@ -1305,7 +1306,7 @@ void AudacityProject::UpdatePrefsVariables()
// gPrefs->Read(wxT("/GUI/UpdateSpectrogram"), &mViewInfo.bUpdateSpectrogram, true);
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleRate"), &mRate, AudioIO::GetOptimalSupportedSampleRate());
mDefaultFormat = (sampleFormat) gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
mDefaultFormat = QualityPrefs::SampleFormatChoice();
gPrefs->Read(wxT("/AudioIO/SeekShortPeriod"), &mSeekShort, 1.0);
gPrefs->Read(wxT("/AudioIO/SeekLongPeriod"), &mSeekLong, 15.0);
@ -5887,8 +5888,7 @@ wxString AudacityProject::GetHoursMinsString(int iMinutes)
int AudacityProject::GetEstimatedRecordingMinsLeftOnDisk(long lCaptureChannels) {
// Obtain the current settings
sampleFormat oCaptureFormat = (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
auto oCaptureFormat = QualityPrefs::SampleFormatChoice();
if (lCaptureChannels == 0) {
gPrefs->Read(wxT("/AudioIO/RecordChannels"), &lCaptureChannels, 2L);
}
@ -6014,12 +6014,6 @@ double AudacityProject::GetZoomOfPreset( int preset ){
return result;
}
double AudacityProject::GetZoomOfPref( const wxString & PresetPrefName, int defaultPreset ){
int preset=defaultPreset;
gPrefs->Read( PresetPrefName, &preset, defaultPreset );
return GetZoomOfPreset( preset );
}
AudacityProject::PlaybackScroller::PlaybackScroller(AudacityProject *project)
: mProject(project)
{

View File

@ -600,7 +600,6 @@ public:
double GetZoomOfToFit();
double GetZoomOfSelection();
double GetZoomOfPreset(int preset );
double GetZoomOfPref( const wxString & PresetPrefName, int defaultPreset );
public:
bool IsSoloSimple() const { return mSoloPref == wxT("Simple"); }

View File

@ -26,6 +26,7 @@
#include "Prefs.h"
#include "TranslatableStringArray.h"
#include "Internat.h"
#include "../include/audacity/IdentInterface.h"
#include <soxr.h>
@ -50,47 +51,57 @@ Resample::~Resample()
{
}
int Resample::GetNumMethods() { return 4; }
//////////
static const IdentInterfaceSymbol methodNames[] = {
{ wxT("LowQuality"), XO("Low Quality (Fastest)") },
{ wxT("MediumQuality"), XO("Medium Quality") },
{ wxT("HighQuality"), XO("High Quality") },
{ wxT("BestQuality"), XO("Best Quality (Slowest)") }
};
wxString Resample::GetMethodName(int index)
static const size_t numMethods = WXSIZEOF(methodNames);
static const wxString fastMethodKey =
wxT("/Quality/LibsoxrSampleRateConverterChoice");
static const wxString bestMethodKey =
wxT("/Quality/LibsoxrHQSampleRateConverterChoice");
static const wxString oldFastMethodKey =
wxT("/Quality/LibsoxrSampleRateConverter");
static const wxString oldBestMethodKey =
wxT("/Quality/LibsoxrHQSampleRateConverter");
static const size_t fastMethodDefault = 1; // Medium Quality
static const size_t bestMethodDefault = 3; // Best Quality
static const int intChoicesMethod[] = {
0, 1, 2, 3
};
static_assert( WXSIZEOF(intChoicesMethod) == numMethods, "size mismatch" );
EncodedEnumSetting Resample::FastMethodSetting{
fastMethodKey,
methodNames, numMethods,
fastMethodDefault,
intChoicesMethod,
oldFastMethodKey
};
EncodedEnumSetting Resample::BestMethodSetting
{
static const wxString soxr_method_names[] = {
XO("Low Quality (Fastest)"),
XO("Medium Quality"),
XO("High Quality"),
XO("Best Quality (Slowest)")
};
bestMethodKey,
methodNames, numMethods,
bestMethodDefault,
wxASSERT( GetNumMethods() ==
sizeof(soxr_method_names) / sizeof(*soxr_method_names) );
class MethodNamesArray final : public TranslatableStringArray
{
void Populate() override
{
for (auto &name : soxr_method_names)
mContents.push_back( wxGetTranslation( name ) );
}
};
static MethodNamesArray theArray;
return theArray.Get()[ index ];
}
const wxString Resample::GetFastMethodKey()
{
return wxT("/Quality/LibsoxrSampleRateConverter");
}
const wxString Resample::GetBestMethodKey()
{
return wxT("/Quality/LibsoxrHQSampleRateConverter");
}
int Resample::GetFastMethodDefault() {return 1;}
int Resample::GetBestMethodDefault() {return 3;}
intChoicesMethod,
oldBestMethodKey
};
//////////
std::pair<size_t, size_t>
Resample::Process(double factor,
float *inBuffer,
@ -121,7 +132,7 @@ std::pair<size_t, size_t>
void Resample::SetMethod(const bool useBestMethod)
{
if (useBestMethod)
mMethod = gPrefs->Read(GetBestMethodKey(), GetBestMethodDefault());
mMethod = BestMethodSetting.ReadInt();
else
mMethod = gPrefs->Read(GetFastMethodKey(), GetFastMethodDefault());
mMethod = FastMethodSetting.ReadInt();
}

View File

@ -20,6 +20,8 @@
#include "SampleFormat.h"
class EncodedEnumSetting;
struct soxr;
extern "C" void soxr_delete(soxr*);
struct soxr_deleter {
@ -43,13 +45,8 @@ class Resample final
Resample(const bool useBestMethod, const double dMinFactor, const double dMaxFactor);
~Resample();
static int GetNumMethods();
static wxString GetMethodName(int index);
static const wxString GetFastMethodKey();
static const wxString GetBestMethodKey();
static int GetFastMethodDefault();
static int GetBestMethodDefault();
static EncodedEnumSetting FastMethodSetting;
static EncodedEnumSetting BestMethodSetting;
/** @brief Main processing function. Resamples from the input buffer to the
* output buffer.

View File

@ -44,19 +44,17 @@
#include "Prefs.h"
#include "Dither.h"
#include "Internat.h"
#include "prefs/QualityPrefs.h"
static Dither::DitherType gLowQualityDither = Dither::none;
static Dither::DitherType gHighQualityDither = Dither::none;
static DitherType gLowQualityDither = DitherType::none;
static DitherType gHighQualityDither = DitherType::none;
static Dither gDitherAlgorithm;
void InitDitherers()
{
// Read dither preferences
gLowQualityDither = (Dither::DitherType)
gPrefs->Read(wxT("/Quality/DitherAlgorithm"), (long)Dither::none);
gHighQualityDither = (Dither::DitherType)
gPrefs->Read(wxT("/Quality/HQDitherAlgorithm"), (long)Dither::shaped);
gLowQualityDither = QualityPrefs::FastDitherChoice();
gHighQualityDither = QualityPrefs::BestDitherChoice();
}
const wxChar *GetSampleFormatStr(sampleFormat format)
@ -120,6 +118,6 @@ void CopySamplesNoDither(samplePtr src, sampleFormat srcFormat,
unsigned int dstStride /* = 1 */)
{
gDitherAlgorithm.Apply(
Dither::none,
DitherType::none,
src, srcFormat, dst, dstFormat, len, srcStride, dstStride);
}

View File

@ -1040,7 +1040,7 @@ void Sequence::WriteXML(XMLWriter &xmlFile) const
xmlFile.StartTag(wxT("sequence"));
xmlFile.WriteAttr(wxT("maxsamples"), mMaxSamples);
xmlFile.WriteAttr(wxT("sampleformat"), mSampleFormat);
xmlFile.WriteAttr(wxT("sampleformat"), (size_t)mSampleFormat);
xmlFile.WriteAttr(wxT("numsamples"), mNumSamples.as_long_long() );
for (b = 0; b < mBlock.size(); b++) {

View File

@ -95,6 +95,7 @@ for registering for changes.
#include "Audacity.h"
#include "Experimental.h"
#include "Prefs.h"
#include "Shuttle.h"
#include "ShuttleGui.h"
@ -106,6 +107,7 @@ for registering for changes.
#include <wx/treectrl.h>
#include <wx/spinctrl.h>
#include <wx/bmpbuttn.h>
#include "../include/audacity/IdentInterface.h"
#include "Internat.h"
#include "WrappedType.h"
#include "widgets/wxPanelWrapper.h"
@ -1847,32 +1849,55 @@ wxTextCtrl * ShuttleGuiBase::TieNumericTextBox(
return pText;
}
/// Variant of the standard TieChoice which does the two step exchange
/// between gui and stack variable and stack variable and shuttle.
/// @param Prompt The prompt shown beside the control.
/// @param Setting Encapsulates setting name, internal and visible
/// choice strings, and a designation of one of
/// those as default.
wxChoice *ShuttleGuiBase::TieChoice(
const wxString &Prompt,
EnumSetting &enumSetting )
{
// Do this to force any needed migrations first
enumSetting.Read();
wxArrayString visibleChoices, internalChoices;
for (const auto &ident : enumSetting) {
visibleChoices.push_back( ident.Translation() );
internalChoices.push_back( ident.Internal() );
}
return TieChoice(
Prompt, enumSetting.Key(), enumSetting.Default().Translation(),
visibleChoices, internalChoices );
}
/// Variant of the standard TieChoice which does the two step exchange
/// between gui and stack variable and stack variable and shuttle.
/// @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 TranslatedChoices The corresponding values (as a string array)
/// @param InternalChoices The corresponding values (as a string array)
wxChoice * ShuttleGuiBase::TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const wxString &Default,
const wxArrayString & Choices,
const wxArrayString & TranslatedChoices)
const wxArrayString & InternalChoices)
{
wxChoice * pChoice=(wxChoice*)NULL;
int TempIndex=0;
// int TempIndex = TranslateToIndex( Default, TranslatedChoices );
// int TempIndex = TranslateToIndex( Default, InternalChoices );
wxString TempStr = Default;
WrappedType WrappedRef( TempStr );
// Get from prefs does 1 and 2.
// Put to prefs does 2 and 3.
if( DoStep(1) ) DoDataShuttle( SettingName, WrappedRef ); // Get Index from Prefs.
if( DoStep(1) ) TempIndex = TranslateToIndex( TempStr, TranslatedChoices ); // To an index
if( DoStep(1) ) TempIndex = TranslateToIndex( TempStr, InternalChoices ); // To an index
if( DoStep(2) ) pChoice = TieChoice( Prompt, TempIndex, &Choices ); // Get/Put index from GUI.
if( DoStep(3) ) TempStr = TranslateFromIndex( TempIndex, TranslatedChoices ); // To a string
if( DoStep(3) ) TempStr = TranslateFromIndex( TempIndex, InternalChoices ); // To a string
if( DoStep(3) ) DoDataShuttle( SettingName, WrappedRef ); // Put into Prefs.
return pChoice;
}
@ -1885,13 +1910,13 @@ wxChoice * ShuttleGuiBase::TieChoice(
/// @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 TranslatedChoices The correcponding values (as an integer array)
/// @param InternalChoices The corresponding values (as an integer array)
wxChoice * ShuttleGuiBase::TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayString & Choices,
const std::vector<int> & TranslatedChoices)
const std::vector<int> & InternalChoices)
{
wxChoice * pChoice=(wxChoice*)NULL;
@ -1901,13 +1926,34 @@ wxChoice * ShuttleGuiBase::TieChoice(
// 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, TranslatedChoices ); // Int to an index.
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, TranslatedChoices ); // Index to int
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.
/// Behaves identically to the previous, but is meant for use when the choices
/// are non-exhaustive and there is a companion control for abitrary entry.
/// @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::TieNumberAsChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayString & Choices,
const std::vector<int> & InternalChoices)
{
return ShuttleGuiBase::TieChoice(
Prompt, SettingName, Default, Choices, InternalChoices );
}
/// Integer specific version of StartRadioButtonGroup.
/// All 'TieRadioButton()' enclosed must be ints.
void ShuttleGuiBase::StartRadioButtonGroup( const wxString & SettingName, const int iDefaultValue )
@ -2391,7 +2437,7 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice(
const wxString &SettingName,
const wxString &Default,
const wxArrayString &Choices,
const wxArrayString & TranslatedChoices )
const wxArrayString & InternalChoices )
{
StartStruct();
AddItem( SettingName, "id" );
@ -2405,15 +2451,22 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice(
EndArray();
EndField();
EndStruct();
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, TranslatedChoices );
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, InternalChoices );
}
wxChoice * ShuttleGuiGetDefinition::TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayString & Choices,
const std::vector<int> & TranslatedChoices)
const std::vector<int> & 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" );
@ -2426,7 +2479,26 @@ wxChoice * ShuttleGuiGetDefinition::TieChoice(
EndArray();
EndField();
EndStruct();
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, TranslatedChoices );
return ShuttleGui::TieChoice( Prompt, SettingName, Default, Choices, InternalChoices );
}
wxChoice * ShuttleGuiGetDefinition::TieNumberAsChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayString & Choices,
const std::vector<int> & InternalChoices)
{
// Come here for controls that present non-exhaustive choices among some
// numbers, with an associated control that allows arbitrary entry of an
// "Other..."
StartStruct();
AddItem( SettingName, "id" );
AddItem( Prompt, "prompt" );
AddItem( "number", "type" ); // not "enum" !
AddItem( Default, "default" );
EndStruct();
return ShuttleGui::TieNumberAsChoice(
Prompt, SettingName, Default, Choices, InternalChoices );
}
wxTextCtrl * ShuttleGuiGetDefinition::TieTextBox(
const wxString &Prompt,

View File

@ -27,6 +27,9 @@
// For ShuttleGuiGetDefinitions.
#include "commands/CommandTargets.h"
class EnumSetting;
const int nMaxNestedSizers = 20;
enum teShuttleMode
@ -209,18 +212,42 @@ public:
const wxString &Prompt,
const wxString &SettingName,
const bool bDefault);
// This one is defined in terms of the next and not virtual
virtual wxChoice *TieChoice(
const wxString &Prompt,
EnumSetting &enumSetting );
virtual wxChoice * TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const wxString &Default,
const wxArrayString &Choices,
const wxArrayString & TranslatedChoices );
const wxArrayString & 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 wxArrayString & Choices,
const std::vector<int> & TranslatedChoices);
const std::vector<int> & InternalChoices );
// This overload presents what is really a numerical setting as a choice among
// commonly used values, but the choice is not exhaustive because there is
// also an associated control that allows entry of a user-specified value
// that is arbitrary (within some bounds).
// This behaves just like the previous for building dialogs, but the
// behavior is different when the call is intercepted for purposes of
// emitting scripting information about Preferences.
virtual wxChoice * TieNumberAsChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayString & Choices,
const std::vector<int> & InternalChoices );
virtual wxTextCtrl * TieTextBox(
const wxString &Prompt,
const wxString &SettingName,
@ -421,13 +448,23 @@ public:
const wxString &SettingName,
const wxString &Default,
const wxArrayString &Choices,
const wxArrayString & TranslatedChoices ) override;
const wxArrayString & InternalChoices ) override;
// An assertion will be violated if this override is reached!
wxChoice * TieChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayString & Choices,
const std::vector<int> & TranslatedChoices) override;
const std::vector<int> & InternalChoices) override;
wxChoice * TieNumberAsChoice(
const wxString &Prompt,
const wxString &SettingName,
const int Default,
const wxArrayString & Choices,
const std::vector<int> & InternalChoices) override;
wxTextCtrl * TieTextBox(
const wxString &Prompt,
const wxString &SettingName,

View File

@ -176,6 +176,7 @@ audio tracks.
#include "Prefs.h"
#include "prefs/GUISettings.h"
#include "prefs/SpectrogramSettings.h"
#include "prefs/TracksPrefs.h"
#include "prefs/WaveformSettings.h"
#include "Spectrum.h"
#include "ViewInfo.h"
@ -3311,7 +3312,7 @@ void TrackArtist::UpdatePrefs()
{
mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange);
mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping);
gPrefs->Read(wxT("/GUI/SampleView"), &mSampleDisplay, 1);
mSampleDisplay = TracksPrefs::SampleViewChoice();
SetColours(0);
}

View File

@ -179,7 +179,7 @@ class AUDACITY_DLL_API TrackArtist {
// Preference values
float mdBrange; // "/GUI/EnvdBRange"
long mShowClipping; // "/GUI/ShowClipping"
int mSampleDisplay; // "/GUI/SampleView"
int mSampleDisplay;
bool mbShowTrackNameInWaveform; // "/GUI/ShowTrackNameInWaveform"
int mMarginLeft;

View File

@ -96,7 +96,7 @@ WaveTrack::WaveTrack(const std::shared_ptr<DirManager> &projDirManager, sampleFo
// Force creation always:
WaveformSettings &settings = GetIndependentWaveformSettings();
mDisplay = FindDefaultViewMode();
mDisplay = TracksPrefs::ViewModeChoice();
if (mDisplay == obsoleteWaveformDBDisplay) {
mDisplay = Waveform;
settings.scaleType = WaveformSettings::stLogarithmic;
@ -254,32 +254,6 @@ void WaveTrack::SetPanFromChannelType()
};
//static
WaveTrack::WaveTrackDisplay WaveTrack::FindDefaultViewMode()
{
// PRL: Bugs 1043, 1044
// 2.1.1 writes a NEW key for this preference, which got NEW values,
// to avoid confusing version 2.1.0 if it reads the preference file afterwards.
// Prefer the NEW preference key if it is present
WaveTrack::WaveTrackDisplay viewMode;
gPrefs->Read(wxT("/GUI/DefaultViewModeNew"), &viewMode, -1);
// Default to the old key only if not, default the value if it's not there either
wxASSERT(WaveTrack::MinDisplay >= 0);
if (viewMode < 0) {
int oldMode;
gPrefs->Read(wxT("/GUI/DefaultViewMode"), &oldMode,
(int)(WaveTrack::Waveform));
viewMode = WaveTrack::ConvertLegacyDisplayValue(oldMode);
}
// Now future-proof 2.1.1 against a recurrence of this sort of bug!
viewMode = WaveTrack::ValidateWaveTrackDisplay(viewMode);
return viewMode;
}
// static
WaveTrack::WaveTrackDisplay
WaveTrack::ConvertLegacyDisplayValue(int oldValue)

View File

@ -578,9 +578,6 @@ private:
kMaxZoom,
};
// Read appropriate value from preferences
static WaveTrackDisplay FindDefaultViewMode();
// Handle remapping of enum values from 2.1.0 and earlier
static WaveTrackDisplay ConvertLegacyDisplayValue(int oldValue);

View File

@ -42,6 +42,7 @@
#include "ImportPlugin.h"
#include "../Tags.h"
#include "../prefs/QualityPrefs.h"
#include "../Experimental.h"
@ -350,8 +351,7 @@ FLACImportFileHandle::FLACImportFileHandle(const wxString & name)
mStreamInfoDone(false),
mUpdateResult(ProgressResult::Success)
{
mFormat = (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
mFormat = QualityPrefs::SampleFormatChoice();
mFile = std::make_unique<MyFLACFile>(this);
}

View File

@ -45,6 +45,7 @@
#include "ImportPlugin.h"
#include "../Internat.h"
#include "../Tags.h"
#include "../prefs/QualityPrefs.h"
#define DESC _("MP3 files")
@ -498,8 +499,7 @@ enum mad_flow output_cb(void *_data,
if(data->channels.empty()) {
data->channels.resize(channels);
sampleFormat format = (sampleFormat) gPrefs->
Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
auto format = QualityPrefs::SampleFormatChoice();
for(auto &channel: data->channels) {
channel = data->trackFactory->NewWaveTrack(format, samplerate);

View File

@ -42,6 +42,7 @@
#include "../Prefs.h"
#include "../Internat.h"
#include "../Tags.h"
#include "../prefs/QualityPrefs.h"
#define DESC _("Ogg Vorbis files")
@ -108,8 +109,7 @@ public:
mVorbisFile(std::move(vorbisFile))
, mStreamUsage{ static_cast<size_t>(mVorbisFile->links) }
{
mFormat = (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
mFormat = QualityPrefs::SampleFormatChoice();
for (int i = 0; i < mVorbisFile->links; i++)
{

View File

@ -38,6 +38,7 @@
#include "../ondemand/ODManager.h"
#include "../ondemand/ODComputeSummaryTask.h"
#include "../prefs/QualityPrefs.h"
//If OD is enabled, he minimum number of samples a file has to use it.
//Otherwise, we use the older PCMAliasBlockFile method since it should be fast enough.
@ -204,8 +205,7 @@ PCMImportFileHandle::PCMImportFileHandle(wxString name,
// the quality of the original file.
//
mFormat = (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
mFormat = QualityPrefs::SampleFormatChoice();
if (mFormat != floatSample &&
sf_subtype_more_than_16_bits(mInfo.format))

View File

@ -34,6 +34,7 @@ and sample size to help you importing data of an unknown format.
#include "../ShuttleGui.h"
#include "../UserException.h"
#include "../WaveTrack.h"
#include "../prefs/QualityPrefs.h"
#include <cmath>
#include <cstdio>
@ -193,8 +194,7 @@ void ImportRaw(wxWindow *parent, const wxString &fileName,
// the quality of the original file.
//
format = (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);
format = QualityPrefs::SampleFormatChoice();
if (format != floatSample &&
sf_subtype_more_than_16_bits(encoding))

View File

@ -225,8 +225,7 @@ bool ODFlacDecoder::ReadHeader()
{
mFormat = int16Sample;//start with the smallest and move up in the metadata_callback.
//we want to use the native flac type for quick conversion.
/* (sampleFormat)
gPrefs->Read(wxT("/SamplingRate/DefaultProjectSampleFormat"), floatSample);*/
/* QualityPrefs::SampleFormatChoice(); */
mFile = std::make_unique<ODFLACFile>(this);

View File

@ -30,6 +30,70 @@
#define ID_SAMPLE_RATE_CHOICE 7001
//////////
static const IdentInterfaceSymbol choicesFormat[] = {
{ wxT("Format16Bit"), XO("16-bit") },
{ wxT("Format24Bit"), XO("24-bit") },
{ wxT("Format32BitFloat"), XO("32-bit float") }
};
static const size_t nChoicesFormat = WXSIZEOF( choicesFormat );
static const int intChoicesFormat[] = {
int16Sample,
int24Sample,
floatSample
};
static_assert( nChoicesFormat == WXSIZEOF(intChoicesFormat), "size mismatch" );
static const size_t defaultChoiceFormat = 2; // floatSample
static EncodedEnumSetting formatSetting{
wxT("/SamplingRate/DefaultProjectSampleFormatChoice"),
choicesFormat, nChoicesFormat, defaultChoiceFormat,
intChoicesFormat,
wxT("/SamplingRate/DefaultProjectSampleFormat"),
};
//////////
static const IdentInterfaceSymbol choicesDither[] = {
{ XO("None") },
{ XO("Rectangle") },
{ XO("Triangle") },
{ XO("Shaped") },
};
static const size_t nChoicesDither = WXSIZEOF( choicesDither );
static const int intChoicesDither[] = {
(int) DitherType::none,
(int) DitherType::rectangle,
(int) DitherType::triangle,
(int) DitherType::shaped,
};
static_assert(
nChoicesDither == WXSIZEOF( intChoicesDither ),
"size mismatch"
);
static const int defaultFastDither = 0; // none
static EncodedEnumSetting fastDitherSetting{
wxT("Quality/DitherAlgorithmChoice"),
choicesDither, nChoicesDither, defaultFastDither,
intChoicesDither,
wxT("Quality/DitherAlgorithm")
};
static const int defaultBestDither = 3; // shaped
static EncodedEnumSetting bestDitherSetting{
wxT("Quality/HQDitherAlgorithmChoice"),
choicesDither, nChoicesDither, defaultBestDither,
intChoicesDither,
wxT("Quality/HQDitherAlgorithm")
};
//////////
BEGIN_EVENT_TABLE(QualityPrefs, PrefsPanel)
EVT_CHOICE(ID_SAMPLE_RATE_CHOICE, QualityPrefs::OnSampleRateChoice)
END_EVENT_TABLE()
@ -71,12 +135,6 @@ void QualityPrefs::Populate()
/// The corresponding labels are what gets stored.
void QualityPrefs::GetNamesAndLabels()
{
//------------ Dither Names
mDitherNames.Add(_("None")); mDitherLabels.push_back(Dither::none);
mDitherNames.Add(_("Rectangle")); mDitherLabels.push_back(Dither::rectangle);
mDitherNames.Add(_("Triangle")); mDitherLabels.push_back(Dither::triangle);
mDitherNames.Add(_("Shaped")); mDitherLabels.push_back(Dither::shaped);
//------------ Sample Rate Names
// JKC: I don't understand the following comment.
// Can someone please explain or correct it?
@ -101,18 +159,6 @@ void QualityPrefs::GetNamesAndLabels()
// The label for the 'Other...' case can be any value at all.
mSampleRateLabels.push_back(44100); // If chosen, this value will be overwritten
//------------- Sample Format Names
mSampleFormatNames.Add(wxT("16-bit")); mSampleFormatLabels.push_back(int16Sample);
mSampleFormatNames.Add(wxT("24-bit")); mSampleFormatLabels.push_back(int24Sample);
mSampleFormatNames.Add(wxT("32-bit float")); mSampleFormatLabels.push_back(floatSample);
//------------- Converter Names
int numConverters = Resample::GetNumMethods();
for (int i = 0; i < numConverters; i++) {
mConverterNames.Add(Resample::GetMethodName(i));
mConverterLabels.push_back(i);
}
}
void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
@ -135,7 +181,7 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
// We make sure it uses the ID we want, so that we get changes
S.Id(ID_SAMPLE_RATE_CHOICE);
// We make sure we have a pointer to it, so that we can drive it.
mSampleRates = S.TieChoice( {},
mSampleRates = S.TieNumberAsChoice( {},
wxT("/SamplingRate/DefaultProjectSampleRate"),
AudioIO::GetOptimalSupportedSampleRate(),
mSampleRateNames,
@ -149,10 +195,7 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
S.EndHorizontalLay();
S.TieChoice(_("Default Sample &Format:"),
wxT("/SamplingRate/DefaultProjectSampleFormat"),
floatSample,
mSampleFormatNames,
mSampleFormatLabels);
formatSetting);
}
S.EndMultiColumn();
}
@ -163,17 +206,11 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
S.StartMultiColumn(2, wxEXPAND);
{
S.TieChoice(_("Sample Rate Con&verter:"),
Resample::GetFastMethodKey(),
Resample::GetFastMethodDefault(),
mConverterNames,
mConverterLabels);
Resample::FastMethodSetting);
/* i18n-hint: technical term for randomization to reduce undesirable resampling artifacts */
S.TieChoice(_("&Dither:"),
wxT("/Quality/DitherAlgorithm"),
Dither::none,
mDitherNames,
mDitherLabels);
fastDitherSetting);
}
S.EndMultiColumn();
}
@ -184,17 +221,11 @@ void QualityPrefs::PopulateOrExchange(ShuttleGui & S)
S.StartMultiColumn(2);
{
S.TieChoice(_("Sample Rate Conver&ter:"),
Resample::GetBestMethodKey(),
Resample::GetBestMethodDefault(),
mConverterNames,
mConverterLabels);
Resample::BestMethodSetting);
/* i18n-hint: technical term for randomization to reduce undesirable resampling artifacts */
S.TieChoice(_("Dit&her:"),
wxT("/Quality/HQDitherAlgorithm"),
Dither::shaped,
mDitherNames,
mDitherLabels);
bestDitherSetting);
}
S.EndMultiColumn();
}
@ -239,3 +270,19 @@ PrefsPanel *QualityPrefsFactory::operator () (wxWindow *parent, wxWindowID winid
wxASSERT(parent); // to justify safenew
return safenew QualityPrefs(parent, winid);
}
sampleFormat QualityPrefs::SampleFormatChoice()
{
return (sampleFormat)formatSetting.ReadInt();
}
DitherType QualityPrefs::FastDitherChoice()
{
return (DitherType) fastDitherSetting.ReadInt();
}
DitherType QualityPrefs::BestDitherChoice()
{
return (DitherType) bestDitherSetting.ReadInt();
}

View File

@ -22,6 +22,8 @@
#include "PrefsPanel.h"
class ShuttleGui;
enum sampleFormat : unsigned;
enum class DitherType : unsigned;
class QualityPrefs final : public PrefsPanel
{
@ -33,19 +35,18 @@ class QualityPrefs final : public PrefsPanel
wxString HelpPageName() override;
void PopulateOrExchange(ShuttleGui & S) override;
static sampleFormat SampleFormatChoice();
static DitherType FastDitherChoice();
static DitherType BestDitherChoice();
private:
void Populate();
void GetNamesAndLabels();
void OnSampleRateChoice(wxCommandEvent & e);
wxArrayString mDitherNames;
std::vector<int> mDitherLabels;
wxArrayString mSampleRateNames;
std::vector<int> mSampleRateLabels;
wxArrayString mSampleFormatNames;
std::vector<int> mSampleFormatLabels;
wxArrayString mConverterNames;
std::vector<int> mConverterLabels;
wxChoice *mSampleRates;
wxTextCtrl *mOtherSampleRate;

View File

@ -45,17 +45,182 @@ namespace {
}
//////////
static const IdentInterfaceSymbol choicesView[] = {
{ XO("Waveform") },
{ wxT("WaveformDB"), XO("Waveform (dB)") },
{ XO("Spectrogram") }
};
static const int intChoicesView[] = {
(int)(WaveTrack::Waveform),
(int)(WaveTrack::obsoleteWaveformDBDisplay),
(int)(WaveTrack::Spectrum)
};
static const size_t nChoicesView = WXSIZEOF(choicesView);
static_assert( nChoicesView == WXSIZEOF(intChoicesView), "size mismatch" );
static const size_t defaultChoiceView = 0;
class TracksViewModeSetting : public EncodedEnumSetting {
public:
TracksViewModeSetting(
const wxString &key,
const IdentInterfaceSymbol symbols[], size_t nSymbols,
size_t defaultSymbol,
const int intValues[],
const wxString &oldKey
)
: EncodedEnumSetting{
key, symbols, nSymbols, defaultSymbol, intValues, oldKey }
{}
void Migrate( wxString &value ) override
{
// Special logic for this preference which was twice migrated!
// First test for the older but not oldest key:
EncodedEnumSetting::Migrate(value);
if (!value.empty())
return;
// PRL: Bugs 1043, 1044
// 2.1.1 writes a NEW key for this preference, which got NEW values,
// to avoid confusing version 2.1.0 if it reads the preference file afterwards.
// Prefer the NEW preference key if it is present
int oldMode;
gPrefs->Read(wxT("/GUI/DefaultViewMode"), // The very old key
&oldMode,
(int)(WaveTrack::Waveform));
auto viewMode = WaveTrack::ConvertLegacyDisplayValue(oldMode);
// Now future-proof 2.1.1 against a recurrence of this sort of bug!
viewMode = WaveTrack::ValidateWaveTrackDisplay(viewMode);
const_cast<TracksViewModeSetting*>(this)->WriteInt( viewMode );
gPrefs->Flush();
value = mSymbols[ FindInt(viewMode) ].Internal();
}
};
static TracksViewModeSetting viewModeSetting{
wxT("/GUI/DefaultViewModeChoice"),
choicesView, nChoicesView, defaultChoiceView,
intChoicesView,
wxT("/GUI/DefaultViewModeNew")
};
WaveTrack::WaveTrackDisplay TracksPrefs::ViewModeChoice()
{
return (WaveTrack::WaveTrackDisplay) viewModeSetting.ReadInt();
}
//////////
static const IdentInterfaceSymbol choicesSampleDisplay[] = {
{ wxT("ConnectDots"), XO("Connect dots") },
{ wxT("StemPlot"), XO("Stem plot") }
};
static const size_t nChoicesSampleDisplay = WXSIZEOF( choicesSampleDisplay );
static const int intChoicesSampleDisplay[] = {
(int) WaveTrack::LinearInterpolate,
(int) WaveTrack::StemPlot
};
static_assert(
nChoicesSampleDisplay == WXSIZEOF(intChoicesSampleDisplay), "size mismatch" );
static const size_t defaultChoiceSampleDisplay = 1;
static EncodedEnumSetting sampleDisplaySetting{
wxT("/GUI/SampleViewChoice"),
choicesSampleDisplay, nChoicesSampleDisplay, defaultChoiceSampleDisplay,
intChoicesSampleDisplay,
wxT("/GUI/SampleView")
};
WaveTrack::SampleDisplay TracksPrefs::SampleViewChoice()
{
return (WaveTrack::SampleDisplay) sampleDisplaySetting.ReadInt();
}
//////////
static const IdentInterfaceSymbol choicesZoom[] = {
{ wxT("FitToWidth"), XO("Fit to Width") },
{ wxT("ZoomToSelection"), XO("Zoom to Selection") },
{ wxT("ZoomDefault"), XO("Zoom Default") },
{ XO("Minutes") },
{ XO("Seconds") },
{ wxT("FifthsOfSeconds"), XO("5ths of Seconds") },
{ wxT("TenthsOfSeconds"), XO("10ths of Seconds") },
{ wxT("TwentiethsOfSeconds"), XO("20ths of Seconds") },
{ wxT("FiftiethsOfSeconds"), XO("50ths of Seconds") },
{ wxT("HundredthsOfSeconds"), XO("100ths of Seconds") },
{ wxT("FiveHundredthsOfSeconds"), XO("500ths of Seconds") },
{ XO("MilliSeconds") },
{ XO("Samples") },
{ wxT("FourPixelsPerSample"), XO("4 Pixels per Sample") },
{ wxT("MaxZoom"), XO("Max Zoom") },
};
static const size_t nChoicesZoom = WXSIZEOF( choicesZoom );
static const int intChoicesZoom[] = {
WaveTrack::kZoomToFit,
WaveTrack::kZoomToSelection,
WaveTrack::kZoomDefault,
WaveTrack::kZoomMinutes,
WaveTrack::kZoomSeconds,
WaveTrack::kZoom5ths,
WaveTrack::kZoom10ths,
WaveTrack::kZoom20ths,
WaveTrack::kZoom50ths,
WaveTrack::kZoom100ths,
WaveTrack::kZoom500ths,
WaveTrack::kZoomMilliSeconds,
WaveTrack::kZoomSamples,
WaveTrack::kZoom4To1,
WaveTrack::kMaxZoom,
};
static_assert( nChoicesZoom == WXSIZEOF(intChoicesZoom), "size mismatch" );
static const size_t defaultChoiceZoom1 = 2; // kZoomDefault
static EncodedEnumSetting zoom1Setting{
wxT("/GUI/ZoomPreset1Choice"),
choicesZoom, nChoicesZoom, defaultChoiceZoom1,
intChoicesZoom,
wxT("/GUI/ZoomPreset1")
};
static const size_t defaultChoiceZoom2 = 13; // kZoom4To1
static EncodedEnumSetting zoom2Setting{
wxT("/GUI/ZoomPreset2Choice"),
choicesZoom, nChoicesZoom, defaultChoiceZoom2,
intChoicesZoom,
wxT("/GUI/ZoomPreset2")
};
WaveTrack::ZoomPresets TracksPrefs::Zoom1Choice()
{
return (WaveTrack::ZoomPresets) zoom1Setting.ReadInt();
}
WaveTrack::ZoomPresets TracksPrefs::Zoom2Choice()
{
return (WaveTrack::ZoomPresets) zoom2Setting.ReadInt();
}
//////////
TracksPrefs::TracksPrefs(wxWindow * parent, wxWindowID winid)
/* i18n-hint: "Tracks" include audio recordings but also other collections of
* data associated with a time line, such as sequences of labels, and musical
* notes */
: PrefsPanel(parent, winid, _("Tracks"))
{
// Bugs 1043, 1044
// First rewrite legacy preferences
gPrefs->Write(wxT("/GUI/DefaultViewModeNew"),
(int) WaveTrack::FindDefaultViewMode());
Populate();
}
@ -68,56 +233,9 @@ void TracksPrefs::Populate()
// Keep view choices and codes in proper correspondence --
// we don't display them by increasing integer values.
mViewChoices.Add(_("Waveform"));
mViewCodes.push_back((int)(WaveTrack::Waveform));
mViewChoices.Add(_("Waveform (dB)"));
mViewCodes.push_back((int)(WaveTrack::obsoleteWaveformDBDisplay));
mViewChoices.Add(_("Spectrogram"));
mViewCodes.push_back(WaveTrack::Spectrum);
// How samples are displayed when zoomed in:
mSampleDisplayChoices.Add(_("Connect dots"));
mSampleDisplayCodes.push_back((int) WaveTrack::LinearInterpolate);
mSampleDisplayChoices.Add(_("Stem plot"));
mSampleDisplayCodes.push_back((int) WaveTrack::StemPlot);
mZoomChoices.Add( _("Fit to Width") );
mZoomCodes.push_back( WaveTrack::kZoomToFit );
mZoomChoices.Add( _("Zoom to Selection") );
mZoomCodes.push_back( WaveTrack::kZoomToSelection );
mZoomChoices.Add( _("Zoom Default") );
mZoomCodes.push_back( WaveTrack::kZoomDefault );
mZoomChoices.Add( _("Minutes") );
mZoomCodes.push_back( WaveTrack::kZoomMinutes );
mZoomChoices.Add( _("Seconds") );
mZoomCodes.push_back( WaveTrack::kZoomSeconds );
mZoomChoices.Add( _("5ths of Seconds") );
mZoomCodes.push_back( WaveTrack::kZoom5ths );
mZoomChoices.Add( _("10ths of Seconds") );
mZoomCodes.push_back( WaveTrack::kZoom10ths );
mZoomChoices.Add( _("20ths of Seconds") );
mZoomCodes.push_back( WaveTrack::kZoom20ths );
mZoomChoices.Add( _("50ths of Seconds") );
mZoomCodes.push_back( WaveTrack::kZoom50ths );
mZoomChoices.Add( _("100ths of Seconds") );
mZoomCodes.push_back( WaveTrack::kZoom100ths );
mZoomChoices.Add( _("500ths of Seconds") );
mZoomCodes.push_back( WaveTrack::kZoom500ths );
mZoomChoices.Add( _("MilliSeconds") );
mZoomCodes.push_back( WaveTrack::kZoomMilliSeconds );
mZoomChoices.Add( _("Samples") );
mZoomCodes.push_back( WaveTrack::kZoomSamples );
mZoomChoices.Add( _("4 Pixels per Sample") );
mZoomCodes.push_back( WaveTrack::kZoom4To1 );
mZoomChoices.Add( _("Max Zoom") );
mZoomCodes.push_back( WaveTrack::kMaxZoom );
//------------------------- Main section --------------------
// Now construct the GUI itself.
@ -153,16 +271,10 @@ void TracksPrefs::PopulateOrExchange(ShuttleGui & S)
S.StartMultiColumn(2);
{
S.TieChoice(_("Default &view mode:"),
wxT("/GUI/DefaultViewModeNew"),
0,
mViewChoices,
mViewCodes);
viewModeSetting );
S.TieChoice(_("Display &samples:"),
wxT("/GUI/SampleView"),
1,
mSampleDisplayChoices,
mSampleDisplayCodes);
sampleDisplaySetting );
S.TieTextBox(_("Default audio track &name:"),
wxT("/GUI/TrackNames/DefaultTrackName"),
@ -178,16 +290,10 @@ void TracksPrefs::PopulateOrExchange(ShuttleGui & S)
S.StartMultiColumn(4);
{
S.TieChoice(_("Preset 1:"),
wxT("/GUI/ZoomPreset1"),
WaveTrack::kZoomDefault,
mZoomChoices,
mZoomCodes);
zoom1Setting );
S.TieChoice(_("Preset 2:"),
wxT("/GUI/ZoomPreset2"),
WaveTrack::kZoom4To1,
mZoomChoices,
mZoomCodes);
zoom2Setting );
}
}
S.EndStatic();

View File

@ -20,6 +20,7 @@
#include <vector>
#include "PrefsPanel.h"
#include "../WaveTrack.h"
class ShuttleGui;
@ -36,18 +37,16 @@ class TracksPrefs final : public PrefsPanel
static wxString GetDefaultAudioTrackNamePreference();
static WaveTrack::WaveTrackDisplay ViewModeChoice();
static WaveTrack::SampleDisplay SampleViewChoice();
static WaveTrack::ZoomPresets Zoom1Choice();
static WaveTrack::ZoomPresets Zoom2Choice();
private:
void Populate();
void PopulateOrExchange(ShuttleGui & S) override;
static int iPreferencePinned;
std::vector<int> mViewCodes;
wxArrayString mViewChoices;
std::vector<int> mSampleDisplayCodes;
wxArrayString mSampleDisplayChoices;
std::vector<int> mZoomCodes;
wxArrayString mZoomChoices;
};
class TracksPrefsFactory final : public PrefsPanelFactory