Audacity 3.2.0
TracksPrefs.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 TracksPrefs.cpp
6
7 Brian Gunlogson
8 Joshua Haberman
9 Dominic Mazzoni
10 James Crook
11
12
13*******************************************************************//*******************************************************************/
19
20
21#include "TracksPrefs.h"
22#include "MemoryX.h"
23
24//#include <algorithm>
25//#include <wx/defs.h>
26
27#include "Prefs.h"
28#include "Project.h"
29#include "ShuttleGui.h"
30#include "UndoManager.h"
31#include "Viewport.h"
32#include "WaveformSettings.h"
33#include "WaveTrack.h"
34
36
38 "/GUI/TracksFitVerticallyZoomed", false };
39
40namespace {
42 {
43 return wxT("/AudioIO/PinnedHead");
44 }
45
47 {
48 return false;
49 }
50
52 {
53 return wxT("/AudioIO/PinnedHeadPosition");
54 }
55
57 {
58 return 0.5;
59 }
60}
61
63// There is a complicated migration history here!
64namespace {
65 const auto key0 = wxT("/GUI/DefaultViewMode");
66 const auto key1 = wxT("/GUI/DefaultViewModeNew");
67 const auto key2 = wxT("/GUI/DefaultViewModeChoice");
68 const auto key3 = wxT("/GUI/DefaultViewModeChoiceNew");
69
70 const wxString obsoleteValue{ wxT("WaveformDB") };
71};
72
74 : public EnumSetting<WaveChannelViewConstants::Display> {
75public:
77
78 void Migrate( wxString &value ) override
79 {
80 // Special logic for this preference which was three times migrated!
81
82 // PRL: Bugs 1043, 1044
83 // 2.1.1 writes a NEW key for this preference, which got NEW values,
84 // to avoid confusing version 2.1.0 if it reads the preference file afterwards.
85 // Prefer the NEW preference key if it is present
86
87 static const EnumValueSymbol waveformSymbol{ XO("Waveform") };
88 static const EnumValueSymbol spectrumSymbol{ XO("Spectrogram") };
89
91 int oldMode;
92 wxString newValue;
93 auto stringValue =
95 switch (display) {
97 return spectrumSymbol.Internal();
99 return obsoleteValue;
100 default:
101 return waveformSymbol.Internal();
102 }
103 };
104
105 if (gPrefs->Read(key0, // The very old key
106 &oldMode,
109 newValue = stringValue(viewMode);
110 }
111 else if ( gPrefs->Read(key1,
112 &oldMode,
114 viewMode = static_cast<WaveChannelViewConstants::Display>(oldMode);
115 newValue = stringValue(viewMode);
116 }
117 else
118 gPrefs->Read( key2, &newValue );
119
120 if ( !gPrefs->Read( key3, &value ) ) {
121 if (newValue == obsoleteValue) {
122 newValue = waveformSymbol.Internal();
123 gPrefs->Write(
126 }
127
128 Write( value = newValue );
129 gPrefs->Flush();
130 return;
131 }
132 }
133};
134
136{
137 // Do a delayed computation, so that registration of sub-view types completes
138 // first
139 const auto &types = WaveChannelSubViewType::All();
140 auto symbols = transform_container< EnumValueSymbols >(
141 types, std::mem_fn(&WaveChannelSubViewType::name));
142 auto ids = transform_container<std::vector<WaveChannelSubViewType::Display>>(
143 types, std::mem_fn(&WaveChannelSubViewType::id));
144
145 // Special entry for multi
148
149 return {
150 key3,
151 symbols,
152 0, // Waveform
153 ids
154 };
155}
156
158{
159 return ViewModeSetting().ReadEnum();
160}
161
165 wxT("/GUI/SampleViewChoice"),
166 {
167 { wxT("ConnectDots"), XO("Connect dots") },
168 { wxT("StemPlot"), XO("Stem plot") }
169 },
170 1, // StemPlot
171
172 // for migrating old preferences:
173 {
176 },
177 wxT("/GUI/SampleView")
178};
179
181{
182 return sampleDisplaySetting.ReadEnum();
183}
184
186static const std::initializer_list<EnumValueSymbol> choicesZoom{
187 { wxT("FitToWidth"), XO("Fit to Width") },
188 { wxT("ZoomToSelection"), XO("Zoom to Selection") },
189 { wxT("ZoomDefault"), XO("Zoom Default") },
190 { XO("Minutes") },
191 { XO("Seconds") },
192 { wxT("FifthsOfSeconds"), XO("5ths of Seconds") },
193 { wxT("TenthsOfSeconds"), XO("10ths of Seconds") },
194 { wxT("TwentiethsOfSeconds"), XO("20ths of Seconds") },
195 { wxT("FiftiethsOfSeconds"), XO("50ths of Seconds") },
196 { wxT("HundredthsOfSeconds"), XO("100ths of Seconds") },
197 { wxT("FiveHundredthsOfSeconds"), XO("500ths of Seconds") },
198 { XO("MilliSeconds") },
199 { XO("Samples") },
200 { wxT("FourPixelsPerSample"), XO("4 Pixels per Sample") },
201 { wxT("MaxZoom"), XO("Max Zoom") },
202};
203static auto enumChoicesZoom = {
219};
220
222 wxT("/GUI/ZoomPreset1Choice"),
224 2, // kZoomDefault
225
226 // for migrating old preferences:
228 wxT("/GUI/ZoomPreset1")
229};
230
232 wxT("/GUI/ZoomPreset2Choice"),
234 13, // kZoom4To1
235
236 // for migrating old preferences:
238 wxT("/GUI/ZoomPreset2")
239};
240
242{
243 return zoom1Setting.ReadEnum();
244}
245
247{
248 return zoom2Setting.ReadEnum();
249}
250
252TracksPrefs::TracksPrefs(wxWindow * parent, wxWindowID winid)
253/* i18n-hint: "Tracks" include audio recordings but also other collections of
254 * data associated with a time line, such as sequences of labels, and musical
255 * notes */
256: PrefsPanel(parent, winid, XO("Tracks"))
257{
258 Populate();
259}
260
262{
263}
264
266{
268}
269
271{
272 return XO("Preferences for Tracks");
273}
274
276{
277 return "Tracks_Preferences";
278}
279
281{
282 // Keep view choices and codes in proper correspondence --
283 // we don't display them by increasing integer values.
284
285
286 // How samples are displayed when zoomed in:
287
288
289 //------------------------- Main section --------------------
290 // Now construct the GUI itself.
291 // Use 'eIsCreatingFromPrefs' so that the GUI is
292 // initialised with values from gPrefs.
295 // ----------------------- End of main section --------------
296}
297
299{
300 auto viewModeSetting = ViewModeSetting();
301
302 S.SetBorder(2);
303 S.StartScroller();
304
305 S.StartStatic(XO("Display"));
306 {
307 S.TieCheckBox(XXO("Auto-&fit track height"), TracksFitVerticallyZoomed);
308 S.TieCheckBox(XXO("Use &half-wave display when collapsed"),
309 {wxT("/GUI/CollapseToHalfWave"),
310 false});
311#ifdef SHOW_PINNED_UNPINNED_IN_PREFS
312 S.TieCheckBox(XXO("&Pinned Recording/Playback head"),
315#endif
316 S.TieCheckBox(XXO("A&uto-scroll if head unpinned"),
317 {wxT("/GUI/AutoScroll"),
318 true});
319
320 S.AddSpace(10);
321
322 S.StartMultiColumn(2);
323 {
324#ifdef SHOW_PINNED_POSITION_IN_PREFS
325 S.TieNumericTextBox(
326 XXO("Pinned &head position"),
329 30
330 );
331#endif
332
333 S.TieChoice(XXO("Default &view mode:"),
334 viewModeSetting );
335
336 S.TieChoice(
337 XXO("Default Waveform scale:"),
339
340 S.TieChoice(XXO("Display &samples:"),
342
343 S.TieTextBox(XXO("Default audio track &name:"),
345 30);
346 }
347 S.EndMultiColumn();
348 }
349 S.EndStatic();
350
351 S.StartStatic(XO("Zoom Toggle"));
352 {
353 S.StartMultiColumn(4);
354 {
355 S.TieChoice(XXO("Preset 1:"),
356 zoom1Setting );
357
358 S.TieChoice(XXO("Preset 2:"),
359 zoom2Setting );
360 }
361 }
362 S.EndStatic();
363 S.EndScroller();
364}
365
367{
368 // JKC: Cache this setting as it is read many times during drawing, and otherwise causes screen flicker.
369 // Correct solution would be to re-write wxFileConfig to be efficient.
370 if( iPreferencePinned >= 0 )
371 return iPreferencePinned == 1;
373 iPreferencePinned = bResult ? 1: 0;
374 return bResult;
375}
376
377void TracksPrefs::SetPinnedHeadPreference(bool value, bool flush)
378{
379 iPreferencePinned = value ? 1 :0;
381 if(flush)
382 gPrefs->Flush();
383}
384
386{
387 auto value = gPrefs->ReadDouble(
390 return std::max(0.0, std::min(1.0, value));
391}
392
394{
395 value = std::max(0.0, std::min(1.0, value));
397 if(flush)
398 gPrefs->Flush();
399}
400
402{
403 // Bug 1583: Clear the caching of the preference pinned state.
407
408 // Bug 1661: Don't store the name for new tracks if the name is the
409 // default in that language.
413 gPrefs->Flush();
414 }
415
418 return true;
419}
420
421namespace{
423 [](wxWindow *parent, wxWindowID winid, AudacityProject *)
424 {
425 wxASSERT(parent); // to justify safenew
426 return safenew TracksPrefs(parent, winid);
427 }
428};
429
432 explicit Handler(AudacityProject &project) : mProject{ project }
433 , mUndoSubscription{ UndoManager::Get(mProject)
434 .Subscribe([this](const UndoRedoMessage &message){
435 if (message.type == UndoRedoMessage::Pushed &&
437 )
438 Viewport::Get(mProject).ZoomFitVertically(); })}
439 {}
440
441 Handler(const Handler &) = delete;
442 Handler &operator=(const Handler &) = delete;
443
446}; // struct Handler
447
449 Callable::UniqueMaker<Handler, AudacityProject &>()
450};
451}
wxT("CloseDown"))
int min(int a, int b)
XO("Cut/Copy/Paste")
XXO("&Cut/Copy/Paste Toolbar")
#define safenew
Definition: MemoryX.h:10
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
@ eIsCreatingFromPrefs
Definition: ShuttleGui.h:46
@ eIsSavingToPrefs
Definition: ShuttleGui.h:47
const auto project
#define S(N)
Definition: ToChars.cpp:64
static EnumSetting< WaveChannelViewConstants::ZoomPresets > zoom2Setting
static const std::initializer_list< EnumValueSymbol > choicesZoom
static EnumSetting< WaveChannelViewConstants::ZoomPresets > zoom1Setting
static EnumSetting< WaveChannelViewConstants::SampleDisplay > sampleDisplaySetting
static TracksViewModeEnumSetting ViewModeSetting()
static auto enumChoicesZoom
#define TRACKS_PREFS_PLUGIN_SYMBOL
Definition: TracksPrefs.h:25
StringSetting AudioTrackNameSetting
Definition: WaveTrack.cpp:3398
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:346
bool Write(const wxString &value)
Definition: Prefs.cpp:424
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:275
ComponentInterfaceSymbol pairs a persistent string identifier used internally with an optional,...
Adapts EnumSettingBase to a particular enumeration type.
Definition: Prefs.h:514
Enum ReadEnum() const
Definition: Prefs.h:534
A move-only handle representing a connection to a Publisher.
Definition: Observer.h:70
Base class for a panel in the PrefsDialog. Classes derived from this class include BatchPrefs,...
Definition: PrefsPanel.h:51
bool Delete()
Delete the key if present, and return true iff it was.
Definition: Prefs.cpp:549
void Invalidate() override
Definition: Prefs.h:289
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:207
const T & GetDefault() const
Definition: Prefs.h:199
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:640
A PrefsPanel for track display and behavior properties.
Definition: TracksPrefs.h:28
static WaveChannelViewConstants::ZoomPresets Zoom1Choice()
TracksPrefs(wxWindow *parent, wxWindowID winid)
static void SetPinnedHeadPreference(bool value, bool flush=false)
static bool GetPinnedHeadPreference()
TranslatableString GetDescription() const override
ManualPageID HelpPageName() override
If not empty string, the Help button is added below the panel.
static WaveChannelViewConstants::ZoomPresets Zoom2Choice()
static double GetPinnedHeadPositionPreference()
static WaveChannelViewConstants::SampleDisplay SampleViewChoice()
void PopulateOrExchange(ShuttleGui &S) override
static BoolSetting TracksFitVerticallyZoomed
Definition: TracksPrefs.h:30
static WaveChannelViewConstants::Display ViewModeChoice()
static void SetPinnedHeadPositionPreference(double value, bool flush=false)
void Populate()
static int iPreferencePinned
Definition: TracksPrefs.h:55
bool Commit() override
ComponentInterfaceSymbol GetSymbol() const override
void Migrate(wxString &value) override
Definition: TracksPrefs.cpp:78
Holds a msgid for the translation catalog; may also bind format arguments.
Maintain a non-persistent list of states of the project, to support undo and redo commands.
Definition: UndoManager.h:155
void ZoomFitVertically()
Definition: Viewport.cpp:699
static Viewport & Get(AudacityProject &project)
Definition: Viewport.cpp:33
static wxString GetDefaultAudioTrackNamePreference()
Definition: WaveTrack.cpp:373
static const wxString dbLogValueString
static EnumSetting< ScaleTypeValues > waveformScaleSetting
static const wxString waveformScaleKey
virtual bool Flush() noexcept=0
double ReadDouble(const wxString &key, double defaultValue) const
virtual bool Write(const wxString &key, bool value)=0
bool ReadBool(const wxString &key, bool defaultValue) const
virtual bool Read(const wxString &key, bool *value) const =0
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:202
WAVE_TRACK_API Display ConvertLegacyDisplayValue(int oldValue)
@ MultiView
"Multi" is special, not really a view type on par with the others.
WAVE_TRACK_API const EnumValueSymbol MultiViewSymbol
String identifier for a preference for one of each type of view.
const wxChar * PinnedHeadPositionPreferenceKey()
Definition: TracksPrefs.cpp:51
static const AudacityProject::AttachedObjects::RegisteredFactory key
PrefsPanel::Registration sAttachment
A convenient default parameter for class template Site.
Definition: ClientData.h:29
Type of message published by UndoManager.
Definition: UndoManager.h:55
static const std::vector< WaveChannelSubViewType > & All()
Discover all registered types.
Observer attached to each project applies the vertical zoom fit preference.
const Observer::Subscription mUndoSubscription
Handler & operator=(const Handler &)=delete