mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-22 15:20:15 +02:00
Merge branch 'master' into HEAD
This commit is contained in:
commit
250a2ea12a
55
images/Help.xpm
Normal file
55
images/Help.xpm
Normal file
@ -0,0 +1,55 @@
|
||||
/* XPM */
|
||||
static const char * Help_xpm[] = {
|
||||
"21 21 31 1",
|
||||
" c None",
|
||||
". c #6699FF",
|
||||
"+ c #8CB2FE",
|
||||
"@ c #CDDDFE",
|
||||
"# c #F0F5FE",
|
||||
"$ c #F9FAFE",
|
||||
"% c #E4ECFE",
|
||||
"& c #A4C2FE",
|
||||
"* c #6698FE",
|
||||
"= c #FFFFFF",
|
||||
"- c #A9C5FE",
|
||||
"; c #DAE6FE",
|
||||
"> c #95B8FE",
|
||||
", c #6D9DFE",
|
||||
"' c #71A0FE",
|
||||
") c #BFD4FE",
|
||||
"! c #E9F0FE",
|
||||
"~ c #F7F9FE",
|
||||
"{ c #90B4FE",
|
||||
"] c #C8DAFE",
|
||||
"^ c #78A5FE",
|
||||
"/ c #EEF3FE",
|
||||
"( c #E3ECFE",
|
||||
"_ c #6F9FFE",
|
||||
": c #7CA7FE",
|
||||
"< c #EDF2FE",
|
||||
"[ c #E6EEFE",
|
||||
"} c #DBE7FE",
|
||||
"| c #87AEFE",
|
||||
"1 c #FBFCFE",
|
||||
"2 c #6799FE",
|
||||
" ..... ",
|
||||
" ......... ",
|
||||
" ............. ",
|
||||
" ............... ",
|
||||
" .....+@#$%&*..... ",
|
||||
" .....======-..... ",
|
||||
" ......;>,')=!...... ",
|
||||
" ..........,=~...... ",
|
||||
"...........{=].......",
|
||||
"..........^/(_.......",
|
||||
".........:<['........",
|
||||
".........}=|.........",
|
||||
".........1=2.........",
|
||||
" ........==......... ",
|
||||
" ................... ",
|
||||
" .......==........ ",
|
||||
" .......==........ ",
|
||||
" ............... ",
|
||||
" ............. ",
|
||||
" ......... ",
|
||||
" ..... "};
|
@ -3,6 +3,7 @@
|
||||
;type analyze
|
||||
;categories "http://lv2plug.in/ns/lv2core#AnalyserPlugin"
|
||||
;name "Silence Finder..."
|
||||
;manpage "Silence_Finder"
|
||||
;action "Finding silence..."
|
||||
;info "Adds point labels in areas of silence according to the specified\nlevel and duration of silence. If too many silences are detected,\nincrease the silence level and duration; if too few are detected,\nreduce the level and duration."
|
||||
;author "Alex S. Brown"
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type analyze
|
||||
;categories "http://lv2plug.in/ns/lv2core#AnalyserPlugin"
|
||||
;name "Sound Finder..."
|
||||
;manpage "Sound_Finder"
|
||||
;action "Finding sound..."
|
||||
;info "Adds region labels for areas of sound according to the specified level\nand duration of surrounding silence. If too many labels are produced,\nincrease the silence level and duration; if too few are produced,\nreduce the level and duration."
|
||||
;author "Jeremy R. Brown"
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type process spectral
|
||||
;preview linear
|
||||
;name "Spectral edit parametric EQ..."
|
||||
;manpage "Spectral_edit_parametric_EQ"
|
||||
;action "Filtering..."
|
||||
;author "Paul Licameli"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type process spectral
|
||||
;preview linear
|
||||
;name "Spectral edit shelves..."
|
||||
;manpage "Spectral_edit_shelves"
|
||||
;action "Filtering..."
|
||||
;author "Paul Licameli"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type process
|
||||
;categories "http://lv2plug.in/ns/lv2core#MixerPlugin"
|
||||
;name "Studio Fade Out"
|
||||
;manpage "Fades#studio_fadeout"
|
||||
;action "Applying Fade..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -5,6 +5,8 @@
|
||||
;preview selection
|
||||
;categories "http://lv2plug.in/ns/lv2core#MixerPlugin"
|
||||
;name "Adjustable Fade..."
|
||||
;manpage "Adjustable_Fade"
|
||||
;debug false
|
||||
;action "Applying Fade..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type analyze
|
||||
;categories "http://audacityteam.org/namespace#OnsetDetector"
|
||||
;name "Beat Finder..."
|
||||
;manpage "Beat_Finder"
|
||||
;action "Finding beats..."
|
||||
;author "Audacity"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type process
|
||||
;preview enabled
|
||||
;name "Clip Fix..."
|
||||
;manpage "Clip_Fix"
|
||||
;action "Reconstructing clips..."
|
||||
;author "Benjamin Schwartz and Steve Daulton"
|
||||
;copyright "Licensing confirmed under terms of the GNU General Public License version 2"
|
||||
|
@ -4,6 +4,7 @@
|
||||
;mergeclips 1
|
||||
;restoresplits 0
|
||||
;name "Crossfade Clips"
|
||||
;manpage "Crossfade_Clips"
|
||||
;action "Crossfading..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -2,6 +2,8 @@
|
||||
;version 4
|
||||
;type process
|
||||
;name "Crossfade Tracks..."
|
||||
;manpage "Crossfade_Tracks"
|
||||
;debug disabled
|
||||
;action "Crossfading..."
|
||||
;preview selection
|
||||
;author "Steve Daulton"
|
||||
@ -69,4 +71,6 @@ audio clip, fade in, otherwise fade out."
|
||||
(setf out-dist (min out-dist (abs (- end (second (nth i clips)))))))
|
||||
(if (< in-dist out-dist) 'in 'out)))
|
||||
|
||||
(crossfade type direction curve)
|
||||
(if (< (length (get '*selection* 'tracks)) 2)
|
||||
"Error.\nSelect 2 (or more) tracks to crossfade."
|
||||
(crossfade type direction curve))
|
||||
|
@ -4,6 +4,7 @@
|
||||
;preview linear
|
||||
;categories "http://lv2plug.in/ns/lv2core#DelayPlugin"
|
||||
;name "Delay..."
|
||||
;manpage "Delay"
|
||||
;action "Applying Delay Effect..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -2,6 +2,7 @@
|
||||
;version 4
|
||||
;type analyze
|
||||
;name "Regular Interval Labels..."
|
||||
;manpage "Regular_Interval_Labels"
|
||||
;action "Adding equally-spaced labels to the label track..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,6 +3,8 @@
|
||||
;type process
|
||||
;preview linear
|
||||
;name "High Pass Filter..."
|
||||
;manpage "High_Pass_Filter"
|
||||
;debug disabled
|
||||
;action "Performing High Pass Filter..."
|
||||
;author "Dominic Mazzoni"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,6 +3,8 @@
|
||||
;type process
|
||||
;categories "http://lv2plug.in/ns/lv2core/#DynamicsPlugin"
|
||||
;name "Limiter..."
|
||||
;manpage "Limiter"
|
||||
;debug false
|
||||
;action "Limiting..."
|
||||
;preview enabled
|
||||
;author "Steve Daulton"
|
||||
|
@ -3,6 +3,8 @@
|
||||
;type process
|
||||
;preview linear
|
||||
;name "Low Pass Filter..."
|
||||
;manpage "Low_Pass_Filter"
|
||||
;debug disabled
|
||||
;action "Performing Low Pass Filter..."
|
||||
;author "Dominic Mazzoni"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,28 +3,27 @@
|
||||
;type process
|
||||
;preview linear
|
||||
;name "Notch Filter..."
|
||||
;manpage "Notch_Filter"
|
||||
;debug false
|
||||
;action "Applying Notch Filter..."
|
||||
;author "Steve Daulton and Bill Wharrie"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
||||
;; notch.ny by Steve Daulton and Bill Wharrie, September 2010.
|
||||
;; Last updated August 2015.
|
||||
;; notch.ny by Steve Daulton and Bill Wharrie
|
||||
;; Released under terms of the GNU General Public License version 2:
|
||||
;; http://www.gnu.org/licenses/old-licenses/gpl-2.0.html .
|
||||
|
||||
|
||||
;control frequency "Frequency (Hz)" float-text "" 60 0 nil
|
||||
;control q "Q (higher value reduces width)" float-text "" 1 0.1 nil
|
||||
|
||||
;control q "Q (higher value reduces width)" float-text "" 1 0.1 1000
|
||||
|
||||
(cond
|
||||
((< frequency 0.1) "Frequency must be at least 0.1 Hz.")
|
||||
((>= frequency (/ *sound-srate* 2.0))
|
||||
(format nil "Error:~%~%Frequency (~a Hz) is too high for track sample rate.~%~%~
|
||||
Track sample rate is ~a Hz~%~
|
||||
Track sample rate is ~a Hz.~%~
|
||||
Frequency must be less than ~a Hz."
|
||||
frequency
|
||||
*sound-srate*
|
||||
(/ *sound-srate* 2.0)))
|
||||
((< q 0.1) "Q must be at least 0.1.")
|
||||
(T (notch2 *track* frequency q)))
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type generate
|
||||
;categories "http://lv2plug.in/ns/lv2core#GeneratorPlugin"
|
||||
;name "Pluck..."
|
||||
;manpage "Pluck"
|
||||
;preview linear
|
||||
;action "Generating pluck sound..."
|
||||
;info "MIDI values for C notes: 36, 48, 60 [middle C], 72, 84, 96."
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type generate
|
||||
;categories "http://lv2plug.in/ns/lv2core#GeneratorPlugin"
|
||||
;name "Rhythm Track..."
|
||||
;manpage "Rhythm_Track"
|
||||
;preview linear
|
||||
;action "Generating Rhythm..."
|
||||
;author "Dominic Mazzoni"
|
||||
|
@ -4,6 +4,7 @@
|
||||
;categories "http://lv2plug.in/ns/lv2core#GeneratorPlugin"
|
||||
;preview linear
|
||||
;name "Risset Drum..."
|
||||
;manpage "Risset_Drum"
|
||||
;action "Generating Risset Drum..."
|
||||
;author "Steven Jones"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -2,6 +2,7 @@
|
||||
;version 3
|
||||
;type analyze
|
||||
;name "Sample Data Export..."
|
||||
;manpage "Sample_Data_Export"
|
||||
;action "Analyzing..."
|
||||
;maxlen 1000001
|
||||
;categories "http://lv2plug.in/ns/lv2core#AnalyserPlugin"
|
||||
|
@ -2,6 +2,7 @@
|
||||
;version 4
|
||||
;type generate
|
||||
;name "Sample Data Import..."
|
||||
;manpage "Sample_Data_Import"
|
||||
;action "Reading and rendering samples..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -4,6 +4,8 @@
|
||||
;preview linear
|
||||
;categories "http://lv2plug.in/ns/lv2core#ModulatorPlugin"
|
||||
;name "Tremolo..."
|
||||
;manpage "Tremolo"
|
||||
;debug disabled
|
||||
;action "Applying Tremolo..."
|
||||
;author "Steve Daulton"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
@ -18,11 +20,8 @@
|
||||
|
||||
;control wave "Waveform type" choice "sine,triangle,sawtooth,inverse sawtooth,square" 0
|
||||
;control phase "Starting phase (degrees)" int "" 0 -180 180
|
||||
;control wet "Wet level (percent)" int "" 40 0 100
|
||||
;control lfo "Frequency (Hz)" real "" 4 0 10
|
||||
|
||||
; Limit to sensible range
|
||||
(setq lfo (min 1000 (max lfo (/ (get-duration 1)))))
|
||||
;control wet "Wet level (percent)" int "" 40 1 100
|
||||
;control lfo "Frequency (Hz)" float-text "" 4 0.001 1000
|
||||
|
||||
; Convert % to linear
|
||||
(setq wet (/ wet 200.0))
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type process
|
||||
;categories "http://lv2plug.in/ns/lv2core#MixerPlugin"
|
||||
;name "Vocal Reduction and Isolation..."
|
||||
;manpage "Vocal_Reduction_and_Isolation"
|
||||
;action "Applying Action..."
|
||||
;author "Robert Haenggi"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -3,6 +3,7 @@
|
||||
;type process
|
||||
;preview linear
|
||||
;name "Vocal Remover..."
|
||||
;manpage "Vocal_Remover"
|
||||
;action "Removing center-panned audio..."
|
||||
;info "For reducing center-panned vocals"
|
||||
;author "Steve Daulton"
|
||||
|
@ -4,6 +4,7 @@
|
||||
;preview enabled
|
||||
;categories "http://lv2plug.in/ns/lv2core#SpectralPlugin"
|
||||
;name "Vocoder..."
|
||||
;manpage "Vocoder"
|
||||
;action "Processing Vocoder..."
|
||||
;author "Edgar-RFT"
|
||||
;copyright "Released under terms of the GNU General Public License version 2"
|
||||
|
@ -85,11 +85,6 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpMic, wxImage( 25, 25 ), wxT("Mic"));
|
||||
DEFINE_IMAGE( bmpSpeaker, wxImage( 25, 25 ), wxT("Speaker"));
|
||||
|
||||
DEFINE_IMAGE( bmpPinnedPlayHead, wxImage( 27, 27 ), wxT("PinnedPlayHead"));
|
||||
DEFINE_IMAGE( bmpUnpinnedPlayHead, wxImage( 27, 27 ), wxT("UnpinnedPlayHead"));
|
||||
DEFINE_IMAGE( bmpPinnedRecordHead, wxImage( 27, 27 ), wxT("PinnedRecordHead"));
|
||||
DEFINE_IMAGE( bmpUnpinnedRecordHead, wxImage( 27, 27 ), wxT("UnpinnedRecordHead"));
|
||||
|
||||
SET_THEME_FLAGS( resFlagPaired );
|
||||
DEFINE_IMAGE( bmpZoomFit, wxImage( 27, 27 ), wxT("ZoomFit"));
|
||||
DEFINE_IMAGE( bmpZoomFitDisabled, wxImage( 27, 27 ), wxT("ZoomFitDisabled"));
|
||||
@ -135,6 +130,8 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpTnSelectSoundDisabled, wxImage( 24, 24 ), wxT("TnSelectSoundDisabled"));
|
||||
DEFINE_IMAGE( bmpTnSelectSilence, wxImage( 24, 24 ), wxT("TnSelectSilence"));
|
||||
DEFINE_IMAGE( bmpTnSelectSilenceDisabled, wxImage( 24, 24 ), wxT("TnSelectSilenceDisabled"));
|
||||
DEFINE_IMAGE( bmpOptions, wxImage( 24, 24 ), wxT("Options"));
|
||||
DEFINE_IMAGE( bmpOptionsDisabled, wxImage( 24, 24 ), wxT("OptionsDisabled"));
|
||||
|
||||
SET_THEME_FLAGS( resFlagNone );
|
||||
DEFINE_IMAGE( bmpLabelGlyph0, wxImage( 15, 23 ), wxT("LabelGlyph0"));
|
||||
@ -161,13 +158,21 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpPostfishLoop, wxImage( 29, 17 ), wxT("PostfishLoop"));
|
||||
|
||||
SET_THEME_FLAGS( resFlagNone );
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpDockDown, wxImage( 15, 55 ), wxT("DockDown"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpDockDownShort, wxImage( 15, 27 ), wxT("DockDownShort"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpDockOver, wxImage( 15, 55 ), wxT("DockOver"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpDockOverShort, wxImage( 15, 27 ), wxT("DockOverShort"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpDockUp, wxImage( 15, 55 ), wxT("DockUp"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpDockUpShort, wxImage( 15, 27 ), wxT("DockUpShort"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpPinnedPlayRecordHead, wxImage( 27, 27 ), wxT("PinnedPlayRecordHead"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpUnpinnedPlayRecordHead, wxImage( 27, 27 ), wxT("UnpinnedPlayRecordHead"));
|
||||
|
||||
DEFINE_IMAGE( bmpSyncLockSelTile, wxImage(20, 22), wxT("SyncLockSelTile"));
|
||||
@ -176,7 +181,6 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpSyncLockTracksUp, wxImage( 20, 20 ), wxT("SyncLockTracksUp"));
|
||||
DEFINE_IMAGE( bmpSyncLockTracksDisabled, wxImage( 20, 20 ), wxT("SyncLockTracksDisabled"));
|
||||
DEFINE_IMAGE( bmpToggleScrubRuler, wxImage( 20, 20 ), wxT("ToggleScrubRuler"));
|
||||
// DEFINE_IMAGE( bmpSliderThumb, wxImage( 11, 14 ), wxT("SliderThumb"));
|
||||
DEFINE_IMAGE( bmpSyncLockIcon, wxImage(12, 12), wxT("SyncLockIcon"));
|
||||
|
||||
SET_THEME_FLAGS( resFlagNewLine );
|
||||
@ -189,7 +193,9 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
|
||||
SET_THEME_FLAGS( resFlagNone );
|
||||
DEFINE_IMAGE( bmpSliderThumb, wxImage( 11, 20 ), wxT("SliderThumb"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpSlider, wxImage( 80, 20 ), wxT("Slider"));
|
||||
SET_THEME_FLAGS( resFlagSkip );
|
||||
DEFINE_IMAGE( bmpHiliteSlider, wxImage( 80, 20 ), wxT("HiliteSlider"));
|
||||
DEFINE_IMAGE( bmpUpButtonExpandSel, wxImage( 96, 18 ), wxT("UpButtonExpandSel"));
|
||||
DEFINE_IMAGE( bmpDownButtonExpandSel, wxImage( 96, 18 ), wxT("DownButtonExpandSel"));
|
||||
@ -206,8 +212,6 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpUpButtonSmall, wxImage( 27, 27 ), wxT("UpButtonSmall"));
|
||||
DEFINE_IMAGE( bmpDownButtonSmall, wxImage( 27, 27 ), wxT("DownButtonSmall"));
|
||||
DEFINE_IMAGE( bmpHiliteButtonSmall, wxImage( 27, 27 ), wxT("HiliteButtonSmall"));
|
||||
//DEFINE_IMAGE( bmpVolumeSlider, wxImage( 100, 28 ), wxT("VolumeSlider"));
|
||||
//DEFINE_IMAGE( bmpVolumeSliderThumb, wxImage( 10, 28 ), wxT("VolumeSliderThumb"));
|
||||
|
||||
SET_THEME_FLAGS( resFlagNone );
|
||||
DEFINE_IMAGE( bmpMacUpButton, wxImage( 36, 36 ), wxT("MacUpButton"));
|
||||
@ -216,8 +220,6 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpMacUpButtonSmall, wxImage( 27, 27 ), wxT("MacUpButtonSmall"));
|
||||
DEFINE_IMAGE( bmpMacDownButtonSmall, wxImage( 27, 27 ), wxT("MacDownButtonSmall"));
|
||||
DEFINE_IMAGE( bmpMacHiliteButtonSmall, wxImage( 27, 27 ), wxT("MacHiliteButtonSmall"));
|
||||
DEFINE_IMAGE( bmpMacSlider, wxImage( 100, 28 ), wxT("MacSlider"));
|
||||
DEFINE_IMAGE( bmpMacSliderThumb, wxImage( 17, 28 ), wxT("MacSliderThumb"));
|
||||
|
||||
SET_THEME_FLAGS( resFlagInternal );
|
||||
DEFINE_IMAGE( bmpRecoloredUpLarge, wxImage( 48, 48 ), wxT("RecoloredUpLarge"));
|
||||
@ -241,19 +243,7 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
DEFINE_IMAGE( bmpTopFrequencyCursor, wxImage( 32, 32 ), wxT("TopFrequencyCursor"));
|
||||
DEFINE_IMAGE( bmpBandWidthCursor, wxImage(32, 32), wxT("BandWidthCursor"));
|
||||
|
||||
|
||||
|
||||
/*
|
||||
DEFINE_IMAGE( bmpToolBarToggle, wxImage( 43, 35 ), wxT("ToolBarToggle"));
|
||||
DEFINE_IMAGE( bmpToolBarTarget, wxImage( 17, 26 ), wxT("ToolBarTarget"));
|
||||
DEFINE_IMAGE( bmpToolBarGrabber, wxImage( 17, 8 ), wxT("ToolBarGrabber"));
|
||||
DEFINE_IMAGE( bmpArrow, wxImage( 9, 16 ), wxT("Arrow"));
|
||||
DEFINE_IMAGE( bmpUploadFile, wxImage( 16, 16 ), wxT("UploadFile"));
|
||||
DEFINE_IMAGE( bmpUploadFolder, wxImage( 16, 16 ), wxT("UploadFolder"));
|
||||
DEFINE_IMAGE( bmpUploadMp3, wxImage( 16, 16 ), wxT("UploadMp3"));
|
||||
DEFINE_IMAGE( bmpUploadUp, wxImage( 16, 16 ), wxT("UploadUp"));
|
||||
*/
|
||||
SET_THEME_FLAGS( resFlagNewLine );
|
||||
//SET_THEME_FLAGS( resFlagNewLine );
|
||||
|
||||
// DA: The logo with name xpm has a different width.
|
||||
#ifdef EXPERIMENTAL_DA
|
||||
@ -264,9 +254,11 @@ from there. Audacity will look for a file called "Pause.png".
|
||||
|
||||
#define LOGOWITHNAME_HEIGHT 200
|
||||
|
||||
SET_THEME_FLAGS( resFlagSkip | resFlagNewLine );
|
||||
DEFINE_IMAGE( bmpAudacityLogo, wxImage( 215, 190 ), wxT("AudacityLogo"));
|
||||
DEFINE_IMAGE( bmpAudacityLogo48x48, wxImage( 48, 48 ), wxT("AudacityLogo48x48"));
|
||||
|
||||
|
||||
DEFINE_COLOUR( clrBlank, wxColour( 64, 64, 64), wxT("Blank"));
|
||||
DEFINE_COLOUR( clrUnselected, wxColour( 30, 30, 30), wxT("Unselected"));
|
||||
DEFINE_COLOUR( clrSelected, wxColour( 93, 65, 93), wxT("Selected"));
|
||||
|
@ -1508,15 +1508,26 @@ bool AudacityApp::OnInit()
|
||||
|
||||
AudacityProject *project;
|
||||
{
|
||||
// Bug 718: Position splash screen on same screen
|
||||
// as where Audacity project will appear.
|
||||
wxRect wndRect;
|
||||
bool bMaximized = false;
|
||||
bool bIconized = false;
|
||||
GetNextWindowPlacement(&wndRect, &bMaximized, &bIconized);
|
||||
|
||||
wxSplashScreen temporarywindow(
|
||||
logo,
|
||||
wxSPLASH_CENTRE_ON_SCREEN | wxSPLASH_NO_TIMEOUT,
|
||||
wxSPLASH_NO_CENTRE | wxSPLASH_NO_TIMEOUT,
|
||||
0,
|
||||
NULL,
|
||||
wxID_ANY,
|
||||
wxDefaultPosition,
|
||||
wxDefaultSize,
|
||||
wxSTAY_ON_TOP);
|
||||
// Possibly move it on to the second screen...
|
||||
temporarywindow.SetPosition( wndRect.GetTopLeft() );
|
||||
// Centered on whichever screen it is on.
|
||||
temporarywindow.Center();
|
||||
temporarywindow.SetTitle(_("Audacity is starting up..."));
|
||||
SetTopWindow(&temporarywindow);
|
||||
|
||||
|
@ -2130,7 +2130,7 @@ void AudioIO::PrepareMidiIterator(bool send, double offset)
|
||||
// Iterator not yet intialized, must add each track...
|
||||
for (i = 0; i < nTracks; i++) {
|
||||
NoteTrack *t = mMidiPlaybackTracks[i];
|
||||
Alg_seq_ptr seq = t->GetSequence();
|
||||
Alg_seq_ptr seq = &t->GetSeq();
|
||||
// mark sequence tracks as "in use" since we're handing this
|
||||
// off to another thread and want to make sure nothing happens
|
||||
// to the data until playback finishes. This is just a sanity check.
|
||||
@ -2387,7 +2387,7 @@ void AudioIO::StopStream()
|
||||
int nTracks = mMidiPlaybackTracks.size();
|
||||
for (int i = 0; i < nTracks; i++) {
|
||||
NoteTrack *t = mMidiPlaybackTracks[i];
|
||||
Alg_seq_ptr seq = t->GetSequence();
|
||||
Alg_seq_ptr seq = &t->GetSeq();
|
||||
seq->set_in_use(false);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -933,14 +933,15 @@ void Envelope::InsertSpace( double t0, double tlen )
|
||||
point.SetT( point.GetT() + tlen );
|
||||
}
|
||||
|
||||
// increase track len, before insert or replace,
|
||||
// since it range chacks the values.
|
||||
mTrackLen += tlen;
|
||||
// Preserve the right-side limit.
|
||||
if ( 1 + range.first < range.second )
|
||||
// There was a control point already.
|
||||
;
|
||||
else
|
||||
InsertOrReplaceRelative( t0 + tlen, val );
|
||||
|
||||
mTrackLen += tlen;
|
||||
}
|
||||
|
||||
int Envelope::Reassign(double when, double value)
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
* This returns the string path to where the user may have put plug-ins
|
||||
* if they don't have system admin rights. Under default settings, it's
|
||||
* <DataDir>/Plug-Ins/ */
|
||||
static wxString PlugInDir();
|
||||
static wxString PlugInDir(); // Windows and Mac only
|
||||
static wxString ThemeDir();
|
||||
static wxString ThemeComponentsDir();
|
||||
static wxString ThemeCachePng();
|
||||
|
@ -493,6 +493,9 @@ FreqWindow::FreqWindow(wxWindow * parent, wxWindowID id,
|
||||
|
||||
Layout();
|
||||
Fit();
|
||||
// Bug 1607:
|
||||
Center();
|
||||
|
||||
SetMinSize(GetSize());
|
||||
mAlgChoice->SetFocus();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,7 @@ for drawing different aspects of the label and its text box.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/brush.h>
|
||||
@ -473,7 +474,9 @@ void LabelTrack::ComputeLayout(const wxRect & r, const ZoomInfo &zoomInfo) const
|
||||
// Initially none of the rows have been used.
|
||||
// So set a value that is less than any valid value.
|
||||
{
|
||||
const int xStart = zoomInfo.TimeToPosition(0.0, r.x) - 100;
|
||||
// Bug 502: With dragging left of zeros, labels can be in
|
||||
// negative space. So set least possible value as starting point.
|
||||
const int xStart = INT_MIN;
|
||||
for (auto &x : xUsed)
|
||||
x = xStart;
|
||||
}
|
||||
|
@ -461,6 +461,7 @@ void Lyrics::OnKeyEvent(wxKeyEvent & event)
|
||||
{
|
||||
AudacityProject *project = GetActiveProject();
|
||||
project->GetCommandManager()->FilterKeyEvent(project, event, true);
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void Lyrics::OnPaint(wxPaintEvent & WXUNUSED(event))
|
||||
|
@ -130,6 +130,7 @@ LyricsWindow::LyricsWindow(AudacityProject *parent):
|
||||
wxCommandEventHandler(LyricsWindow::OnTimer),
|
||||
NULL,
|
||||
this);
|
||||
Center();
|
||||
}
|
||||
|
||||
LyricsWindow::~LyricsWindow()
|
||||
|
297
src/Menus.cpp
297
src/Menus.cpp
@ -999,7 +999,7 @@ void AudacityProject::CreateMenusAndCommands()
|
||||
c->AddSeparator();
|
||||
c->AddCheck(wxT("MoveSelectionWithTracks"), _("&Move Selection with Tracks (on/off)"),
|
||||
FN(OnMoveSelectionWithTracks),
|
||||
gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), 1L),
|
||||
gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), 0L),
|
||||
AlwaysEnabledFlag, AlwaysEnabledFlag);
|
||||
c->EndSubMenu();
|
||||
|
||||
@ -1240,7 +1240,7 @@ void AudacityProject::CreateMenusAndCommands()
|
||||
// Ext-Bar Menu
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
c->BeginMenu("Ext-Bar");
|
||||
c->BeginMenu("Ext-&Bar");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -1399,7 +1399,7 @@ void AudacityProject::CreateMenusAndCommands()
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
c->SetDefaultFlags(AlwaysEnabledFlag, AlwaysEnabledFlag);
|
||||
c->BeginMenu("Ext-Command");
|
||||
c->BeginMenu("Ext-Co&mmand");
|
||||
|
||||
c->AddGlobalCommand(wxT("PrevWindow"), _("Move backward thru active windows"), FN(PrevWindow), wxT("Alt+Shift+F6"));
|
||||
c->AddGlobalCommand(wxT("NextWindow"), _("Move forward thru active windows"), FN(NextWindow), wxT("Alt+F6"));
|
||||
@ -1438,8 +1438,8 @@ void AudacityProject::CreateMenusAndCommands()
|
||||
c->AddItem(wxT("CursorLongJumpLeft"), _("Cursor Long Jump Left"), FN(OnCursorLongJumpLeft), wxT("Shift+,"));
|
||||
c->AddItem(wxT("CursorLongJumpRight"), _("Cursor Long Jump Right"), FN(OnCursorLongJumpRight), wxT("Shift+."));
|
||||
|
||||
c->AddItem(wxT("ClipLeft"), _("Clip Left"), FN(OnClipLeft), wxT(""));
|
||||
c->AddItem(wxT("ClipRight"), _("Clip Right"), FN(OnClipRight), wxT(""));
|
||||
c->AddItem(wxT("ClipLeft"), _("Clip Left"), FN(OnClipLeft), wxT("\twantKeyup"));
|
||||
c->AddItem(wxT("ClipRight"), _("Clip Right"), FN(OnClipRight), wxT("\twantKeyup"));
|
||||
c->EndSubMenu();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -2082,7 +2082,7 @@ void AudacityProject::SelectAllIfNone()
|
||||
auto flags = GetUpdateFlags();
|
||||
if(!(flags & TracksSelectedFlag) ||
|
||||
(mViewInfo.selectedRegion.isPoint()))
|
||||
OnSelectAll();
|
||||
OnSelectSomething();
|
||||
}
|
||||
|
||||
void AudacityProject::StopIfPaused()
|
||||
@ -3081,14 +3081,55 @@ void AudacityProject::OnSelContractRight(const wxEvent * evt)
|
||||
OnCursorLeft( true, true, bKeyUp );
|
||||
}
|
||||
|
||||
void AudacityProject::OnClipLeft()
|
||||
void AudacityProject::DoClipLeftOrRight(bool right, bool keyUp )
|
||||
{
|
||||
mTrackPanel->OnClipMove(false);
|
||||
if (keyUp) {
|
||||
GetUndoManager()->StopConsolidating();
|
||||
return;
|
||||
}
|
||||
|
||||
auto &panel = *GetTrackPanel();
|
||||
|
||||
auto amount = TrackPanel::OnClipMove
|
||||
( mViewInfo, panel.GetFocusedTrack(),
|
||||
*GetTracks(), IsSyncLocked(), right );
|
||||
|
||||
panel.ScrollIntoView(mViewInfo.selectedRegion.t0());
|
||||
panel.Refresh(false);
|
||||
|
||||
if (amount != 0.0) {
|
||||
wxString message = right? _("Time shifted clips to the right") :
|
||||
_("Time shifted clips to the left");
|
||||
|
||||
// The following use of the UndoPush flags is so that both a single
|
||||
// keypress (keydown, then keyup), and holding down a key
|
||||
// (multiple keydowns followed by a keyup) result in a single
|
||||
// entry in Audacity's history dialog.
|
||||
PushState(message, _("Time-Shift"), UndoPush::CONSOLIDATE);
|
||||
}
|
||||
|
||||
if ( amount == 0.0 )
|
||||
panel.MessageForScreenReader( _("clip not moved"));
|
||||
}
|
||||
|
||||
void AudacityProject::OnClipRight()
|
||||
void AudacityProject::OnClipLeft(const wxEvent* evt)
|
||||
{
|
||||
mTrackPanel->OnClipMove(true);
|
||||
if (evt)
|
||||
DoClipLeftOrRight( false, evt->GetEventType() == wxEVT_KEY_UP );
|
||||
else { // called from menu, so simulate keydown and keyup
|
||||
DoClipLeftOrRight( false, false );
|
||||
DoClipLeftOrRight( false, true );
|
||||
}
|
||||
}
|
||||
|
||||
void AudacityProject::OnClipRight(const wxEvent* evt)
|
||||
{
|
||||
if (evt)
|
||||
DoClipLeftOrRight( true, evt->GetEventType() == wxEVT_KEY_UP );
|
||||
else { // called from menu, so simulate keydown and keyup
|
||||
DoClipLeftOrRight( true, false );
|
||||
DoClipLeftOrRight( true, true );
|
||||
}
|
||||
}
|
||||
|
||||
//this pops up a dialog which allows the left selection to be set.
|
||||
@ -5374,20 +5415,87 @@ void AudacityProject::OnSplitNew()
|
||||
RedrawProject();
|
||||
}
|
||||
|
||||
void AudacityProject::OnSelectAll()
|
||||
int AudacityProject::CountSelectedWaveTracks()
|
||||
{
|
||||
TrackListIterator iter(GetTracks());
|
||||
|
||||
Track *t = iter.First();
|
||||
while (t) {
|
||||
t->SetSelected(true);
|
||||
t = iter.Next();
|
||||
|
||||
int count =0;
|
||||
for (Track *t = iter.First(); t; t = iter.Next()) {
|
||||
if( (t->GetKind() == Track::Wave) && t->GetSelected() )
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int AudacityProject::CountSelectedTracks()
|
||||
{
|
||||
TrackListIterator iter(GetTracks());
|
||||
Track *t = iter.First();
|
||||
|
||||
int count =0;
|
||||
for (Track *t = iter.First(); t; t = iter.Next()) {
|
||||
if( t->GetSelected() )
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void AudacityProject::OnSelectTimeAndTracks(bool bAllTime, bool bAllTracks)
|
||||
{
|
||||
if( bAllTime )
|
||||
mViewInfo.selectedRegion.setTimes(
|
||||
mTracks->GetMinOffset(), mTracks->GetEndTime());
|
||||
|
||||
ModifyState(false);
|
||||
if( bAllTracks ){
|
||||
TrackListIterator iter(GetTracks());
|
||||
for (Track *t = iter.First(); t; t = iter.Next()) {
|
||||
t->SetSelected(true);
|
||||
}
|
||||
|
||||
ModifyState(false);
|
||||
mTrackPanel->Refresh(false);
|
||||
if (mMixerBoard)
|
||||
mMixerBoard->Refresh(false);}
|
||||
}
|
||||
|
||||
void AudacityProject::OnSelectAllTime()
|
||||
{
|
||||
OnSelectTimeAndTracks( true, false );
|
||||
}
|
||||
|
||||
void AudacityProject::OnSelectAllTracks()
|
||||
{
|
||||
OnSelectTimeAndTracks( false, true );
|
||||
}
|
||||
|
||||
void AudacityProject::OnSelectAll()
|
||||
{
|
||||
OnSelectTimeAndTracks( true, true );
|
||||
}
|
||||
|
||||
// This function selects all tracks if no tracks selected,
|
||||
// and all time if no time selected.
|
||||
// There is an argument for making it just count wave tracks,
|
||||
// However you could then not select a label and cut it,
|
||||
// without this function selecting all tracks.
|
||||
void AudacityProject::OnSelectSomething()
|
||||
{
|
||||
bool bTime = mViewInfo.selectedRegion.isPoint();
|
||||
bool bTracks = CountSelectedTracks() == 0;
|
||||
|
||||
if( bTime || bTracks )
|
||||
OnSelectTimeAndTracks(bTime,bTracks);
|
||||
}
|
||||
|
||||
void AudacityProject::SelectNone()
|
||||
{
|
||||
TrackListIterator iter(GetTracks());
|
||||
Track *t = iter.First();
|
||||
while (t) {
|
||||
t->SetSelected(false);
|
||||
t = iter.Next();
|
||||
}
|
||||
mTrackPanel->Refresh(false);
|
||||
if (mMixerBoard)
|
||||
mMixerBoard->Refresh(false);
|
||||
@ -5524,6 +5632,8 @@ AudacityProject::FoundClip AudacityProject::FindNextClip(const WaveTrack* wt, do
|
||||
result.waveTrack = wt;
|
||||
const auto clips = wt->SortedClipArray();
|
||||
|
||||
t0 = AdjustForFindingStartTimes(clips, t0);
|
||||
|
||||
auto p = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() == t0; });
|
||||
if (p != clips.end() && (*p)->GetEndTime() > t1) {
|
||||
@ -5552,6 +5662,8 @@ AudacityProject::FoundClip AudacityProject::FindPrevClip(const WaveTrack* wt, do
|
||||
result.waveTrack = wt;
|
||||
const auto clips = wt->SortedClipArray();
|
||||
|
||||
t0 = AdjustForFindingStartTimes(clips, t0);
|
||||
|
||||
auto p = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() == t0; });
|
||||
if (p != clips.end() && (*p)->GetEndTime() < t1) {
|
||||
@ -5677,10 +5789,10 @@ void AudacityProject::OnSelectClip(bool next)
|
||||
|
||||
message += temp;
|
||||
}
|
||||
if (result.waveTrack->GetNumClips() > 1 || nTracksSearched == 1) {
|
||||
temp.Printf(wxT("%d %s %d "), result.index + 1, _("of"), result.waveTrack->GetNumClips());
|
||||
temp.Printf(wxT("%d %s %d %s "), result.index + 1, _("of"), result.waveTrack->GetNumClips(),
|
||||
result.waveTrack->GetNumClips() == 1 ? _("clip") : _("clips"));
|
||||
message += temp;
|
||||
}
|
||||
|
||||
message += wxT(", ");
|
||||
}
|
||||
mTrackPanel->MessageForScreenReader(message);
|
||||
@ -5719,20 +5831,6 @@ void AudacityProject::OnSelectSyncLockSel()
|
||||
mMixerBoard->Refresh(false);
|
||||
}
|
||||
|
||||
void AudacityProject::OnSelectAllTracks()
|
||||
{
|
||||
TrackListIterator iter(GetTracks());
|
||||
for (Track *t = iter.First(); t; t = iter.Next()) {
|
||||
t->SetSelected(true);
|
||||
}
|
||||
|
||||
ModifyState(false);
|
||||
|
||||
mTrackPanel->Refresh(false);
|
||||
if (mMixerBoard)
|
||||
mMixerBoard->Refresh(false);
|
||||
}
|
||||
|
||||
//
|
||||
// View Menu
|
||||
//
|
||||
@ -6527,27 +6625,18 @@ AudacityProject::FoundClipBoundary AudacityProject::FindNextClipBoundary(const W
|
||||
{
|
||||
AudacityProject::FoundClipBoundary result{};
|
||||
result.waveTrack = wt;
|
||||
|
||||
const auto clips = wt->SortedClipArray();
|
||||
double timeStart = AdjustForFindingStartTimes(clips, time);
|
||||
double timeEnd = AdjustForFindingEndTimes(clips, time);
|
||||
|
||||
auto pStart = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() > time; });
|
||||
return clip->GetStartTime() > timeStart; });
|
||||
auto pEnd = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetEndTime() > time; });
|
||||
return clip->GetEndTime() > timeEnd; });
|
||||
|
||||
if (pStart != clips.end() && pEnd != clips.end()) {
|
||||
if ((*pStart)->GetStartTime() < (*pEnd)->GetEndTime()) {
|
||||
result.nFound = 1;
|
||||
result.time = (*pStart)->GetStartTime();
|
||||
result.index1 = std::distance(clips.begin(), pStart);
|
||||
result.clipStart1 = true;
|
||||
}
|
||||
else if ((*pStart)->GetStartTime() > (*pEnd)->GetEndTime()) {
|
||||
result.nFound = 1;
|
||||
result.time = (*pEnd)->GetEndTime();
|
||||
result.index1 = std::distance(clips.begin(), pEnd);
|
||||
result.clipStart1 = false;
|
||||
}
|
||||
else { // both the end of one clip and the start of the next clip
|
||||
if ((*pEnd)->SharesBoundaryWithNextClip(*pStart)) {
|
||||
// boundary between two clips which are immediately next to each other.
|
||||
result.nFound = 2;
|
||||
result.time = (*pEnd)->GetEndTime();
|
||||
result.index1 = std::distance(clips.begin(), pEnd);
|
||||
@ -6555,6 +6644,18 @@ AudacityProject::FoundClipBoundary AudacityProject::FindNextClipBoundary(const W
|
||||
result.index2 = std::distance(clips.begin(), pStart);
|
||||
result.clipStart2 = true;
|
||||
}
|
||||
else if ((*pStart)->GetStartTime() < (*pEnd)->GetEndTime()) {
|
||||
result.nFound = 1;
|
||||
result.time = (*pStart)->GetStartTime();
|
||||
result.index1 = std::distance(clips.begin(), pStart);
|
||||
result.clipStart1 = true;
|
||||
}
|
||||
else {
|
||||
result.nFound = 1;
|
||||
result.time = (*pEnd)->GetEndTime();
|
||||
result.index1 = std::distance(clips.begin(), pEnd);
|
||||
result.clipStart1 = false;
|
||||
}
|
||||
}
|
||||
else if (pEnd != clips.end()) {
|
||||
result.nFound = 1;
|
||||
@ -6570,34 +6671,37 @@ AudacityProject::FoundClipBoundary AudacityProject::FindPrevClipBoundary(const W
|
||||
{
|
||||
AudacityProject::FoundClipBoundary result{};
|
||||
result.waveTrack = wt;
|
||||
|
||||
const auto clips = wt->SortedClipArray();
|
||||
double timeStart = AdjustForFindingStartTimes(clips, time);
|
||||
double timeEnd = AdjustForFindingEndTimes(clips, time);
|
||||
|
||||
auto pStart = std::find_if(clips.rbegin(), clips.rend(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() < time; });
|
||||
return clip->GetStartTime() < timeStart; });
|
||||
auto pEnd = std::find_if(clips.rbegin(), clips.rend(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetEndTime() < time; });
|
||||
return clip->GetEndTime() < timeEnd; });
|
||||
|
||||
if (pStart != clips.rend() && pEnd != clips.rend()) {
|
||||
if ((*pStart)->GetStartTime() > (*pEnd)->GetEndTime()) {
|
||||
result.nFound = 1;
|
||||
result.time = (*pStart)->GetStartTime();
|
||||
result.index1 = static_cast<int>(clips.size()) - 1 - std::distance(clips.rbegin(), pStart);
|
||||
result.clipStart1 = true;
|
||||
}
|
||||
else if ((*pStart)->GetStartTime() < (*pEnd)->GetEndTime()) {
|
||||
result.nFound = 1;
|
||||
result.time = (*pEnd)->GetEndTime();
|
||||
result.index1 = static_cast<int>(clips.size()) - 1 - std::distance(clips.rbegin(), pEnd);
|
||||
result.clipStart1 = false;
|
||||
}
|
||||
else {
|
||||
result.nFound = 2; // both the start of one clip and the end of the previous clip
|
||||
if ((*pEnd)->SharesBoundaryWithNextClip(*pStart)) {
|
||||
// boundary between two clips which are immediately next to each other.
|
||||
result.nFound = 2;
|
||||
result.time = (*pStart)->GetStartTime();
|
||||
result.index1 = static_cast<int>(clips.size()) - 1 - std::distance(clips.rbegin(), pStart);
|
||||
result.clipStart1 = true;
|
||||
result.index2 = static_cast<int>(clips.size()) - 1 - std::distance(clips.rbegin(), pEnd);
|
||||
result.clipStart2 = false;
|
||||
}
|
||||
else if ((*pStart)->GetStartTime() > (*pEnd)->GetEndTime()) {
|
||||
result.nFound = 1;
|
||||
result.time = (*pStart)->GetStartTime();
|
||||
result.index1 = static_cast<int>(clips.size()) - 1 - std::distance(clips.rbegin(), pStart);
|
||||
result.clipStart1 = true;
|
||||
}
|
||||
else {
|
||||
result.nFound = 1;
|
||||
result.time = (*pEnd)->GetEndTime();
|
||||
result.index1 = static_cast<int>(clips.size()) - 1 - std::distance(clips.rbegin(), pEnd);
|
||||
result.clipStart1 = false;
|
||||
}
|
||||
}
|
||||
else if (pStart != clips.rend()) {
|
||||
result.nFound = 1;
|
||||
@ -6609,6 +6713,42 @@ AudacityProject::FoundClipBoundary AudacityProject::FindPrevClipBoundary(const W
|
||||
return result;
|
||||
}
|
||||
|
||||
// When two clips are immediately next to each other, the GetEndTime() of the first clip and the
|
||||
// GetStartTime() of the second clip may not be exactly equal due to rounding errors. When searching
|
||||
// for the next/prev start time from a given time, the following function adjusts that given time if
|
||||
// necessary to take this into account. If the given time is the end time of the first of two clips which
|
||||
// are next to each other, then the given time is changed to the start time of the second clip.
|
||||
// This ensures that the correct next/prev start time is found.
|
||||
double AudacityProject::AdjustForFindingStartTimes(const std::vector<const WaveClip*> & clips, double time)
|
||||
{
|
||||
auto q = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetEndTime() == time; });
|
||||
if (q != clips.end() && q + 1 != clips.end() &&
|
||||
(*q)->SharesBoundaryWithNextClip(*(q+1))) {
|
||||
time = (*(q+1))->GetStartTime();
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
// When two clips are immediately next to each other, the GetEndTime() of the first clip and the
|
||||
// GetStartTime() of the second clip may not be exactly equal due to rounding errors. When searching
|
||||
// for the next/prev end time from a given time, the following function adjusts that given time if
|
||||
// necessary to take this into account. If the given time is the start time of the second of two clips which
|
||||
// are next to each other, then the given time is changed to the end time of the first clip.
|
||||
// This ensures that the correct next/prev end time is found.
|
||||
double AudacityProject::AdjustForFindingEndTimes(const std::vector<const WaveClip*>& clips, double time)
|
||||
{
|
||||
auto q = std::find_if(clips.begin(), clips.end(), [&] (const WaveClip* const& clip) {
|
||||
return clip->GetStartTime() == time; });
|
||||
if (q != clips.end() && q != clips.begin() &&
|
||||
(*(q - 1))->SharesBoundaryWithNextClip(*q)) {
|
||||
time = (*(q-1))->GetEndTime();
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
int AudacityProject::FindClipBoundaries(double time, bool next, std::vector<FoundClipBoundary>& finalResults)
|
||||
{
|
||||
const TrackList* tracks = GetTracks();
|
||||
@ -6664,7 +6804,8 @@ void AudacityProject::OnCursorPrevClipBoundary()
|
||||
void AudacityProject::OnCursorClipBoundary(bool next)
|
||||
{
|
||||
std::vector<FoundClipBoundary> results;
|
||||
int nTracksSearched = FindClipBoundaries(mViewInfo.selectedRegion.t0(), next, results);
|
||||
int nTracksSearched = FindClipBoundaries(next ? mViewInfo.selectedRegion.t1() :
|
||||
mViewInfo.selectedRegion.t0(), next, results);
|
||||
|
||||
if (results.size() > 0) {
|
||||
// note that if there is more than one result, each has the same time value.
|
||||
@ -6697,10 +6838,11 @@ wxString AudacityProject::ClipBoundaryMessage(int nTracksSearched, const std::ve
|
||||
message += temp;
|
||||
}
|
||||
message += (result.clipStart1 ? _("start") : _("end")) + wxT(" ");
|
||||
if (result.waveTrack->GetNumClips() > 1 ) {
|
||||
temp.Printf(wxT("%d %s %d "), result.index1 + 1, _("of"), result.waveTrack->GetNumClips());
|
||||
|
||||
temp.Printf(wxT("%d %s %d %s "), result.index1 + 1, _("of"), result.waveTrack->GetNumClips(),
|
||||
result.waveTrack->GetNumClips() == 1 ? _("clip") : _("clips"));
|
||||
message += temp;
|
||||
}
|
||||
|
||||
if (result.nFound == 2) {
|
||||
temp.Printf(wxT("%s %s %d "), _("and"), result.clipStart2 ? _("start") : _("end"),
|
||||
result.index2 + 1);
|
||||
@ -6892,7 +7034,7 @@ void AudacityProject::OnAlignNoSync(int index)
|
||||
void AudacityProject::OnAlign(int index)
|
||||
{
|
||||
bool bMoveWith;
|
||||
gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, true);
|
||||
gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, false);
|
||||
HandleAlign(index, bMoveWith);
|
||||
}
|
||||
/*
|
||||
@ -7098,14 +7240,6 @@ void AudacityProject::OnScoreAlign()
|
||||
// Make a copy of the note track in case alignment is canceled or fails
|
||||
auto holder = nt->Duplicate();
|
||||
auto alignedNoteTrack = static_cast<NoteTrack*>(holder.get());
|
||||
// Duplicate() on note tracks serializes seq to a buffer, but we need
|
||||
// the seq, so Duplicate again and discard the track with buffer. The
|
||||
// test is here in case Duplicate() is changed in the future.
|
||||
if (alignedNoteTrack->GetSequence() == NULL) {
|
||||
holder = alignedNoteTrack->Duplicate();
|
||||
alignedNoteTrack = static_cast<NoteTrack*>(holder.get());
|
||||
wxASSERT(alignedNoteTrack->GetSequence());
|
||||
}
|
||||
// Remove offset from NoteTrack because audio is
|
||||
// mixed starting at zero and incorporating clip offsets.
|
||||
if (alignedNoteTrack->GetOffset() < 0) {
|
||||
@ -7145,7 +7279,7 @@ void AudacityProject::OnScoreAlign()
|
||||
#ifndef SKIP_ACTUAL_SCORE_ALIGNMENT
|
||||
result = scorealign((void *) &mix, &mixer_process,
|
||||
2 /* channels */, 44100.0 /* srate */, endTime,
|
||||
alignedNoteTrack->GetSequence(), &progress, params);
|
||||
&alignedNoteTrack->GetSeq(), &progress, params);
|
||||
#else
|
||||
result = SA_SUCCESS;
|
||||
#endif
|
||||
@ -7398,7 +7532,7 @@ int AudacityProject::DoAddLabel(const SelectedRegion ®ion, bool preserveFocus
|
||||
void AudacityProject::OnMoveSelectionWithTracks()
|
||||
{
|
||||
bool bMoveWith;
|
||||
gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, true);
|
||||
gPrefs->Read(wxT("/GUI/MoveSelectionWithTracks"), &bMoveWith, false);
|
||||
gPrefs->Write(wxT("/GUI/MoveSelectionWithTracks"), !bMoveWith);
|
||||
gPrefs->Flush();
|
||||
|
||||
@ -7878,6 +8012,7 @@ void AudacityProject::OnResample()
|
||||
}
|
||||
}
|
||||
|
||||
GetUndoManager()->StopConsolidating();
|
||||
RedrawProject();
|
||||
|
||||
// Need to reset
|
||||
|
17
src/Menus.h
17
src/Menus.h
@ -160,8 +160,10 @@ void OnSelExtendRight(const wxEvent * evt);
|
||||
void OnSelContractLeft(const wxEvent * evt);
|
||||
void OnSelContractRight(const wxEvent * evt);
|
||||
|
||||
void OnClipLeft();
|
||||
void OnClipRight();
|
||||
public:
|
||||
void DoClipLeftOrRight(bool right, bool keyUp );
|
||||
void OnClipLeft(const wxEvent* evt);
|
||||
void OnClipRight(const wxEvent* evt);
|
||||
|
||||
void OnCursorShortJumpLeft();
|
||||
void OnCursorShortJumpRight();
|
||||
@ -275,8 +277,16 @@ void OnSplitLabels();
|
||||
void OnJoinLabels();
|
||||
void OnDisjoinLabels();
|
||||
|
||||
void OnSelectTimeAndTracks(bool bAllTime, bool bAllTracks);
|
||||
void OnSelectAllTime();
|
||||
void OnSelectAllTracks();
|
||||
void OnSelectAll();
|
||||
void OnSelectSomething();
|
||||
void OnSelectNone();
|
||||
private:
|
||||
int CountSelectedWaveTracks();
|
||||
int CountSelectedTracks();
|
||||
public:
|
||||
#ifdef EXPERIMENTAL_SPECTRAL_EDITING
|
||||
void OnToggleSpectralSelection();
|
||||
void DoNextPeakFrequency(bool up);
|
||||
@ -303,7 +313,6 @@ void OnSelectNextClip();
|
||||
void OnSelectClip(bool next);
|
||||
void OnSelectCursorStoredCursor();
|
||||
void OnSelectSyncLockSel();
|
||||
void OnSelectAllTracks();
|
||||
|
||||
// View Menu
|
||||
|
||||
@ -411,6 +420,8 @@ typedef struct FoundClipBoundary {
|
||||
} FoundClipBoundary;
|
||||
FoundClipBoundary FindNextClipBoundary(const WaveTrack* wt, double time);
|
||||
FoundClipBoundary FindPrevClipBoundary(const WaveTrack* wt, double time);
|
||||
double AdjustForFindingStartTimes(const std::vector<const WaveClip*>& clips, double time);
|
||||
double AdjustForFindingEndTimes(const std::vector<const WaveClip*>& clips, double time);
|
||||
int FindClipBoundaries(double time, bool next, std::vector<FoundClipBoundary>& results);
|
||||
void OnCursorNextClipBoundary();
|
||||
void OnCursorPrevClipBoundary();
|
||||
|
@ -776,11 +776,9 @@ void MixerTrackCluster::OnButton_Solo(wxCommandEvent& WXUNUSED(event))
|
||||
// Have to refresh all tracks.
|
||||
mMixerBoard->UpdateMute();
|
||||
mMixerBoard->UpdateSolo();
|
||||
mProject->RedrawProject();
|
||||
}
|
||||
else
|
||||
// Update only the changed track.
|
||||
mProject->RefreshTPTrack(mTrack);
|
||||
// Bug 509: Must repaint all, as many tracks can change with one Solo change.
|
||||
mProject->RedrawProject();
|
||||
}
|
||||
|
||||
|
||||
@ -1512,7 +1510,8 @@ MixerBoardFrame::MixerBoardFrame(AudacityProject* parent)
|
||||
#endif
|
||||
SetIcon(ic);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
Center();
|
||||
}
|
||||
|
||||
MixerBoardFrame::~MixerBoardFrame()
|
||||
|
@ -95,7 +95,9 @@ public:
|
||||
// PluginManager use
|
||||
bool DiscoverProviders();
|
||||
|
||||
// Seems we don't currently use FindAllPlugins
|
||||
void FindAllPlugins(PluginIDList & providers, wxArrayString & paths);
|
||||
|
||||
wxArrayString FindPluginsForProvider(const PluginID & provider, const wxString & path);
|
||||
bool RegisterPlugin(const PluginID & provider, const wxString & path);
|
||||
|
||||
|
@ -127,15 +127,35 @@ NoteTrack::~NoteTrack()
|
||||
{
|
||||
}
|
||||
|
||||
Alg_seq &NoteTrack::GetSeq() const
|
||||
{
|
||||
if (!mSeq) {
|
||||
if (!mSerializationBuffer)
|
||||
mSeq = std::make_unique<Alg_seq>();
|
||||
else {
|
||||
std::unique_ptr<Alg_track> alg_track
|
||||
{ Alg_seq::unserialize
|
||||
( mSerializationBuffer.get(), mSerializationLength ) };
|
||||
wxASSERT(alg_track->get_type() == 's');
|
||||
mSeq.reset( static_cast<Alg_seq*>(alg_track.release()) );
|
||||
|
||||
// Preserve the invariant that at most one of the representations is
|
||||
// valid
|
||||
mSerializationBuffer.reset();
|
||||
mSerializationLength = 0;
|
||||
}
|
||||
}
|
||||
wxASSERT(mSeq);
|
||||
return *mSeq;
|
||||
}
|
||||
|
||||
Track::Holder NoteTrack::Duplicate() const
|
||||
{
|
||||
auto duplicate = std::make_unique<NoteTrack>(mDirManager);
|
||||
duplicate->Init(*this);
|
||||
// Duplicate on NoteTrack moves data from mSeq to mSerializationBuffer
|
||||
// and from mSerializationBuffer to mSeq on alternate calls. Duplicate
|
||||
// to the undo stack and Duplicate back to the project should result
|
||||
// in serialized blobs on the undo stack and traversable data in the
|
||||
// project object.
|
||||
// The duplicate begins life in serialized state. Often the duplicate is
|
||||
// pushed on the Undo stack. Then we want to un-serialize it (or a further
|
||||
// copy) only on demand after an Undo.
|
||||
if (mSeq) {
|
||||
SonifyBeginSerialize();
|
||||
wxASSERT(!mSerializationBuffer);
|
||||
@ -145,15 +165,19 @@ Track::Holder NoteTrack::Duplicate() const
|
||||
&duplicate->mSerializationLength);
|
||||
duplicate->mSerializationBuffer.reset( (char*)buffer );
|
||||
SonifyEndSerialize();
|
||||
} else if (mSerializationBuffer) {
|
||||
SonifyBeginUnserialize();
|
||||
}
|
||||
else if (mSerializationBuffer) {
|
||||
// Copy already serialized data.
|
||||
wxASSERT(!mSeq);
|
||||
std::unique_ptr<Alg_track> alg_track{ Alg_seq::unserialize(mSerializationBuffer.get(),
|
||||
mSerializationLength) };
|
||||
wxASSERT(alg_track->get_type() == 's');
|
||||
duplicate->mSeq.reset(static_cast<Alg_seq*>(alg_track.release()));
|
||||
SonifyEndUnserialize();
|
||||
} else wxFAIL_MSG("neither mSeq nor mSerializationBuffer were present"); // bug if neither mSeq nor mSerializationBuffer
|
||||
duplicate->mSerializationLength = this->mSerializationLength;
|
||||
duplicate->mSerializationBuffer.reset
|
||||
( new char[ this->mSerializationLength ] );
|
||||
memcpy( duplicate->mSerializationBuffer.get(),
|
||||
this->mSerializationBuffer.get(), this->mSerializationLength );
|
||||
}
|
||||
else {
|
||||
// We are duplicating a default-constructed NoteTrack, and that's okay
|
||||
}
|
||||
// copy some other fields here
|
||||
duplicate->SetBottomNote(mBottomNote);
|
||||
duplicate->SetPitchHeight(mPitchHeight);
|
||||
@ -180,7 +204,7 @@ double NoteTrack::GetStartTime() const
|
||||
|
||||
double NoteTrack::GetEndTime() const
|
||||
{
|
||||
return GetStartTime() + (mSeq ? mSeq->get_real_dur() : 0.0);
|
||||
return GetStartTime() + GetSeq().get_real_dur();
|
||||
}
|
||||
|
||||
|
||||
@ -188,25 +212,13 @@ void NoteTrack::WarpAndTransposeNotes(double t0, double t1,
|
||||
const TimeWarper &warper,
|
||||
double semitones)
|
||||
{
|
||||
// Since this is a duplicate and duplicates convert mSeq to
|
||||
// a text string for saving as XML, we probably have to
|
||||
// duplicate again to get back an mSeq
|
||||
double offset = this->GetOffset(); // track is shifted this amount
|
||||
if (!mSeq) { // replace saveme with an (unserialized) duplicate
|
||||
Track::Holder unt{ Duplicate() };
|
||||
const auto nt = static_cast<NoteTrack*>(unt.get());
|
||||
wxASSERT(!mSeq && nt->mSeq && !nt->mSerializationBuffer);
|
||||
// swap mSeq and Buffer between this and nt
|
||||
nt->mSerializationBuffer = std::move(mSerializationBuffer);
|
||||
nt->mSerializationLength = mSerializationLength;
|
||||
mSerializationLength = 0;
|
||||
mSeq = std::move(nt->mSeq);
|
||||
}
|
||||
mSeq->convert_to_seconds(); // make sure time units are right
|
||||
auto &seq = GetSeq();
|
||||
seq.convert_to_seconds(); // make sure time units are right
|
||||
t1 -= offset; // adjust time range to compensate for track offset
|
||||
t0 -= offset;
|
||||
if (t1 > mSeq->get_dur()) { // make sure t0, t1 are within sequence
|
||||
t1 = mSeq->get_dur();
|
||||
if (t1 > seq.get_dur()) { // make sure t0, t1 are within sequence
|
||||
t1 = seq.get_dur();
|
||||
if (t0 >= t1) return;
|
||||
}
|
||||
Alg_iterator iter(mSeq.get(), false);
|
||||
@ -219,8 +231,8 @@ void NoteTrack::WarpAndTransposeNotes(double t0, double t1,
|
||||
}
|
||||
iter.end();
|
||||
// now, use warper to warp the tempo map
|
||||
mSeq->convert_to_beats(); // beats remain the same
|
||||
Alg_time_map_ptr map = mSeq->get_time_map();
|
||||
seq.convert_to_beats(); // beats remain the same
|
||||
Alg_time_map_ptr map = seq.get_time_map();
|
||||
map->insert_beat(t0, map->time_to_beat(t0));
|
||||
map->insert_beat(t1, map->time_to_beat(t1));
|
||||
int i, len = map->length();
|
||||
@ -229,7 +241,7 @@ void NoteTrack::WarpAndTransposeNotes(double t0, double t1,
|
||||
beat.time = warper.Warp(beat.time + offset) - offset;
|
||||
}
|
||||
// about to redisplay, so might as well convert back to time now
|
||||
mSeq->convert_to_seconds();
|
||||
seq.convert_to_seconds();
|
||||
}
|
||||
|
||||
// Draws the midi channel toggle buttons within the given rect.
|
||||
@ -348,11 +360,6 @@ void NoteTrack::SetSequence(std::unique_ptr<Alg_seq> &&seq)
|
||||
mSeq = std::move(seq);
|
||||
}
|
||||
|
||||
Alg_seq* NoteTrack::GetSequence()
|
||||
{
|
||||
return mSeq.get();
|
||||
}
|
||||
|
||||
void NoteTrack::PrintSequence()
|
||||
{
|
||||
FILE *debugOutput;
|
||||
@ -360,6 +367,8 @@ void NoteTrack::PrintSequence()
|
||||
debugOutput = fopen("debugOutput.txt", "wt");
|
||||
fprintf(debugOutput, "Importing MIDI...\n");
|
||||
|
||||
// This is called for debugging purposes. Do not compute mSeq on demand
|
||||
// with GetSeq()
|
||||
if (mSeq) {
|
||||
int i = 0;
|
||||
|
||||
@ -416,15 +425,23 @@ Track::Holder NoteTrack::Cut(double t0, double t1)
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
||||
double len = t1-t0;
|
||||
//auto delta = -(
|
||||
//( std::min( t1, GetEndTime() ) ) - ( std::max( t0, GetStartTime() ) )
|
||||
//);
|
||||
|
||||
auto newTrack = std::make_unique<NoteTrack>(mDirManager);
|
||||
|
||||
newTrack->Init(*this);
|
||||
|
||||
mSeq->convert_to_seconds();
|
||||
newTrack->mSeq.reset(mSeq->cut(t0 - GetOffset(), len, false));
|
||||
auto &seq = GetSeq();
|
||||
seq.convert_to_seconds();
|
||||
newTrack->mSeq.reset(seq.cut(t0 - GetOffset(), len, false));
|
||||
newTrack->SetOffset(GetOffset());
|
||||
|
||||
// Not needed
|
||||
// Alg_seq::cut seems to handle this
|
||||
//AddToDuration( delta );
|
||||
|
||||
// What should be done with the rest of newTrack's members?
|
||||
//(mBottomNote, mDirManager, mLastMidiPosition,
|
||||
// mSerializationBuffer, mSerializationLength, mVisibleChannels)
|
||||
@ -444,8 +461,9 @@ Track::Holder NoteTrack::Copy(double t0, double t1, bool) const
|
||||
|
||||
newTrack->Init(*this);
|
||||
|
||||
mSeq->convert_to_seconds();
|
||||
newTrack->mSeq.reset(mSeq->copy(t0 - GetOffset(), len, false));
|
||||
auto &seq = GetSeq();
|
||||
seq.convert_to_seconds();
|
||||
newTrack->mSeq.reset(seq.copy(t0 - GetOffset(), len, false));
|
||||
newTrack->SetOffset(GetOffset());
|
||||
|
||||
// What should be done with the rest of newTrack's members?
|
||||
@ -460,13 +478,23 @@ bool NoteTrack::Trim(double t0, double t1)
|
||||
{
|
||||
if (t1 < t0)
|
||||
return false;
|
||||
mSeq->convert_to_seconds();
|
||||
auto &seq = GetSeq();
|
||||
//auto delta = -(
|
||||
//( GetEndTime() - std::min( GetEndTime(), t1 ) ) +
|
||||
//( std::max(t0, GetStartTime()) - GetStartTime() )
|
||||
//);
|
||||
seq.convert_to_seconds();
|
||||
// DELETE way beyond duration just in case something is out there:
|
||||
mSeq->clear(t1 - GetOffset(), mSeq->get_dur() + 10000.0, false);
|
||||
seq.clear(t1 - GetOffset(), seq.get_dur() + 10000.0, false);
|
||||
// Now that stuff beyond selection is cleared, clear before selection:
|
||||
mSeq->clear(0.0, t0 - GetOffset(), false);
|
||||
seq.clear(0.0, t0 - GetOffset(), false);
|
||||
// want starting time to be t0
|
||||
SetOffset(t0);
|
||||
|
||||
// Not needed
|
||||
// Alg_seq::clear seems to handle this
|
||||
//AddToDuration( delta );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -477,8 +505,15 @@ void NoteTrack::Clear(double t0, double t1)
|
||||
|
||||
double len = t1-t0;
|
||||
|
||||
if (mSeq)
|
||||
mSeq->clear(t0 - GetOffset(), len, false);
|
||||
auto &seq = GetSeq();
|
||||
//auto delta = -(
|
||||
//( std::min( t1, GetEndTime() ) ) - ( std::max( t0, GetStartTime() ) )
|
||||
//);
|
||||
seq.clear(t0 - GetOffset(), len, false);
|
||||
|
||||
// Not needed
|
||||
// Alg_seq::clear seems to handle this
|
||||
// AddToDuration( delta );
|
||||
}
|
||||
|
||||
void NoteTrack::Paste(double t, const Track *src)
|
||||
@ -497,19 +532,27 @@ void NoteTrack::Paste(double t, const Track *src)
|
||||
return;
|
||||
|
||||
NoteTrack* other = (NoteTrack*)src;
|
||||
if (other->mSeq == NULL)
|
||||
// THROW_INCONSISTENCY_EXCEPTION; // ?
|
||||
return;
|
||||
|
||||
if(!mSeq)
|
||||
mSeq = std::make_unique<Alg_seq>();
|
||||
|
||||
if (other->GetOffset() > 0) {
|
||||
mSeq->convert_to_seconds();
|
||||
mSeq->insert_silence(t - GetOffset(), other->GetOffset());
|
||||
t += other->GetOffset();
|
||||
double delta = 0.0;
|
||||
auto &seq = GetSeq();
|
||||
auto offset = other->GetOffset();
|
||||
if ( offset > 0 ) {
|
||||
seq.convert_to_seconds();
|
||||
seq.insert_silence( t - GetOffset(), offset );
|
||||
t += offset;
|
||||
// Is this needed or does Alg_seq::insert_silence take care of it?
|
||||
//delta += offset;
|
||||
}
|
||||
mSeq->paste(t - GetOffset(), other->mSeq.get());
|
||||
|
||||
// This seems to be needed:
|
||||
delta += std::max( 0.0, t - GetEndTime() );
|
||||
|
||||
// This, not:
|
||||
//delta += other->GetSeq().get_real_dur();
|
||||
|
||||
seq.paste(t - GetOffset(), &other->GetSeq());
|
||||
|
||||
AddToDuration( delta );
|
||||
}
|
||||
|
||||
void NoteTrack::Silence(double t0, double t1)
|
||||
@ -519,20 +562,25 @@ void NoteTrack::Silence(double t0, double t1)
|
||||
|
||||
auto len = t1 - t0;
|
||||
|
||||
mSeq->convert_to_seconds();
|
||||
auto &seq = GetSeq();
|
||||
seq.convert_to_seconds();
|
||||
// XXX: do we want to set the all param?
|
||||
// If it's set, then it seems like notes are silenced if they start or end in the range,
|
||||
// otherwise only if they start in the range. --Poke
|
||||
mSeq->silence(t0 - GetOffset(), len, false);
|
||||
seq.silence(t0 - GetOffset(), len, false);
|
||||
}
|
||||
|
||||
void NoteTrack::InsertSilence(double t, double len)
|
||||
{
|
||||
if (len <= 0)
|
||||
if (len < 0)
|
||||
THROW_INCONSISTENCY_EXCEPTION;
|
||||
|
||||
mSeq->convert_to_seconds();
|
||||
mSeq->insert_silence(t - GetOffset(), len);
|
||||
auto &seq = GetSeq();
|
||||
seq.convert_to_seconds();
|
||||
seq.insert_silence(t - GetOffset(), len);
|
||||
|
||||
// is this needed?
|
||||
// AddToDuration( len );
|
||||
}
|
||||
|
||||
// Call this function to manipulate the underlying sequence data. This is
|
||||
@ -540,51 +588,61 @@ void NoteTrack::InsertSilence(double t, double len)
|
||||
bool NoteTrack::Shift(double t) // t is always seconds
|
||||
{
|
||||
if (t > 0) {
|
||||
auto &seq = GetSeq();
|
||||
// insert an even number of measures
|
||||
mSeq->convert_to_beats();
|
||||
seq.convert_to_beats();
|
||||
// get initial tempo
|
||||
double tempo = mSeq->get_tempo(0.0);
|
||||
double beats_per_measure = mSeq->get_bar_len(0.0);
|
||||
double tempo = seq.get_tempo(0.0);
|
||||
double beats_per_measure = seq.get_bar_len(0.0);
|
||||
int m = ROUND(t * tempo / beats_per_measure);
|
||||
// need at least 1 measure, so if we rounded down to zero, fix it
|
||||
if (m == 0) m = 1;
|
||||
// compute NEW tempo so that m measures at NEW tempo take t seconds
|
||||
tempo = beats_per_measure * m / t; // in beats per second
|
||||
mSeq->insert_silence(0.0, beats_per_measure * m);
|
||||
mSeq->set_tempo(tempo * 60.0 /* bpm */, 0.0, beats_per_measure * m);
|
||||
mSeq->write("afterShift.gro");
|
||||
seq.insert_silence(0.0, beats_per_measure * m);
|
||||
seq.set_tempo(tempo * 60.0 /* bpm */, 0.0, beats_per_measure * m);
|
||||
seq.write("afterShift.gro");
|
||||
} else if (t < 0) {
|
||||
mSeq->convert_to_seconds();
|
||||
mSeq->clear(0, t, true);
|
||||
auto &seq = GetSeq();
|
||||
seq.convert_to_seconds();
|
||||
seq.clear(0, t, true);
|
||||
} else { // offset is zero, no modifications
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double NoteTrack::NearestBeatTime(double time, double *beat) const
|
||||
QuantizedTimeAndBeat NoteTrack::NearestBeatTime( double time ) const
|
||||
{
|
||||
wxASSERT(mSeq);
|
||||
// Alg_seq knows nothing about offset, so remove offset time
|
||||
double seq_time = time - GetOffset();
|
||||
seq_time = mSeq->nearest_beat_time(seq_time, beat);
|
||||
double beat;
|
||||
auto &seq = GetSeq();
|
||||
seq_time = seq.nearest_beat_time(seq_time, &beat);
|
||||
// add the offset back in to get "actual" audacity track time
|
||||
return seq_time + GetOffset();
|
||||
return { seq_time + GetOffset(), beat };
|
||||
}
|
||||
|
||||
bool NoteTrack::StretchRegion(double t0, double t1, double dur)
|
||||
void NoteTrack::AddToDuration( double delta )
|
||||
{
|
||||
wxASSERT(mSeq);
|
||||
// Alg_seq::stretch_region uses beats, so we translate time
|
||||
// to beats first:
|
||||
t0 -= GetOffset();
|
||||
t1 -= GetOffset();
|
||||
double b0 = mSeq->get_time_map()->time_to_beat(t0);
|
||||
double b1 = mSeq->get_time_map()->time_to_beat(t1);
|
||||
bool result = mSeq->stretch_region(b0, b1, dur);
|
||||
auto &seq = GetSeq();
|
||||
#if 0
|
||||
// PRL: Would this be better ?
|
||||
seq.set_real_dur( seq.get_real_dur() + delta );
|
||||
#else
|
||||
seq.convert_to_seconds();
|
||||
seq.set_dur( seq.get_dur() + delta );
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NoteTrack::StretchRegion
|
||||
( QuantizedTimeAndBeat t0, QuantizedTimeAndBeat t1, double newDur )
|
||||
{
|
||||
auto &seq = GetSeq();
|
||||
bool result = seq.stretch_region( t0.second, t1.second, newDur );
|
||||
if (result) {
|
||||
mSeq->convert_to_seconds();
|
||||
mSeq->set_dur(mSeq->get_dur() + dur - (t1 - t0));
|
||||
const auto oldDur = t1.first - t0.first;
|
||||
AddToDuration( newDur - oldDur );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -604,24 +662,21 @@ Alg_seq *NoteTrack::MakeExportableSeq(std::unique_ptr<Alg_seq> &cleanup) const
|
||||
cleanup.reset();
|
||||
double offset = GetOffset();
|
||||
if (offset == 0)
|
||||
return mSeq.get();
|
||||
return &GetSeq();
|
||||
// make a copy, deleting events that are shifted before time 0
|
||||
double start = -offset;
|
||||
if (start < 0) start = 0;
|
||||
// notes that begin before "start" are not included even if they
|
||||
// extend past "start" (because "all" parameter is set to false)
|
||||
cleanup.reset( mSeq->copy(start, mSeq->get_dur() - start, false) );
|
||||
cleanup.reset( GetSeq().copy(start, GetSeq().get_dur() - start, false) );
|
||||
auto seq = cleanup.get();
|
||||
if (offset > 0) {
|
||||
{
|
||||
// Cheat a little
|
||||
NoteTrack *pMutable = const_cast< NoteTrack * >(this);
|
||||
|
||||
// swap cleanup and mSeq so that Shift operates on the NEW copy
|
||||
swap(pMutable->mSeq, cleanup);
|
||||
auto cleanup2 = finally( [&] { swap(pMutable->mSeq, cleanup); } );
|
||||
swap( this->mSeq, cleanup );
|
||||
auto cleanup2 = finally( [&] { swap( this->mSeq, cleanup ); } );
|
||||
|
||||
pMutable->Shift(offset);
|
||||
const_cast< NoteTrack *>( this )->Shift(offset);
|
||||
}
|
||||
#ifdef OLD_CODE
|
||||
// now shift events by offset. This must be done with an integer
|
||||
@ -664,27 +719,28 @@ Alg_seq *NoteTrack::MakeExportableSeq(std::unique_ptr<Alg_seq> &cleanup) const
|
||||
seq->set_tempo(bps * 60.0, 0, beats_per_measure * n);
|
||||
#endif
|
||||
} else {
|
||||
auto &mySeq = GetSeq();
|
||||
// if offset is negative, it might not be a multiple of beats, but
|
||||
// we want to preserve the relative positions of measures. I.e. we
|
||||
// should shift barlines and time signatures as well as notes.
|
||||
// Insert a time signature at the first bar-line if necessary.
|
||||
|
||||
// Translate start from seconds to beats and call it beat:
|
||||
double beat = mSeq->get_time_map()->time_to_beat(start);
|
||||
// Find the time signature in mSeq in effect at start (beat):
|
||||
int i = mSeq->time_sig.find_beat(beat);
|
||||
double beat = mySeq.get_time_map()->time_to_beat(start);
|
||||
// Find the time signature in mySeq in effect at start (beat):
|
||||
int i = mySeq.time_sig.find_beat(beat);
|
||||
// i is where you would insert a NEW time sig at beat,
|
||||
// Case 1: beat coincides with a time sig at i. Time signature
|
||||
// at beat means that there is a barline at beat, so when beat
|
||||
// is shifted to 0, the relative barline positions are preserved
|
||||
if (mSeq->time_sig.length() > 0 &&
|
||||
within(beat, mSeq->time_sig[i].beat, ALG_EPS)) {
|
||||
if (mySeq.time_sig.length() > 0 &&
|
||||
within(beat, mySeq.time_sig[i].beat, ALG_EPS)) {
|
||||
// beat coincides with time signature change, so offset must
|
||||
// be a multiple of beats
|
||||
/* do nothing */ ;
|
||||
// Case 2: there is no time signature before beat.
|
||||
} else if (i == 0 && (mSeq->time_sig.length() == 0 ||
|
||||
mSeq->time_sig[i].beat > beat)) {
|
||||
} else if (i == 0 && (mySeq.time_sig.length() == 0 ||
|
||||
mySeq.time_sig[i].beat > beat)) {
|
||||
// If beat does not fall on an implied barline, we need to
|
||||
// insert a time signature.
|
||||
double measures = beat / 4.0;
|
||||
@ -701,7 +757,7 @@ Alg_seq *NoteTrack::MakeExportableSeq(std::unique_ptr<Alg_seq> &cleanup) const
|
||||
// Case 3: i-1 must be the effective time sig position
|
||||
} else {
|
||||
i -= 1; // index the time signature in effect at beat
|
||||
Alg_time_sig_ptr tsp = &(mSeq->time_sig[i]);
|
||||
Alg_time_sig_ptr tsp = &(mySeq.time_sig[i]);
|
||||
double beats_per_measure = (tsp->num * 4) / tsp->den;
|
||||
double measures = (beat - tsp->beat) / beats_per_measure;
|
||||
int imeasures = ROUND(measures);
|
||||
@ -737,12 +793,13 @@ bool NoteTrack::ExportAllegro(const wxString &f) const
|
||||
double offset = GetOffset();
|
||||
bool in_seconds;
|
||||
gPrefs->Read(wxT("/FileFormats/AllegroStyle"), &in_seconds, true);
|
||||
auto &seq = GetSeq();
|
||||
if (in_seconds) {
|
||||
mSeq->convert_to_seconds();
|
||||
seq.convert_to_seconds();
|
||||
} else {
|
||||
mSeq->convert_to_beats();
|
||||
seq.convert_to_beats();
|
||||
}
|
||||
return mSeq->write(f.mb_str(), offset);
|
||||
return seq.write(f.mb_str(), offset);
|
||||
}
|
||||
|
||||
|
||||
@ -810,28 +867,15 @@ void NoteTrack::WriteXML(XMLWriter &xmlFile) const
|
||||
// may throw
|
||||
{
|
||||
std::ostringstream data;
|
||||
// Normally, Duplicate is called in pairs -- once to put NoteTrack
|
||||
// on the Undo stack, and again to move from the Undo stack to an
|
||||
// "active" editable state. For efficiency, we do not do a "real"
|
||||
// Duplicate followed by serialization into a binary blob. Instead,
|
||||
// we combine the Duplicate with serialization or unserialization.
|
||||
// Serialization and Unserialization happen on alternate calls to
|
||||
// Duplicate and (usually) produce the right results at the right
|
||||
// time.
|
||||
// It turns out that this optimized Duplicate is a little too
|
||||
// clever. There is at least one case where a track can be duplicated
|
||||
// and then AutoSave'd. (E.g. do an "Insert Silence" effect on a
|
||||
// NoteTrack.) In this case, mSeq will be NULL. To avoid a crash
|
||||
// and perform WriteXML, we may need to restore NoteTracks from binary
|
||||
// blobs to regular data structures (with an Alg_seq member).
|
||||
Track::Holder holder;
|
||||
const NoteTrack *saveme = this;
|
||||
if (!mSeq) { // replace saveme with an (unserialized) duplicate
|
||||
if (!mSeq) {
|
||||
// replace saveme with an (unserialized) duplicate, which is
|
||||
// destroyed at end of function.
|
||||
holder = Duplicate();
|
||||
saveme = static_cast<NoteTrack*>(holder.get());
|
||||
wxASSERT(saveme->mSeq);
|
||||
}
|
||||
saveme->mSeq->write(data, true);
|
||||
saveme->GetSeq().write(data, true);
|
||||
xmlFile.StartTag(wxT("notetrack"));
|
||||
xmlFile.WriteAttr(wxT("name"), saveme->mName);
|
||||
this->NoteTrackBase::WriteXMLAttributes(xmlFile);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#ifndef __AUDACITY_NOTETRACK__
|
||||
#define __AUDACITY_NOTETRACK__
|
||||
|
||||
#include <utility>
|
||||
#include <wx/string.h>
|
||||
#include "Audacity.h"
|
||||
#include "Experimental.h"
|
||||
@ -58,12 +59,12 @@ using NoteTrackBase =
|
||||
#endif
|
||||
;
|
||||
|
||||
using QuantizedTimeAndBeat = std::pair< double, double >;
|
||||
|
||||
class AUDACITY_DLL_API NoteTrack final
|
||||
: public NoteTrackBase
|
||||
{
|
||||
public:
|
||||
friend class TrackArtist;
|
||||
|
||||
NoteTrack(const std::shared_ptr<DirManager> &projDirManager);
|
||||
virtual ~NoteTrack();
|
||||
|
||||
@ -76,6 +77,8 @@ class AUDACITY_DLL_API NoteTrack final
|
||||
double GetStartTime() const override;
|
||||
double GetEndTime() const override;
|
||||
|
||||
Alg_seq &GetSeq() const;
|
||||
|
||||
void WarpAndTransposeNotes(double t0, double t1,
|
||||
const TimeWarper &warper, double semitones);
|
||||
|
||||
@ -83,7 +86,6 @@ class AUDACITY_DLL_API NoteTrack final
|
||||
bool LabelClick(const wxRect &rect, int x, int y, bool right);
|
||||
|
||||
void SetSequence(std::unique_ptr<Alg_seq> &&seq);
|
||||
Alg_seq* GetSequence();
|
||||
void PrintSequence();
|
||||
|
||||
Alg_seq *MakeExportableSeq(std::unique_ptr<Alg_seq> &cleanup) const;
|
||||
@ -112,8 +114,9 @@ class AUDACITY_DLL_API NoteTrack final
|
||||
void SetVelocity(float velocity) { mVelocity = velocity; }
|
||||
#endif
|
||||
|
||||
double NearestBeatTime(double time, double *beat) const;
|
||||
bool StretchRegion(double b0, double b1, double dur);
|
||||
QuantizedTimeAndBeat NearestBeatTime( double time ) const;
|
||||
bool StretchRegion
|
||||
( QuantizedTimeAndBeat t0, QuantizedTimeAndBeat t1, double newDur );
|
||||
|
||||
int GetBottomNote() const { return mBottomNote; }
|
||||
int GetPitchHeight() const { return mPitchHeight; }
|
||||
@ -204,21 +207,17 @@ class AUDACITY_DLL_API NoteTrack final
|
||||
else
|
||||
mVisibleChannels = CHANNEL_BIT(c);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Alg_seq> mSeq; // NULL means no sequence
|
||||
// when Duplicate() is called, assume that it is to put a copy
|
||||
// of the track into the undo stack or to redo/copy from the
|
||||
// stack to the project object. We want copies to the stack
|
||||
// to be serialized (therefore compact) representations, so
|
||||
// copy will set mSeq to NULL and serialize to the following
|
||||
// variables. If this design is correct, the track will be
|
||||
// duplicated again (in the event of redo) back to the project
|
||||
// at which point we will unserialize the data back to the
|
||||
// mSeq variable. (TrackArtist should check to make sure this
|
||||
// flip-flop from mSeq to mSerializationBuffer happened an
|
||||
// even number of times, otherwise mSeq will be NULL).
|
||||
mutable std::unique_ptr<char[]> mSerializationBuffer; // NULL means no buffer
|
||||
long mSerializationLength;
|
||||
void AddToDuration( double delta );
|
||||
|
||||
// These are mutable to allow NoteTrack to switch details of representation
|
||||
// in logically const methods
|
||||
// At most one of the two pointers is not null at any time.
|
||||
// Both are null in a newly constructed NoteTrack.
|
||||
mutable std::unique_ptr<Alg_seq> mSeq;
|
||||
mutable std::unique_ptr<char[]> mSerializationBuffer;
|
||||
mutable long mSerializationLength;
|
||||
|
||||
#ifdef EXPERIMENTAL_MIDI_OUT
|
||||
float mVelocity; // velocity offset
|
||||
|
@ -1437,11 +1437,13 @@ void PluginManager::FindFilesInPathList(const wxString & pattern,
|
||||
|
||||
wxArrayString paths;
|
||||
|
||||
// Add the "per-user" plug-ins directory
|
||||
// Add the "per-user" plug-ins directory Windows / Mac
|
||||
#if defined(__WXMAC__) || defined(__WXMSW__)
|
||||
{
|
||||
const wxFileName &ff = FileNames::PlugInDir();
|
||||
paths.Add(ff.GetFullPath());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Add the "Audacity" plug-ins directory
|
||||
wxFileName ff = PlatformCompatibility::GetExecutablePath();
|
||||
|
@ -2052,8 +2052,10 @@ void AudacityProject::UpdateLayout()
|
||||
if (!mTrackPanel)
|
||||
return;
|
||||
|
||||
mToolManager->LayoutToolBars();
|
||||
// Layout first to get our new width,
|
||||
// Then and only then we can arrange the toolbars.
|
||||
Layout();
|
||||
mToolManager->LayoutToolBars();
|
||||
|
||||
// Retrieve size of this projects window
|
||||
wxSize mainsz = GetSize();
|
||||
@ -2107,7 +2109,6 @@ void AudacityProject::RefreshAllTitles(bool bShowProjectNumbers )
|
||||
|
||||
void AudacityProject::OnIconize(wxIconizeEvent &event)
|
||||
{
|
||||
|
||||
int VisibleProjectCount = 0;
|
||||
|
||||
//JKC: On Iconizing we get called twice. Don't know
|
||||
@ -2311,7 +2312,9 @@ bool AudacityProject::TryToMakeActionAllowed
|
||||
if( (MissingFlags & ~( TimeSelectedFlag | WaveTracksSelectedFlag)) )
|
||||
return false;
|
||||
|
||||
OnSelectAll();
|
||||
// This was 'OnSelectAll'. Changing it to OnSelectSomething means if
|
||||
// selecting all tracks is enough, we just do that.
|
||||
OnSelectSomething();
|
||||
flags = GetUpdateFlags();
|
||||
bAllowed = ((flags & mask) == (flagsRqd & mask));
|
||||
return bAllowed;
|
||||
@ -2319,7 +2322,19 @@ bool AudacityProject::TryToMakeActionAllowed
|
||||
|
||||
void AudacityProject::OnMenu(wxCommandEvent & event)
|
||||
{
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// Bug 1642: We can arrive here with bogus menu IDs, which we
|
||||
// proceed to process. So if bogus, don't.
|
||||
// The bogus menu IDs are probably generated by controls on the TrackPanel,
|
||||
// such as the Project Rate.
|
||||
// 17000 is the magic number at which we start our menu.
|
||||
// This code would probably NOT be OK on Mac, since we assign
|
||||
// some specific ID numbers.
|
||||
if( event.GetId() < 17000){
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bool handled = mCommandManager.HandleMenuID(event.GetId(),
|
||||
GetUpdateFlags(),
|
||||
NoFlagsSpecifed);
|
||||
@ -4607,19 +4622,6 @@ void AudacityProject::Clear()
|
||||
RedrawProject();
|
||||
}
|
||||
|
||||
void AudacityProject::SelectNone()
|
||||
{
|
||||
TrackListIterator iter(GetTracks());
|
||||
Track *t = iter.First();
|
||||
while (t) {
|
||||
t->SetSelected(false);
|
||||
t = iter.Next();
|
||||
}
|
||||
mTrackPanel->Refresh(false);
|
||||
if (mMixerBoard)
|
||||
mMixerBoard->Refresh(false);
|
||||
}
|
||||
|
||||
// Utility function called by other zoom methods
|
||||
void AudacityProject::Zoom(double level)
|
||||
{
|
||||
|
@ -100,6 +100,7 @@ class UndoManager;
|
||||
enum class UndoPush : unsigned char;
|
||||
|
||||
class Track;
|
||||
class WaveClip;
|
||||
|
||||
AudacityProject *CreateNewAudacityProject();
|
||||
AUDACITY_DLL_API AudacityProject *GetActiveProject();
|
||||
|
@ -120,7 +120,7 @@ ScreenFramePtr mFrame;
|
||||
void OpenScreenshotTools()
|
||||
{
|
||||
if (!mFrame) {
|
||||
mFrame = ScreenFramePtr{ safenew ScreenFrame(NULL, -1) };
|
||||
mFrame = ScreenFramePtr{ safenew ScreenFrame(wxGetApp().GetTopWindow(), -1) };
|
||||
}
|
||||
mFrame->Show();
|
||||
mFrame->Raise();
|
||||
@ -298,6 +298,7 @@ ScreenFrame::ScreenFrame(wxWindow * parent, wxWindowID id)
|
||||
// The monitoring will switch off temporarily
|
||||
// because we've switched monitor mid play.
|
||||
mContext.GetProject()->GetToolManager()->Reset();
|
||||
Center();
|
||||
}
|
||||
|
||||
ScreenFrame::~ScreenFrame()
|
||||
|
@ -103,14 +103,20 @@ for registering for changes.
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/treectrl.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/bmpbuttn.h>
|
||||
#include "Internat.h"
|
||||
#include "Experimental.h"
|
||||
#include "Shuttle.h"
|
||||
#include "WrappedType.h"
|
||||
#include "widgets/wxPanelWrapper.h"
|
||||
|
||||
#include "../images/Help.xpm"
|
||||
|
||||
ShuttleGuiBase::ShuttleGuiBase(wxWindow * pParent, teShuttleMode ShuttleMode )
|
||||
{
|
||||
// Suppress warnings about the header file
|
||||
wxUnusedVar(Help_xpm);
|
||||
|
||||
wxASSERT( (pParent != NULL ) || ( ShuttleMode != eIsCreating));
|
||||
|
||||
mpParent = pParent;
|
||||
@ -2168,7 +2174,11 @@ std::unique_ptr<wxSizer> CreateStdButtonSizer(wxWindow *parent, long buttons, wx
|
||||
|
||||
if( buttons & eHelpButton )
|
||||
{
|
||||
bs->AddButton(safenew wxButton(parent, wxID_HELP));
|
||||
// Replace standard Help button with smaller icon button.
|
||||
// bs->AddButton(safenew wxButton(parent, wxID_HELP));
|
||||
b = new wxBitmapButton(parent, wxID_HELP, Help_xpm);
|
||||
b->SetToolTip( _("Help") );
|
||||
bs->AddButton( b );
|
||||
}
|
||||
|
||||
if (buttons & ePreviewButton)
|
||||
|
@ -490,6 +490,7 @@ void ThemeBase::RegisterImage( int &iIndex, const wxImage &Image, const wxString
|
||||
|
||||
mBitmapNames.Add( Name );
|
||||
mBitmapFlags.Add( mFlow.mFlags );
|
||||
mFlow.mFlags &= ~resFlagSkip;
|
||||
iIndex = mBitmaps.GetCount()-1;
|
||||
}
|
||||
|
||||
@ -541,7 +542,7 @@ void FlowPacker::GetNextPosition( int xSize, int ySize )
|
||||
xSize += 2*mBorderWidth;
|
||||
ySize += 2*mBorderWidth;
|
||||
// if the height has increased, then we are on a NEW group.
|
||||
if(( ySize > myHeight )||(mFlags != mOldFlags ))
|
||||
if(( ySize > myHeight )||(((mFlags ^ mOldFlags )& ~resFlagSkip)!=0))
|
||||
{
|
||||
SetNewGroup( ((mFlags & resFlagPaired)!=0) ? 2 : 1 );
|
||||
myHeight = ySize;
|
||||
@ -690,9 +691,12 @@ void ThemeBase::CreateImageCache( bool bBinarySave )
|
||||
{
|
||||
mFlow.GetNextPosition( SrcImage.GetWidth(), SrcImage.GetHeight());
|
||||
ImageCache.SetRGB( mFlow.Rect(), 0xf2, 0xb0, 0x27 );
|
||||
if( (mFlow.mFlags & resFlagSkip) == 0 )
|
||||
PasteSubImage( &ImageCache, &SrcImage,
|
||||
mFlow.mxPos + mFlow.mBorderWidth,
|
||||
mFlow.myPos + mFlow.mBorderWidth);
|
||||
else
|
||||
ImageCache.SetRGB( mFlow.RectInner(), 1,1,1);
|
||||
#ifdef IMAGE_MAP
|
||||
// No href in html. Uses title not alt.
|
||||
wxRect R( mFlow.Rect() );
|
||||
@ -753,12 +757,14 @@ void ThemeBase::CreateImageCache( bool bBinarySave )
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
// Deliberate policy to use the fast/cheap blocky pixel-multiplication
|
||||
// algorithm, as this introduces no artifacts on repeated scale up/down.
|
||||
ImageCache.Rescale(
|
||||
ImageCache.GetWidth() * 4,
|
||||
ImageCache.GetHeight() *4,
|
||||
ImageCache.GetWidth()*4,
|
||||
ImageCache.GetHeight()*4,
|
||||
wxIMAGE_QUALITY_NEAREST );
|
||||
#endif
|
||||
if( !ImageCache.SaveFile( FileName, wxBITMAP_TYPE_PNG ))
|
||||
{
|
||||
wxMessageBox(
|
||||
|
@ -41,7 +41,8 @@ enum teResourceFlags
|
||||
resFlagPaired =0x01,
|
||||
resFlagCursor =0x02,
|
||||
resFlagNewLine = 0x04,
|
||||
resFlagInternal = 0x08 // For image manipulation. Don't save or load.
|
||||
resFlagInternal = 0x08, // For image manipulation. Don't save or load.
|
||||
resFlagSkip = 0x10
|
||||
};
|
||||
|
||||
enum teThemeType
|
||||
|
@ -250,7 +250,7 @@ class AUDACITY_DLL_API Track /* not final */ : public XMLTagHandler
|
||||
bool IsSyncLockSelected() const;
|
||||
};
|
||||
|
||||
class AudioTrack /* not final */ : public Track
|
||||
class AUDACITY_DLL_API AudioTrack /* not final */ : public Track
|
||||
{
|
||||
public:
|
||||
AudioTrack(const std::shared_ptr<DirManager> &projDirManager)
|
||||
@ -265,7 +265,7 @@ public:
|
||||
{ return false; }
|
||||
};
|
||||
|
||||
class PlayableTrack /* not final */ : public AudioTrack
|
||||
class AUDACITY_DLL_API PlayableTrack /* not final */ : public AudioTrack
|
||||
{
|
||||
public:
|
||||
PlayableTrack(const std::shared_ptr<DirManager> &projDirManager)
|
||||
|
@ -273,7 +273,7 @@ TrackArtist::TrackArtist()
|
||||
|
||||
mdBrange = ENV_DB_RANGE;
|
||||
mShowClipping = false;
|
||||
mSampleDisplay = 0;
|
||||
mSampleDisplay = 1;// Stem plots by default.
|
||||
UpdatePrefs();
|
||||
|
||||
SetColours();
|
||||
@ -2730,7 +2730,7 @@ void TrackArtist::DrawNoteBackground(const NoteTrack *track, wxDC &dc,
|
||||
int left = TIME_TO_X(track->GetOffset());
|
||||
if (left < sel.x) left = sel.x; // clip on left
|
||||
|
||||
int right = TIME_TO_X(track->GetOffset() + track->mSeq->get_real_dur());
|
||||
int right = TIME_TO_X(track->GetOffset() + track->GetSeq().get_real_dur());
|
||||
if (right > sel.x + sel.width) right = sel.x + sel.width; // clip on right
|
||||
|
||||
// need overlap between MIDI data and the background region
|
||||
@ -2772,7 +2772,7 @@ void TrackArtist::DrawNoteBackground(const NoteTrack *track, wxDC &dc,
|
||||
}
|
||||
|
||||
// draw bar lines
|
||||
Alg_seq_ptr seq = track->mSeq.get();
|
||||
Alg_seq_ptr seq = &track->GetSeq();
|
||||
// We assume that sliding a NoteTrack around slides the barlines
|
||||
// along with the notes. This means that when we write out a track
|
||||
// as Allegro or MIDI without the offset, we'll need to insert an
|
||||
@ -2824,19 +2824,7 @@ void TrackArtist::DrawNoteTrack(const NoteTrack *track,
|
||||
const double h = X_TO_TIME(rect.x);
|
||||
const double h1 = X_TO_TIME(rect.x + rect.width);
|
||||
|
||||
Alg_seq_ptr seq = track->mSeq.get();
|
||||
if (!seq) {
|
||||
wxASSERT(track->mSerializationBuffer);
|
||||
// JKC: Previously this indirected via seq->, a NULL pointer.
|
||||
// This was actually OK, since unserialize is a static function.
|
||||
// Alg_seq:: is clearer.
|
||||
std::unique_ptr<Alg_track> alg_track{ Alg_seq::unserialize(track->mSerializationBuffer.get(),
|
||||
track->mSerializationLength) };
|
||||
wxASSERT(alg_track->get_type() == 's');
|
||||
const_cast<NoteTrack*>(track)->mSeq.reset(seq = static_cast<Alg_seq*>(alg_track.release()));
|
||||
track->mSerializationBuffer.reset();
|
||||
}
|
||||
wxASSERT(seq);
|
||||
Alg_seq_ptr seq = &track->GetSeq();
|
||||
|
||||
if (!track->GetSelected())
|
||||
sel0 = sel1 = 0.0;
|
||||
@ -3214,7 +3202,7 @@ void TrackArtist::UpdatePrefs()
|
||||
{
|
||||
mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange);
|
||||
mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping);
|
||||
gPrefs->Read(wxT("/GUI/SampleView"), &mSampleDisplay, 0);
|
||||
gPrefs->Read(wxT("/GUI/SampleView"), &mSampleDisplay, 1);
|
||||
SetColours();
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
101
src/TrackPanel.h
101
src/TrackPanel.h
@ -155,6 +155,25 @@ private:
|
||||
const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click.
|
||||
|
||||
|
||||
struct ClipMoveState {
|
||||
WaveClip *capturedClip {};
|
||||
bool capturedClipIsSelection {};
|
||||
TrackArray trackExclusions {};
|
||||
double hSlideAmount {};
|
||||
TrackClipArray capturedClipArray {};
|
||||
wxInt64 snapLeft { -1 }, snapRight { -1 };
|
||||
|
||||
void clear()
|
||||
{
|
||||
capturedClip = nullptr;
|
||||
capturedClipIsSelection = false;
|
||||
trackExclusions.clear();
|
||||
hSlideAmount = 0;
|
||||
capturedClipArray.clear();
|
||||
snapLeft = snapRight = -1;
|
||||
}
|
||||
};
|
||||
|
||||
class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
||||
public:
|
||||
|
||||
@ -256,7 +275,9 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
||||
// (ignoring any fisheye)
|
||||
virtual double GetScreenEndTime() const;
|
||||
|
||||
virtual void OnClipMove(bool right);
|
||||
static double OnClipMove
|
||||
(ViewInfo &viewInfo, Track *track,
|
||||
TrackList &trackList, bool syncLocked, bool right);
|
||||
|
||||
protected:
|
||||
virtual MixerBoard* GetMixerBoard();
|
||||
@ -299,20 +320,33 @@ class AUDACITY_DLL_API TrackPanel final : public OverlayPanel {
|
||||
// part shrinks, keeping the leftmost and rightmost boundaries
|
||||
// fixed.
|
||||
enum StretchEnum {
|
||||
stretchNone = 0, // false value!
|
||||
stretchLeft,
|
||||
stretchCenter,
|
||||
stretchRight
|
||||
};
|
||||
StretchEnum mStretchMode; // remembers what to drag
|
||||
bool mStretching; // true between mouse down and mouse up
|
||||
bool mStretched; // true after drag has pushed state
|
||||
double mStretchStart; // time of initial mouse position, quantized
|
||||
// to the nearest beat
|
||||
double mStretchSel0; // initial sel0 (left) quantized to nearest beat
|
||||
double mStretchSel1; // initial sel1 (left) quantized to nearest beat
|
||||
double mStretchLeftBeats; // how many beats from left to cursor
|
||||
double mStretchRightBeats; // how many beats from cursor to right
|
||||
virtual bool HitTestStretch(Track *track, const wxRect &rect, const wxMouseEvent & event);
|
||||
struct StretchState {
|
||||
StretchEnum mMode { stretchCenter }; // remembers what to drag
|
||||
|
||||
using QuantizedTimeAndBeat = std::pair< double, double >;
|
||||
|
||||
bool mStretching {}; // true between mouse down and mouse up
|
||||
double mOrigT0 {};
|
||||
double mOrigT1 {};
|
||||
QuantizedTimeAndBeat mBeatCenter { 0, 0 };
|
||||
QuantizedTimeAndBeat mBeat0 { 0, 0 };
|
||||
QuantizedTimeAndBeat mBeat1 { 0, 0 };
|
||||
double mLeftBeats {}; // how many beats from left to cursor
|
||||
double mRightBeats {}; // how many beats from cursor to right
|
||||
} mStretchState;
|
||||
|
||||
virtual StretchEnum HitTestStretch
|
||||
( const Track *track, const wxRect &rect, const wxMouseEvent & event,
|
||||
StretchState *pState = nullptr );
|
||||
wxCursor *ChooseStretchCursor( StretchEnum mode );
|
||||
static StretchEnum ChooseStretchMode
|
||||
( const wxMouseEvent &event, const wxRect &rect, const ViewInfo &viewInfo,
|
||||
const NoteTrack *nt, StretchState *pState = nullptr );
|
||||
virtual void Stretch(int mouseXCoordinate, int trackLeftEdge, Track *pTrack);
|
||||
#endif
|
||||
|
||||
@ -383,10 +417,16 @@ protected:
|
||||
virtual void HandleSlide(wxMouseEvent & event);
|
||||
virtual void StartSlide(wxMouseEvent &event);
|
||||
virtual void DoSlide(wxMouseEvent &event);
|
||||
virtual void DoSlideHorizontal();
|
||||
virtual void CreateListOfCapturedClips(double clickTime);
|
||||
virtual void AddClipsToCaptured(Track *t, bool withinSelection);
|
||||
virtual void AddClipsToCaptured(Track *t, double t0, double t1);
|
||||
static void DoSlideHorizontal
|
||||
( ClipMoveState &state, TrackList &trackList, Track &capturedTrack );
|
||||
static void CreateListOfCapturedClips
|
||||
( ClipMoveState &state, const ViewInfo &viewInfo, Track &capturedTrack,
|
||||
TrackList &trackList, bool syncLocked, double clickTime );
|
||||
static void AddClipsToCaptured
|
||||
( ClipMoveState &state, const ViewInfo &viewInfo,
|
||||
Track *t, bool withinSelection );
|
||||
static void AddClipsToCaptured
|
||||
( ClipMoveState &state, Track *t, double t0, double t1 );
|
||||
|
||||
// AS: Handle zooming into tracks
|
||||
virtual void HandleZoom(wxMouseEvent & event);
|
||||
@ -658,10 +698,7 @@ protected:
|
||||
|
||||
Track *mCapturedTrack;
|
||||
Envelope *mCapturedEnvelope;
|
||||
WaveClip *mCapturedClip;
|
||||
TrackClipArray mCapturedClipArray;
|
||||
TrackArray mTrackExclusions;
|
||||
bool mCapturedClipIsSelection;
|
||||
ClipMoveState mClipMoveState;
|
||||
WaveTrackLocation mCapturedTrackLocation;
|
||||
wxRect mCapturedTrackLocationRect;
|
||||
wxRect mCapturedRect;
|
||||
@ -678,10 +715,6 @@ protected:
|
||||
wxBaseArrayDouble mSlideSnapToPoints;
|
||||
wxArrayInt mSlideSnapLinePixels;
|
||||
|
||||
// The amount that clips are sliding horizontally; this allows
|
||||
// us to undo the slide and then slide it by another amount
|
||||
double mHSlideAmount;
|
||||
|
||||
bool mDidSlideVertically;
|
||||
|
||||
bool mRedrawAfterStop;
|
||||
@ -702,10 +735,28 @@ protected:
|
||||
// are the horizontal index of pixels to display user feedback
|
||||
// guidelines so the user knows when such snapping is taking place.
|
||||
std::unique_ptr<SnapManager> mSnapManager;
|
||||
wxInt64 mSnapLeft;
|
||||
wxInt64 mSnapRight;
|
||||
wxInt64 mSnapLeft { -1 };
|
||||
wxInt64 mSnapRight { -1 };
|
||||
bool mSnapPreferRightEdge;
|
||||
|
||||
public:
|
||||
wxInt64 GetSnapLeft () const
|
||||
{
|
||||
if ( mMouseCapture == IsSliding )
|
||||
return mClipMoveState.snapLeft ;
|
||||
else
|
||||
return mSnapLeft ;
|
||||
}
|
||||
wxInt64 GetSnapRight() const
|
||||
{
|
||||
if ( mMouseCapture == IsSliding )
|
||||
return mClipMoveState.snapRight;
|
||||
else
|
||||
return mSnapRight;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
NumericConverter mConverter;
|
||||
|
||||
WaveTrack * mDrawingTrack; // Keeps track of which track you are drawing on between events cf. HandleDraw()
|
||||
|
@ -61,7 +61,6 @@ UndoManager::UndoManager()
|
||||
{
|
||||
current = -1;
|
||||
saved = -1;
|
||||
consolidationCount = 0;
|
||||
ResetODChangesFlag();
|
||||
}
|
||||
|
||||
@ -257,10 +256,9 @@ void UndoManager::PushState(const TrackList * l,
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
// If consolidate is set to true, group up to 3 identical operations.
|
||||
if (((flags & UndoPush::CONSOLIDATE) != UndoPush::MINIMAL) && lastAction == longDescription &&
|
||||
consolidationCount < 2) {
|
||||
consolidationCount++;
|
||||
if ( ((flags & UndoPush::CONSOLIDATE) != UndoPush::MINIMAL) &&
|
||||
lastAction == longDescription &&
|
||||
mayConsolidate ) {
|
||||
ModifyState(l, selectedRegion, tags);
|
||||
// MB: If the "saved" state was modified by ModifyState, reset
|
||||
// it so that UnsavedChanges returns true.
|
||||
@ -270,7 +268,7 @@ void UndoManager::PushState(const TrackList * l,
|
||||
return;
|
||||
}
|
||||
|
||||
consolidationCount = 0;
|
||||
mayConsolidate = true;
|
||||
|
||||
i = current + 1;
|
||||
while (i < stack.size()) {
|
||||
@ -319,7 +317,7 @@ const UndoState &UndoManager::SetStateTo
|
||||
}
|
||||
|
||||
lastAction = wxT("");
|
||||
consolidationCount = 0;
|
||||
mayConsolidate = false;
|
||||
|
||||
return stack[current]->state;
|
||||
}
|
||||
@ -333,7 +331,7 @@ const UndoState &UndoManager::Undo(SelectedRegion *selectedRegion)
|
||||
*selectedRegion = stack[current]->state.selectedRegion;
|
||||
|
||||
lastAction = wxT("");
|
||||
consolidationCount = 0;
|
||||
mayConsolidate = false;
|
||||
|
||||
return stack[current]->state;
|
||||
}
|
||||
@ -360,7 +358,7 @@ const UndoState &UndoManager::Redo(SelectedRegion *selectedRegion)
|
||||
*/
|
||||
|
||||
lastAction = wxT("");
|
||||
consolidationCount = 0;
|
||||
mayConsolidate = false;
|
||||
|
||||
return stack[current]->state;
|
||||
}
|
||||
|
@ -30,8 +30,9 @@
|
||||
|
||||
UndoManager can also automatically consolidate actions into
|
||||
a single state change. If the "consolidate" argument to
|
||||
PushState is true, then up to 3 identical events in a row
|
||||
will result in one PushState and 2 ModifyStates.
|
||||
PushState is true, then new changes may accumulate into the most
|
||||
recent Undo state, if descriptions match and if no Undo or Redo or rollback
|
||||
operation intervened since that state was pushed.
|
||||
|
||||
Undo() temporarily moves down one state and returns the track
|
||||
hierarchy. If another PushState is called, the redo information
|
||||
@ -107,6 +108,8 @@ class AUDACITY_DLL_API UndoManager {
|
||||
unsigned int GetNumStates();
|
||||
unsigned int GetCurrentState();
|
||||
|
||||
void StopConsolidating() { mayConsolidate = false; }
|
||||
|
||||
void GetShortDescription(unsigned int n, wxString *desc);
|
||||
// Return value must first be calculated by CalculateSpaceUsage():
|
||||
wxLongLong_t GetLongDescription(unsigned int n, wxString *desc, wxString *size);
|
||||
@ -143,7 +146,7 @@ class AUDACITY_DLL_API UndoManager {
|
||||
UndoStack stack;
|
||||
|
||||
wxString lastAction;
|
||||
int consolidationCount;
|
||||
bool mayConsolidate { false };
|
||||
|
||||
SpaceArray space;
|
||||
unsigned long long mClipboardSpaceUsage {};
|
||||
|
@ -1948,3 +1948,17 @@ void WaveClip::Resample(int rate, ProgressDialog *progress)
|
||||
mRate = rate;
|
||||
}
|
||||
}
|
||||
|
||||
// Used by commands which interact with clips using the keyboard.
|
||||
// When two clips are immediately next to each other, the GetEndTime()
|
||||
// of the first clip and the GetStartTime() of the second clip may not
|
||||
// be exactly equal due to rounding errors.
|
||||
bool WaveClip::SharesBoundaryWithNextClip(const WaveClip* next) const
|
||||
{
|
||||
double endThis = GetRate() * GetOffset() + GetNumSamples().as_double();
|
||||
double startNext = next->GetRate() * next->GetOffset();
|
||||
|
||||
// given that a double has about 15 significant digits, using a criterion
|
||||
// of half a sample should be safe in all normal usage.
|
||||
return fabs(startNext - endThis) < 0.5;
|
||||
}
|
||||
|
@ -378,6 +378,9 @@ public:
|
||||
bool GetIsPlaceholder() const { return mIsPlaceholder; }
|
||||
void SetIsPlaceholder(bool val) { mIsPlaceholder = val; }
|
||||
|
||||
// used by commands which interact with clips using the keyboard
|
||||
bool SharesBoundaryWithNextClip(const WaveClip* next) const;
|
||||
|
||||
public:
|
||||
// Cache of values to colour pixels of Spectrogram - used by TrackArtist
|
||||
mutable std::unique_ptr<SpecPxCache> mSpecPxCache;
|
||||
|
@ -2212,15 +2212,27 @@ WaveClip* WaveTrack::GetClipAtSample(sampleCount sample)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// When the time is both the end of a clip and the start of the next clip, the
|
||||
// latter clip is returned.
|
||||
WaveClip* WaveTrack::GetClipAtTime(double time)
|
||||
{
|
||||
// When the time is both the end of a clip and the start of the next clip, the
|
||||
// latter clip is returned.
|
||||
|
||||
const auto clips = SortedClipArray();
|
||||
auto result = std::find_if(clips.rbegin(), clips.rend(), [&] (WaveClip* const& clip) {
|
||||
auto p = std::find_if(clips.rbegin(), clips.rend(), [&] (WaveClip* const& clip) {
|
||||
return time >= clip->GetStartTime() && time <= clip->GetEndTime(); });
|
||||
|
||||
return result != clips.rend() ? *result : nullptr;
|
||||
// When two clips are immediately next to each other, the GetEndTime() of the first clip
|
||||
// and the GetStartTime() of the second clip may not be exactly equal due to rounding errors.
|
||||
// If "time" is the end time of the first of two such clips, and the end time is slightly
|
||||
// less than the start time of the second clip, then the first rather than the
|
||||
// second clip is found by the above code. So correct this.
|
||||
if (p != clips.rend() & p != clips.rbegin() &&
|
||||
time == (*p)->GetEndTime() &&
|
||||
(*p)->SharesBoundaryWithNextClip(*(p-1))) {
|
||||
p--;
|
||||
}
|
||||
|
||||
return p != clips.rend() ? *p : nullptr;
|
||||
}
|
||||
|
||||
Envelope* WaveTrack::GetEnvelopeAtX(int xcoord)
|
||||
|
@ -448,7 +448,7 @@ void CommandManager::PurgeData()
|
||||
mCommandIDHash.clear();
|
||||
|
||||
mCurrentMenuName = COMMAND;
|
||||
mCurrentID = 0;
|
||||
mCurrentID = 17000;
|
||||
}
|
||||
|
||||
|
||||
@ -1204,12 +1204,17 @@ bool CommandManager::FilterKeyEvent(AudacityProject *project, const wxKeyEvent &
|
||||
{
|
||||
wxWindow * pWnd = wxWindow::FindFocus();
|
||||
wxWindow * pTrackPanel = (wxWindow*)GetActiveProject()->GetTrackPanel();
|
||||
bool bIntercept = pWnd != pTrackPanel;
|
||||
// Intercept keys from windows that are NOT panels
|
||||
if( bIntercept ){
|
||||
bIntercept = pWnd && ( dynamic_cast<wxPanel*>(pWnd) == NULL );
|
||||
}
|
||||
//wxLogDebug("Focus: %p TrackPanel: %p", pWnd, pTrackPanel );
|
||||
// We allow the keystrokes below to be handled by wxWidgets controls IF we are
|
||||
// in some sub window rather than in the TrackPanel itself.
|
||||
// Otherwise they will go to our command handler and if it handles them
|
||||
// they will NOT be available to wxWidgets.
|
||||
if( pWnd != pTrackPanel ){
|
||||
if( bIntercept ){
|
||||
switch( evt.GetKeyCode() ){
|
||||
case WXK_LEFT:
|
||||
case WXK_RIGHT:
|
||||
|
@ -90,6 +90,11 @@ wxString EffectAmplify::GetDescription()
|
||||
return XO("Increases or decreases the volume of the audio you have selected");
|
||||
}
|
||||
|
||||
wxString EffectAmplify::ManualPage()
|
||||
{
|
||||
return wxT("Amplify");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectAmplify::GetType()
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -115,6 +115,11 @@ wxString EffectAutoDuck::GetDescription()
|
||||
return XO("Reduces (ducks) the volume of one or more tracks whenever the volume of a specified \"control\" track reaches a particular level");
|
||||
}
|
||||
|
||||
wxString EffectAutoDuck::ManualPage()
|
||||
{
|
||||
return wxT("Auto_Duck");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectAutoDuck::GetType()
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -92,6 +92,11 @@ wxString EffectBassTreble::GetDescription()
|
||||
return XO("Simple tone control effect");
|
||||
}
|
||||
|
||||
wxString EffectBassTreble::ManualPage()
|
||||
{
|
||||
return wxT("Bass_and_Treble");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectBassTreble::GetType()
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -126,6 +126,11 @@ wxString EffectChangePitch::GetDescription()
|
||||
return XO("Change the pitch of a track without changing its tempo");
|
||||
}
|
||||
|
||||
wxString EffectChangePitch::ManualPage()
|
||||
{
|
||||
return wxT("Change_Pitch");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectChangePitch::GetType()
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -115,6 +115,12 @@ wxString EffectChangeSpeed::GetDescription()
|
||||
return XO("Change the speed of a track, also changing its pitch");
|
||||
}
|
||||
|
||||
wxString EffectChangeSpeed::ManualPage()
|
||||
{
|
||||
return wxT("Change_Speed");
|
||||
}
|
||||
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectChangeSpeed::GetType()
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -102,6 +102,11 @@ wxString EffectChangeTempo::GetDescription()
|
||||
return XO("Change the tempo of a selection without changing its pitch");
|
||||
}
|
||||
|
||||
wxString EffectChangeTempo::ManualPage()
|
||||
{
|
||||
return wxT("Change_Tempo");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectChangeTempo::GetType()
|
||||
|
@ -42,6 +42,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -85,6 +85,11 @@ wxString EffectClickRemoval::GetDescription()
|
||||
return XO("Click Removal is designed to remove clicks on audio tracks");
|
||||
}
|
||||
|
||||
wxString EffectClickRemoval::ManualPage()
|
||||
{
|
||||
return wxT("Click_Removal");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectClickRemoval::GetType()
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -107,6 +107,11 @@ wxString EffectCompressor::GetDescription()
|
||||
return XO("Compresses the dynamic range of audio");
|
||||
}
|
||||
|
||||
wxString EffectCompressor::ManualPage()
|
||||
{
|
||||
return wxT("Compressor");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectCompressor::GetType()
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -177,6 +177,7 @@ ContrastDialog::ContrastDialog(wxWindow * parent, wxWindowID id,
|
||||
S.SetBorder(5);
|
||||
S.StartHorizontalLay(wxCENTER, false);
|
||||
{
|
||||
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
|
||||
S.AddTitle(_("Contrast Analyzer, for measuring RMS volume differences between two selections of audio."));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
@ -362,6 +363,67 @@ void ContrastDialog::OnGetBackground(wxCommandEvent & /*event*/)
|
||||
results();
|
||||
}
|
||||
|
||||
namespace {
|
||||
// PRL: I gathered formatting into these functions, and eliminated some
|
||||
// repetitions, and removed the redundant word "Average" as applied to RMS.
|
||||
// Should these variations in formats be collapsed further?
|
||||
|
||||
// Pass nullptr when value is not yet defined
|
||||
wxString FormatRMSMessage( float *pValue )
|
||||
{
|
||||
|
||||
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
|
||||
wxString format0{ _("RMS = %s.") };
|
||||
|
||||
/* i18n-hint: dB abbreviates decibels */
|
||||
wxString format1{ _("%s dB") };
|
||||
|
||||
wxString value;
|
||||
|
||||
if ( pValue )
|
||||
if( fabs( *pValue ) != std::numeric_limits<float>::infinity() ) {
|
||||
auto number = wxString::Format( _("%.2f"), *pValue );
|
||||
value = wxString::Format( format1, number );
|
||||
}
|
||||
else
|
||||
value = _("zero");
|
||||
else
|
||||
value = wxString::Format( format1, "" );
|
||||
|
||||
return wxString::Format( format0, value );
|
||||
}
|
||||
|
||||
wxString FormatDifference( float diffdB )
|
||||
{
|
||||
if( diffdB != diffdB ) // test for NaN, reliant on IEEE implementation
|
||||
return _("indeterminate");
|
||||
else {
|
||||
if( diffdB != std::numeric_limits<float>::infinity() )
|
||||
/* i18n-hint: dB abbreviates decibels */
|
||||
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
|
||||
return wxString::Format(_("%.2f dB RMS"), diffdB);
|
||||
else
|
||||
/* i18n-hint: dB abbreviates decibels */
|
||||
return wxString::Format(_("Infinite dB difference"));
|
||||
}
|
||||
}
|
||||
|
||||
wxString FormatDifferenceForExport( float diffdB )
|
||||
{
|
||||
if( diffdB != diffdB ) //test for NaN, reliant on IEEE implementation
|
||||
return _("Difference is indeterminate.");
|
||||
else
|
||||
if( fabs(diffdB) != std::numeric_limits<float>::infinity() )
|
||||
/* i18n-hint: dB abbreviates decibels */
|
||||
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
|
||||
return wxString::Format(_("Difference = %.2f RMS dB."), diffdB );
|
||||
else
|
||||
/* i18n-hint: dB abbreviates decibels */
|
||||
/* i18n-hint: RMS abbreviates root mean square, a certain averaging method */
|
||||
return _("Difference = infinite RMS dB.");
|
||||
}
|
||||
}
|
||||
|
||||
void ContrastDialog::results()
|
||||
{
|
||||
mPassFailText->SetName(wxT(""));
|
||||
@ -381,25 +443,17 @@ void ContrastDialog::results()
|
||||
mPassFailText->ChangeValue(_("Background higher than foreground"));
|
||||
}
|
||||
else if(diffdB > WCAG2_PASS) {
|
||||
/* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
|
||||
mPassFailText->ChangeValue(_("WCAG2 Pass"));
|
||||
}
|
||||
else {
|
||||
/* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
|
||||
mPassFailText->ChangeValue(_("WCAG2 Fail"));
|
||||
}
|
||||
|
||||
/* i18n-hint: i.e. difference in loudness at the moment. */
|
||||
mDiffText->SetName(_("Current difference"));
|
||||
if( diffdB != diffdB ) { // test for NaN, reliant on IEEE implementation
|
||||
mDiffText->ChangeValue(wxString::Format(_("indeterminate")));
|
||||
}
|
||||
else {
|
||||
if( diffdB != std::numeric_limits<float>::infinity() ) {
|
||||
mDiffText->ChangeValue(wxString::Format(_("%.2f dB Average RMS"), diffdB));
|
||||
}
|
||||
else {
|
||||
mDiffText->ChangeValue(wxString::Format(_("Infinite dB difference")));
|
||||
}
|
||||
}
|
||||
mDiffText->ChangeValue( FormatDifference( diffdB ) );
|
||||
}
|
||||
|
||||
if (mForegroundIsDefined) {
|
||||
@ -459,6 +513,7 @@ void ContrastDialog::OnExport(wxCommandEvent & WXUNUSED(event))
|
||||
}
|
||||
|
||||
f.AddLine(wxT("==================================="));
|
||||
/* i18n-hint: WCAG abbreviates Web Content Accessibility Guidelines */
|
||||
f.AddLine(_("WCAG 2.0 Success Criteria 1.4.7 Contrast Results"));
|
||||
f.AddLine(wxT(""));
|
||||
f.AddLine(wxString::Format(_("Filename = %s."), project->GetFileName().c_str() ));
|
||||
@ -474,13 +529,7 @@ void ContrastDialog::OnExport(wxCommandEvent & WXUNUSED(event))
|
||||
m = (int)((t - h*3600)/60);
|
||||
s = t - h*3600.0 - m*60.0;
|
||||
f.AddLine(wxString::Format(_("Time ended = %2d hour(s), %2d minute(s), %.2f seconds."), h, m, s ));
|
||||
if(mForegroundIsDefined)
|
||||
if( fabs(foregrounddB) != std::numeric_limits<float>::infinity() )
|
||||
f.AddLine(wxString::Format(_("Average RMS = %.2f dB."), foregrounddB ));
|
||||
else
|
||||
f.AddLine(wxString::Format(_("Average RMS = zero.") ));
|
||||
else
|
||||
f.AddLine(wxString::Format(_("Average RMS = dB.")));
|
||||
f.AddLine( FormatRMSMessage( mForegroundIsDefined ? &foregrounddB : nullptr ) );
|
||||
f.AddLine(wxT(""));
|
||||
f.AddLine(_("Background"));
|
||||
t = (float)mBackgroundStartT->GetValue();
|
||||
@ -493,23 +542,12 @@ void ContrastDialog::OnExport(wxCommandEvent & WXUNUSED(event))
|
||||
m = (int)((t - h*3600)/60);
|
||||
s = t - h*3600.0 - m*60.0;
|
||||
f.AddLine(wxString::Format(_("Time ended = %2d hour(s), %2d minute(s), %.2f seconds."), h, m, s ));
|
||||
if(mBackgroundIsDefined)
|
||||
if( fabs(backgrounddB) != std::numeric_limits<float>::infinity() )
|
||||
f.AddLine(wxString::Format(_("Average RMS = %.2f dB."), backgrounddB ));
|
||||
else
|
||||
f.AddLine(wxString::Format(_("Average RMS = zero.") ));
|
||||
else
|
||||
f.AddLine(wxString::Format(_("Average RMS = dB.")));
|
||||
f.AddLine( FormatRMSMessage( mBackgroundIsDefined ? &backgrounddB : nullptr ) );
|
||||
f.AddLine(wxT(""));
|
||||
f.AddLine(_("Results"));
|
||||
float diffdB = foregrounddB - backgrounddB;
|
||||
if( diffdB != diffdB ) //test for NaN, reliant on IEEE implementation
|
||||
f.AddLine(wxString::Format(_("Difference is indeterminate.") ));
|
||||
else
|
||||
if( fabs(diffdB) != std::numeric_limits<float>::infinity() )
|
||||
f.AddLine(wxString::Format(_("Difference = %.2f Average RMS dB."), diffdB ));
|
||||
else
|
||||
f.AddLine(wxString::Format(_("Difference = infinite Average RMS dB.")));
|
||||
|
||||
f.AddLine( FormatDifferenceForExport( diffdB ) );
|
||||
if( diffdB > 20. )
|
||||
f.AddLine(_("Success Criteria 1.4.7 of WCAG 2.0: Pass"));
|
||||
else
|
||||
|
@ -192,6 +192,11 @@ wxString EffectDistortion::GetDescription()
|
||||
return XO("Waveshaping distortion effect");
|
||||
}
|
||||
|
||||
wxString EffectDistortion::ManualPage()
|
||||
{
|
||||
return wxT("Distortion");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectDistortion::GetType()
|
||||
|
@ -68,6 +68,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -101,6 +101,11 @@ wxString EffectDtmf::GetDescription()
|
||||
return XO("Generates dual-tone multi-frequency (DTMF) tones like those produced by the keypad on telephones");
|
||||
}
|
||||
|
||||
wxString EffectDtmf::ManualPage()
|
||||
{
|
||||
return wxT("Generate_Menu#dtmf");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectDtmf::GetType()
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -60,6 +60,11 @@ wxString EffectEcho::GetDescription()
|
||||
return XO("Repeats the selected audio again and again");
|
||||
}
|
||||
|
||||
wxString EffectEcho::ManualPage()
|
||||
{
|
||||
return wxT("Echo");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectEcho::GetType()
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -53,6 +53,10 @@ greater use in future.
|
||||
#include "../ondemand/ODManager.h"
|
||||
#include "TimeWarper.h"
|
||||
#include "nyquist/Nyquist.h"
|
||||
#include "../widgets/HelpSystem.h"
|
||||
#include "../widgets/LinkingHtmlWindow.h"
|
||||
#include "../widgets/ErrorDialog.h"
|
||||
#include "../FileNames.h"
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
#include <Cocoa/Cocoa.h>
|
||||
@ -1098,6 +1102,16 @@ wxString Effect::GetPreset(wxWindow * parent, const wxString & parms)
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxString Effect::ManualPage()
|
||||
{
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
wxString Effect::HelpPage()
|
||||
{
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
bool Effect::IsBatchProcessing()
|
||||
{
|
||||
return mIsBatch;
|
||||
@ -2604,8 +2618,9 @@ void Effect::Preview(bool dryOnly)
|
||||
}
|
||||
}
|
||||
else {
|
||||
wxMessageBox(_("Error opening sound device. Try changing the audio host, playback device and the project sample rate."),
|
||||
_("Error"), wxOK | wxICON_EXCLAMATION, FocusDialog);
|
||||
ShowErrorDialog(FocusDialog, _("Error"),
|
||||
_("Error opening sound device.\nTry changing the audio host, playback device and the project sample rate."),
|
||||
wxT("http://manual.audacityteam.org/man/faq_errors.html#sound_device"), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2767,6 +2782,7 @@ BEGIN_EVENT_TABLE(EffectUIHost, wxDialogWrapper)
|
||||
EVT_CLOSE(EffectUIHost::OnClose)
|
||||
EVT_BUTTON(wxID_APPLY, EffectUIHost::OnApply)
|
||||
EVT_BUTTON(wxID_CANCEL, EffectUIHost::OnCancel)
|
||||
EVT_BUTTON(wxID_HELP, EffectUIHost::OnHelp)
|
||||
EVT_BUTTON(eDebugID, EffectUIHost::OnDebug)
|
||||
EVT_BUTTON(kMenuID, EffectUIHost::OnMenu)
|
||||
EVT_CHECKBOX(kEnableID, EffectUIHost::OnEnable)
|
||||
@ -3039,9 +3055,24 @@ bool EffectUIHost::Initialize()
|
||||
bar->SetSizerAndFit(bs.release());
|
||||
}
|
||||
|
||||
long buttons = eApplyButton + eCloseButton;
|
||||
if (mEffect->mUIDebug)
|
||||
{
|
||||
long buttons;
|
||||
if ( mEffect->ManualPage().IsEmpty() && mEffect->HelpPage().IsEmpty()) {
|
||||
buttons = eApplyButton + eCloseButton;
|
||||
this->SetAcceleratorTable(wxNullAcceleratorTable);
|
||||
}
|
||||
else {
|
||||
buttons = eApplyButton + eCloseButton + eHelpButton;
|
||||
wxAcceleratorEntry entries[1];
|
||||
#if defined(__WXMAC__)
|
||||
// Is there a standard shortcut on Mac?
|
||||
#else
|
||||
entries[0].Set(wxACCEL_NORMAL, (int) WXK_F1, wxID_HELP);
|
||||
#endif
|
||||
wxAcceleratorTable accel(1, entries);
|
||||
this->SetAcceleratorTable(accel);
|
||||
}
|
||||
|
||||
if (mEffect->mUIDebug) {
|
||||
buttons += eDebugButton;
|
||||
}
|
||||
|
||||
@ -3203,6 +3234,19 @@ void EffectUIHost::OnCancel(wxCommandEvent & evt)
|
||||
return;
|
||||
}
|
||||
|
||||
void EffectUIHost::OnHelp(wxCommandEvent & WXUNUSED(event))
|
||||
{
|
||||
if (mEffect->GetFamily().IsSameAs(NYQUISTEFFECTS_FAMILY) && (mEffect->ManualPage().IsEmpty())) {
|
||||
// Old ShowHelpDialog required when there is no on-line manual.
|
||||
// Always use default web browser to allow full-featured HTML pages.
|
||||
HelpSystem::ShowHelpDialog(FindWindow(wxID_HELP), mEffect->HelpPage(), wxEmptyString, true, true);
|
||||
}
|
||||
else {
|
||||
// otherwise use the new ShowHelpDialog
|
||||
HelpSystem::ShowHelpDialog(FindWindow(wxID_HELP), mEffect->ManualPage(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectUIHost::OnDebug(wxCommandEvent & evt)
|
||||
{
|
||||
OnApply(evt);
|
||||
|
@ -226,6 +226,11 @@ class AUDACITY_DLL_API Effect /* not final */ : public wxEvtHandler,
|
||||
virtual bool HasFactoryDefaults();
|
||||
virtual wxString GetPreset(wxWindow * parent, const wxString & parms);
|
||||
|
||||
// Name of page in the Audacity alpha manual
|
||||
virtual wxString ManualPage();
|
||||
// Fully qualified local help file name
|
||||
virtual wxString HelpPage();
|
||||
|
||||
virtual bool IsBatchProcessing();
|
||||
virtual void SetBatchProcessing(bool start);
|
||||
|
||||
@ -593,6 +598,7 @@ private:
|
||||
void OnApply(wxCommandEvent & evt);
|
||||
void DoCancel();
|
||||
void OnCancel(wxCommandEvent & evt);
|
||||
void OnHelp(wxCommandEvent & evt);
|
||||
void OnDebug(wxCommandEvent & evt);
|
||||
void OnMenu(wxCommandEvent & evt);
|
||||
void OnEnable(wxCommandEvent & evt);
|
||||
|
@ -298,6 +298,11 @@ wxString EffectEqualization::GetDescription()
|
||||
return XO("Adjusts the volume levels of particular frequencies");
|
||||
}
|
||||
|
||||
wxString EffectEqualization::ManualPage()
|
||||
{
|
||||
return wxT("Equalization");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectEqualization::GetType()
|
||||
|
@ -95,6 +95,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -61,6 +61,11 @@ wxString EffectFindClipping::GetDescription()
|
||||
return XO("Creates labels where clipping is detected");
|
||||
}
|
||||
|
||||
wxString EffectFindClipping::ManualPage()
|
||||
{
|
||||
return wxT("Find_Clipping");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectFindClipping::GetType()
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -78,6 +78,11 @@ wxString EffectNoise::GetDescription()
|
||||
return XO("Generates one of three different types of noise");
|
||||
}
|
||||
|
||||
wxString EffectNoise::ManualPage()
|
||||
{
|
||||
return wxT("Generate_Menu#noise");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectNoise::GetType()
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -68,6 +68,11 @@ wxString EffectNormalize::GetDescription()
|
||||
return XO("Sets the peak amplitude of one or more tracks");
|
||||
}
|
||||
|
||||
wxString EffectNormalize::ManualPage()
|
||||
{
|
||||
return wxT("Normalize");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectNormalize::GetType()
|
||||
|
@ -34,6 +34,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -107,6 +107,11 @@ wxString EffectPaulstretch::GetDescription()
|
||||
return XO("Use Paulstretch only for an extreme time-stretch or \"stasis\" effect");
|
||||
}
|
||||
|
||||
wxString EffectPaulstretch::ManualPage()
|
||||
{
|
||||
return wxT("Paulstretch");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectPaulstretch::GetType()
|
||||
|
@ -28,6 +28,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -112,6 +112,11 @@ wxString EffectPhaser::GetDescription()
|
||||
return XO("Combines phase-shifted signals with the original signal");
|
||||
}
|
||||
|
||||
wxString EffectPhaser::ManualPage()
|
||||
{
|
||||
return wxT("Phaser");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectPhaser::GetType()
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -67,6 +67,11 @@ wxString EffectRepeat::GetDescription()
|
||||
return XO("Repeats the selection the specified number of times");
|
||||
}
|
||||
|
||||
wxString EffectRepeat::ManualPage()
|
||||
{
|
||||
return wxT("Repeat");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectRepeat::GetType()
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
|
||||
wxString GetSymbol() override;
|
||||
wxString GetDescription() override;
|
||||
wxString ManualPage() override;
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
|
@ -153,6 +153,11 @@ wxString EffectReverb::GetDescription()
|
||||
return XO("Adds ambience or a \"hall effect\"");
|
||||
}
|
||||
|
||||
wxString EffectReverb::ManualPage()
|
||||
{
|
||||
return wxT("Reverb");
|
||||
}
|
||||
|
||||
// EffectIdentInterface implementation
|
||||
|
||||
EffectType EffectReverb::GetType()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user