diff --git a/scripts/piped-work/docimages_all.py b/scripts/piped-work/docimages_all.py
index 1178c2b1b..d41338d3e 100644
--- a/scripts/piped-work/docimages_all.py
+++ b/scripts/piped-work/docimages_all.py
@@ -5,8 +5,42 @@
# Make sure Audacity is running first and that mod-script-pipe is enabled
# before running this script.
+import time
+
+
+# records time, name of file and returns contents.
+def inner( name ) :
+ global old_name
+ global start_time
+ global results
+ result = old_name + ' took ' + str( time.time() - start_time )
+ results.append( result )
+ print( result )
+ start_time = time.time()
+ if not name :
+ return ""
+ old_name = name
+ return open("docimages_" + name + ".py" ).read()
+
+#initialise timing
+start_time = time.time()
+old_name = 'startup'
+results = []
+
+#do the different files...
+exec( inner( 'tracks' ) )
+exec( inner( 'labels' ) )
+exec( inner( 'spectro' ) )
+exec( inner( 'after' ) )
+exec( inner( 'envelopes' ) )
+exec( inner( 'cut_n_paste' ) )
+exec( inner( 'clip_boundaries' ) )
+exec( inner( 'oddments' ) )
+
+#report on timing.
+inner( "" )
+
+print( "\n\nSummary:" )
+print( "\n".join( results ) )
+
-exec( open("docimages_tracks.py" ).read() )
-exec( open("docimages_labels.py" ).read() )
-exec( open("docimages_spectro.py" ).read() )
-exec( open("docimages_after.py" ).read() )
diff --git a/scripts/piped-work/docimages_arrange.py b/scripts/piped-work/docimages_arrange.py
new file mode 100644
index 000000000..dc1f8f539
--- /dev/null
+++ b/scripts/piped-work/docimages_arrange.py
@@ -0,0 +1,100 @@
+# docimages_arrange.py
+# Sends commands to get images for the manual.
+# These ones arrange tracks and do alignment.
+
+# Make sure Audacity is running first and that mod-script-pipe is enabled
+# before running this script.
+
+#load and run the common core.
+exec( open("docimages_core.py" ).read() )
+
+import time
+
+
+def loadFourColours() :
+ loadMonoTracks( 4 )
+ do( 'SetTrack: Track=0 Name="Claire" Height=60 Color=Color0')
+ do( 'SetTrack: Track=1 Name="Ann" Height=60 Color=Color1')
+ do( 'SetTrack: Track=2 Name="Bob" Height=60 Color=Color2')
+ do( 'SetTrack: Track=3 Name="David" Height=60 Color=Color3')
+ do( 'SetClip: Track=0 At=1 Start=25')
+ do( 'SetClip: Track=1 At=1 Start=15')
+ do( 'SetClip: Track=2 At=1 Start=20')
+ do( 'SetClip: Track=3 At=1 Start=10')
+ do( 'Select: First=0 Last=100 Mode=Remove' )
+
+def loadFourColoursSelected() :
+ loadFourColours()
+ do( 'ZoomOut' )
+ do( 'Select: Start=90 End=135 First=0 Last=100' )
+
+def blockMoves( name ):
+ # These are the align commands that move tracks 'en block'.
+ loadFourColoursSelected()
+ capture( name + '001.png', 'All_Tracks_Plus' )
+ do( 'Align_StarttoZero' )
+ capture( name + '002.png', 'All_Tracks_Plus' )
+ loadFourColoursSelected()
+ do( 'Align_StarttoCursorSelectionStart' )
+ capture( name + '003.png', 'All_Tracks_Plus' )
+ loadFourColoursSelected()
+ do( 'Align_StarttoSelectionEnd' )
+ capture( name + '004.png', 'All_Tracks_Plus' )
+ loadFourColoursSelected()
+ do( 'Align_EndtoCursorSelectionStart' )
+ capture( name + '005.png', 'All_Tracks_Plus' )
+ loadFourColoursSelected()
+ do( 'Align_EndtoSelectionEnd' )
+ capture( name + '006.png', 'All_Tracks_Plus' )
+
+def track_moves( type ) :
+ loadFourColours()
+ # Sorting tracks into order
+ do( 'SetTrack: Track=1 Focused=1')
+ capture( 'TrackOrder002.png', 'All_Tracks' )
+
+def arrange_imagesA() :
+ loadFourColours()
+ # Moving tracks up and down.
+ capture( 'TrackOrder001.png', 'All_Tracks' )
+ do( 'SetTrack: Track=1 Focused=1')
+ # ToTop=0 to show the focus...
+ capture( 'TrackOrder002.png', 'All_Tracks ToTop=0' )
+ do( 'TrackMoveUp' )
+ capture( 'TrackUp.png', 'All_Tracks ToTop=0' )
+ do( 'TrackMoveDown' ) # undo
+ do( 'TrackMoveDown' )
+ capture( 'TrackDown.png', 'All_Tracks ToTop=0' )
+ do( 'TrackMoveTop' )
+ capture( 'TrackTop.png', 'All_Tracks ToTop=0' )
+ do( 'TrackMoveBottom' )
+ capture( 'TrackBottom.png', 'All_Tracks ToTop=0' )
+ # Sorting tracks into order
+ do( 'SortByName')
+ capture( 'TrackOrder003.png', 'All_Tracks' )
+ do( 'SortByTime')
+ capture( 'TrackOrder004.png', 'All_Tracks' )
+ # Aligning tracks
+ do( 'Select: First=0 Last=100 From=0 To=0')
+ do( 'Align_AlignTogether' )
+ capture( 'TrackAlign001.png', 'All_Tracks' )
+ do( 'Align_AlignEndtoEnd' )
+ do( 'FitInWindow' )
+ capture( 'TrackAlign002.png', 'All_Tracks' )
+
+
+def arrange_imagesB() :
+ blockMoves( 'BlockMoves' )
+ do( 'MoveSelectionWithTracks')
+ blockMoves( 'BlockAndCursorMoves' )
+ do( 'MoveSelectionWithTracks')
+
+
+
+#quickTest()
+
+arrange_imagesA()
+#arrange_imagesB()
+
+
+
diff --git a/scripts/piped-work/docimages_clip_boundaries.py b/scripts/piped-work/docimages_clip_boundaries.py
new file mode 100644
index 000000000..2f855199f
--- /dev/null
+++ b/scripts/piped-work/docimages_clip_boundaries.py
@@ -0,0 +1,69 @@
+# docimages_clip_boundariess.py
+# Sends commands to get images for the manual.
+# Images for clip boundary manipulation, per that chapter in the manual
+# Make sure Audacity is running first and that mod-script-pipe is enabled
+# before running this script.
+
+#load and run the common core.
+exec( open("docimages_core.py" ).read() )
+
+def gappyTrack2() :
+ loadMonoTracks(1)
+ # A mono track
+ do( 'Select: Start=0 End=10')
+ do( 'SplitCut' )
+ do( 'Select: Start=30 End=45')
+ do( 'SplitCut' )
+ do( 'Select: Start=90 End=100')
+ do( 'SplitCut' )
+ do( 'Select: Start=120 End=135')
+ do( 'SplitCut' )
+ do( 'Select: Start=0 End=0')
+
+def clipb_imagesA():
+ gappyTrack2()
+ # clip bound left
+ capture( 'ClipBounds001.png', 'All_Tracks' )
+ do( 'Select: Start=60 End=60')
+ capture( 'ClipBounds002.png', 'All_Tracks' )
+ do( 'SelPrevClipBoundaryToCursor' )
+ capture( 'ClipBounds003.png', 'All_Tracks' )
+ do( 'SelPrevClipBoundaryToCursor' )
+ capture( 'ClipBounds004.png', 'All_Tracks' )
+ do( 'SelPrevClipBoundaryToCursor' )
+ capture( 'ClipBounds005.png', 'All_Tracks' )
+ # clip bound right
+ gappyTrack2()
+ capture( 'ClipBounds006.png', 'All_Tracks' )
+ do( 'Select: Start=60 End=60')
+ capture( 'ClipBounds007.png', 'All_Tracks' )
+ do( 'SelCursorToNextClipBoundary' )
+ capture( 'ClipBounds008.png', 'All_Tracks' )
+ do( 'SelCursorToNextClipBoundary' )
+ capture( 'ClipBounds009.png', 'All_Tracks' )
+ do( 'SelCursorToNextClipBoundary' )
+ capture( 'ClipBounds010.png', 'All_Tracks' )
+ # clip left
+ gappyTrack2()
+ capture( 'ClipBounds011.png', 'All_Tracks' )
+ do( 'Select: Start=60 End=60')
+ capture( 'ClipBounds012.png', 'All_Tracks' )
+ do( 'SelPrevClip' )
+ capture( 'ClipBounds013.png', 'All_Tracks' )
+ do( 'SelPrevClip' )
+ capture( 'ClipBounds014.png', 'All_Tracks' )
+ # clip right
+ gappyTrack2()
+ capture( 'ClipBounds015.png', 'All_Tracks' )
+ do( 'Select: Start=60 End=60')
+ capture( 'ClipBounds016.png', 'All_Tracks' )
+ do( 'SelNextClip' )
+ capture( 'ClipBounds017.png', 'All_Tracks' )
+ do( 'SelNextClip' )
+ capture( 'ClipBounds018.png', 'All_Tracks' )
+
+
+
+
+
+clipb_imagesA()
diff --git a/scripts/piped-work/docimages_core.py b/scripts/piped-work/docimages_core.py
index d4c389fa8..991a9b509 100644
--- a/scripts/piped-work/docimages_core.py
+++ b/scripts/piped-work/docimages_core.py
@@ -72,9 +72,13 @@ def quickTest() :
def setup() :
global path
+ global sample_path
global sample
global sample2
+ global postfix
+ postfix = ''
path = 'C:\\Users\\James Crook\\'
+ sample_path ='C:\\Users\\James Crook\\Music\\'
sample ='C:\\Users\\James Crook\\Music\\The Poodle Podcast.wav'
sample2 ='C:\\Users\\James Crook\\Music\\PoodlePodStereo.wav'
startPipes()
@@ -89,8 +93,17 @@ def makeWayForTracks( ) :
def capture( name, what ) :
global path
+ global postfix
+ name = name.split( '.png' )[0] + postfix + '.png'
do( 'Screenshot: Path="'+path+name+'" CaptureWhat=' + what )
+def loadExample( name ):
+ global sample_path
+ makeWayForTracks( )
+ do( 'Import2: Filename="'+sample_path+name+'"' )
+ do( 'Select: First=0 Last=0 Start=0 End=0')
+ do( 'FitInWindow' )
+
def loadMonoTrack():
global sample
makeWayForTracks( )
@@ -112,6 +125,7 @@ def loadMonoTracks( num ) :
loadMonoTrack()
do( 'SetTrack: Track=0 Name="Foxy Lady"')
for i in range( 0, num-1 ):
+ do( 'Select: First=0 Last=0')
do( 'Duplicate' )
do( 'FitInWindow' )
do( 'Select: Start=55 End=70')
@@ -121,6 +135,7 @@ def loadStereoTracks( num ) :
loadStereoTrack()
do( 'SetTrack: Track=0 Name="Foxy Lady"')
for i in range( 0, num-1 ):
+ do( 'Select: First=0 Last=0')
do( 'Duplicate' )
do( 'FitInWindow' )
do( 'Select: Start=55 End=70 First=0 Last=' + str(num*2-1) )
diff --git a/scripts/piped-work/docimages_cut_n_paste.py b/scripts/piped-work/docimages_cut_n_paste.py
new file mode 100644
index 000000000..722958d64
--- /dev/null
+++ b/scripts/piped-work/docimages_cut_n_paste.py
@@ -0,0 +1,109 @@
+# docimages_cut_n_pastes.py
+# Sends commands to get images for the manual.
+# Images for cut_n_paste manipulation.
+
+# Make sure Audacity is running first and that mod-script-pipe is enabled
+# before running this script.
+
+#load and run the common core.
+exec( open("docimages_core.py" ).read() )
+
+def gappyTrack() :
+ loadMonoTracks(1)
+ # A mono track
+ do( 'Select: Start=0 End=10')
+ do( 'SplitCut' )
+ do( 'Select: Start=60 End=100')
+ do( 'SplitCut' )
+ do( 'Select: Start=30 End=50')
+
+def cut_n_paste_imagesA() :
+ # Split and move
+ gappyTrack()
+ capture( 'CutAndPaste001.png', 'All_Tracks' )
+ do( 'Split' )
+ capture( 'CutAndPaste002.png', 'All_Tracks' )
+ do( 'SetClip: At=55 Start=60')
+ capture( 'CutAndPaste003.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste004.png', 'All_Tracks' )
+
+def cut_n_paste_imagesB() :
+ # SplitNew
+ gappyTrack()
+ capture( 'CutAndPaste005.png', 'All_Tracks' )
+ do( 'SplitNew' )
+ capture( 'CutAndPaste006.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste007.png', 'All_Tracks' )
+
+def cut_n_paste_imagesC() :
+ # Join
+ gappyTrack()
+ do( 'Select: Start=45 End=75')
+ do( 'Split' )
+ do( 'Select: Start=39 End=129')
+ capture( 'CutAndPaste008.png', 'All_Tracks' )
+ do( 'Join' )
+ capture( 'CutAndPaste009.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste010.png', 'All_Tracks' )
+ # Detach at silences
+ do( 'Select: Start=0 End=150')
+ do( 'Join' )
+ capture( 'CutAndPaste011.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=150')
+ do( 'Disjoin' )
+ capture( 'CutAndPaste012.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste013.png', 'All_Tracks' )
+
+def cut_n_paste_imagesD() :
+ #Copy and Paste
+ gappyTrack()
+ do( 'Select: Start=15 End=20')
+ do( 'Copy' )
+ capture( 'CutAndPaste014.png', 'All_Tracks' )
+ #Pasting into
+ do( 'Select: Start=45 End=45')
+ capture( 'CutAndPaste015.png', 'All_Tracks' )
+ do( 'Paste' )
+ capture( 'CutAndPaste016.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste017.png', 'All_Tracks' )
+
+ gappyTrack()
+ do( 'Select: Start=15 End=20')
+ do( 'Copy' )
+ #Pasting before
+ do( 'Select: Start=5 End=5')
+ capture( 'CutAndPaste018.png', 'All_Tracks' )
+ do( 'Paste' )
+ capture( 'CutAndPaste019.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste030.png', 'All_Tracks' )
+
+ #pasting before with no movement (cheat)
+ do( 'Select: Start=11 End=16')
+ do( 'Cut' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste031.png', 'All_Tracks' )
+ do( 'Select: Start=5 End=10')
+ capture( 'CutAndPaste032.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+
+def cut_n_paste_imagesE() :
+ # Duplicate
+ gappyTrack()
+ capture( 'CutAndPaste033.png', 'All_Tracks' )
+ do( 'Duplicate' )
+ capture( 'CutAndPaste034.png', 'All_Tracks' )
+ do( 'Select: Start=0 End=0')
+ capture( 'CutAndPaste035.png', 'All_Tracks' )
+
+
+cut_n_paste_imagesA()
+cut_n_paste_imagesB()
+cut_n_paste_imagesC()
+cut_n_paste_imagesD()
+cut_n_paste_imagesE()
diff --git a/scripts/piped-work/docimages_envelopes.py b/scripts/piped-work/docimages_envelopes.py
new file mode 100644
index 000000000..41963f30e
--- /dev/null
+++ b/scripts/piped-work/docimages_envelopes.py
@@ -0,0 +1,45 @@
+# docimages_envelopes.py
+# Sends commands to get images for the manual.
+# Images for envelope manipulation.
+
+# Make sure Audacity is running first and that mod-script-pipe is enabled
+# before running this script.
+
+#load and run the common core.
+exec( open("docimages_core.py" ).read() )
+
+
+
+def env_images() :
+ loadMonoTracks(1)
+ do( 'Select: Start=0 End=0')
+ # A mono track
+ capture( 'Envelope001.png', 'All_Tracks' )
+ do( 'EnvelopeTool' )
+ # As spectrogram.
+ capture( 'Envelope002.png', 'All_Tracks' )
+ do( 'SetEnvelope: Time=55 Value=0.9');
+ capture( 'Envelope003.png', 'All_Tracks' )
+ do( 'SetEnvelope: Time=120 Value=0.4');
+ capture( 'Envelope004.png', 'All_Tracks' )
+ do( 'SetEnvelope: Time=125 Value=0.9');
+ capture( 'Envelope005.png', 'All_Tracks' )
+ do( 'SetEnvelope: Time=45 Value=0.85');
+ capture( 'Envelope006.png', 'All_Tracks' )
+ do( 'SetEnvelope: Time=25 Value=1.85');
+ capture( 'Envelope007.png', 'All_Tracks' )
+ do( 'SetEnvelope: Time=0 Value=0.85');
+ capture( 'Envelope008.png', 'All_Tracks' )
+ do( 'SetTrack: VZoom=Times2' )
+ capture( 'Envelope009.png', 'All_Tracks' )
+ do( 'SetTrack: VZoom=HalfWave' )
+ capture( 'Envelope010.png', 'All_Tracks' )
+ do( 'SelectTool' )
+ capture( 'Envelope011.png', 'All_Tracks' )
+ do( 'SetTrack: VZoom=Reset' )
+ capture( 'Envelope012.png', 'All_Tracks' )
+
+
+
+env_images()
+
diff --git a/scripts/piped-work/docimages_oddments.py b/scripts/piped-work/docimages_oddments.py
new file mode 100644
index 000000000..341f032c7
--- /dev/null
+++ b/scripts/piped-work/docimages_oddments.py
@@ -0,0 +1,50 @@
+# docimages_oddments.py
+# Sends commands to get images for the manual.
+# Image oddments that don't fit the other categories.
+
+# Make sure Audacity is running first and that mod-script-pipe is enabled
+# before running this script.
+# Historically this file has had peculiar problems with line endings.
+
+#load and run the common core.
+exec( open("docimages_core.py" ).read() )
+
+import time
+
+def oddments_imagesA():
+ for name in ["Select","Envelope","Draw","Zoom","TimeShift","Multi"] :
+ do( name + "Tool" )
+ capture( name + "Tool.png" , 'Tools' );
+ #A track is needed for the buttons to be active.
+ loadMonoTracks(1)
+ do( 'SetPreference: Name="/GUI/Theme" Value="high-contrast"')
+ for id in range( 11000, 11006 ):
+ do( "Drag: Id="+str( id) + " FromX=10 FromY=10" )
+ capture( "Button" + str(id) +"Hover.png", "Transport" )
+ do( "Drag: Id="+str( id) + " FromX=1000 FromY=10" )
+ for id in range( 11200, 11206 ):
+ do( "Drag: Id="+str( id) + " FromX=10 FromY=10" )
+ capture( "Button" + str(id) +"Hover.png", "Tools" )
+ do( "Drag: Id="+str( id) + " FromX=1000 FromY=10" )
+ for id in range( 11300, 11312 ):
+ do( "Drag: Id="+str( id) + " FromX=10 FromY=10" )
+ capture( "Button" + str(id) +"Hover.png", "Edit" )
+ do( "Drag: Id="+str( id) + " FromX=1000 FromY=10" )
+ do( 'SetPreference: Name="/GUI/Theme" Value="light"')
+
+
+def oddments_imagesB():
+ loadMonoTracks(1)
+ #Bring window to top now
+ capture( "Dummy.png", "Ruler" )
+ #We hope nothing else gets focus before the next capture, so
+ #that we actually get to see something!
+ do( "Drag: Window=Timeline FromX=200 FromY=10 ToX=600 ToY=10" )
+ time.sleep(3.0)
+ #Disable bringing to top, so as not to destroy quick play.
+ capture( "QuikPlay001.png", "First_Track_Plus ToTop=0" )
+
+oddments_imagesA()
+oddments_imagesB()
+
+
diff --git a/scripts/piped-work/docimages_spectro.py b/scripts/piped-work/docimages_spectro.py
index d24df4e19..7d734c8cf 100644
--- a/scripts/piped-work/docimages_spectro.py
+++ b/scripts/piped-work/docimages_spectro.py
@@ -8,6 +8,8 @@
#load and run the common core.
exec( open("docimages_core.py" ).read() )
+import math
+import time
# 11 2KHz tones, of decreasing amplitude.
@@ -32,29 +34,139 @@ def makeStepper():
do( 'Select: Start=0 End=0')
-def spectro_image1and2() :
+def spectro_imagesA() :
loadStereoTracks(1)
# A stereo track
capture( 'Spectral001.png', 'First_Track' )
# As spectrogram.
do( 'SetTrack: Track=0 Display=Spectrogram')
do( 'Select: Start=55 End=70 First=0 Last=1')
- capture( 'Spectral002.png', 'First_Track' )
+ capture( 'Spectral002.png', 'All_Tracks' )
# Half spectrogram, half wave.
do( 'SetTrack: Channel=1 Display=Waveform')
- capture( 'MixedMode.png', 'First_Track' )
+ capture( 'MixedMode.png', 'All_Tracks' )
-def spectro_image3and4():
+def spectro_imagesB():
makeStepper();
# Stepper tone, viewed in dB.
do( 'SetTrack: Scale=dB')
- capture( 'Spectral003.png', 'First_Two_Tracks' )
+ capture( 'Spectral003.png', 'All_Tracks' )
# As spectrogram.
do( 'SetTrack: Display=Spectrogram')
- capture( 'Spectral004.png', 'First_Two_Tracks' )
+ capture( 'Spectral004.png', 'All_Tracks' )
+
+def spectro_imagesC():
+ # A chirp and the word 'Audacity'
+ loadExample( 'AudacitySpectral.wav' )
+ capture( 'Spectral005.png', 'All_Tracks' )
+ do( 'SetTrack: Scale=dB')
+ capture( 'Spectral006.png', 'All_Tracks' )
+ do( 'SetTrack: Display=Spectrogram')
+ capture( 'Spectral007.png', 'All_Tracks' )
+ do( 'Select: Start=1.5 End=2.1 Low=3000 High=6000')
+ capture( 'Spectral008.png', 'All_Tracks' )
+ do( 'Select: Start=1.1 End=2.5' )
+ do( 'ZoomSel' )
+ do( 'Select: Start=1.5 End=2.1 Low=3000 High=6000')
+ do( 'SetTrack: Height=400' )
+ multiWindow( "SpectralVocal" )
+
+def setWindow( name, value ):
+ do( 'SetTrack: SpecPrefs=1 Name="Window Size '+value+'"' )
+ do( 'SetPreference: Name="/Spectrum/FFTSize" Reload=1 Value='+value )
+ do( 'SetTrack: Track=0 Display=Spectrogram' )
+ capture( name + postfix + value + '.png', 'All_Tracks' )
+
+
+def multiWindow( name ) :
+ setWindow( name, "256" )
+ setWindow( name, "512" )
+ setWindow( name, "2048" )
+ setWindow( name, "4096" )
+ setWindow( name, "8192" )
+ setWindow( name, "1024" ) # done last so we restore the default.
+
+def spectro_imagesD():
+ makeWayForTracks()
+ do( 'NewMonoTrack' )
+ do( 'Select: Start=0.7 End=1.3')
+ do( 'Silence' ) #Just so we can watch.
+ do( 'Select: Start=0.8 End=1.2')
+ do( 'ZoomSel')
+ do( 'Select: Start=0.7 End=1.3')
+ do( 'Tone: Frequency=3000 Amplitude=0.8' )
+ do( 'Select: Start=0.99 End=0.99005' )
+ do( 'Tone: Frequency=12000 Amplitude=0.9' )
+ do( 'Select: Start=1.01 End=1.01005' )
+ do( 'Tone: Frequency=12000 Amplitude=0.9' )
+ do( 'Select: Start=0 End=0' )
+ multiWindow( 'SpectralAt' )
+
+def spectro_imagesE():
+ makeWayForTracks()
+ do( 'NewMonoTrack' )
+ do( 'Select: Start=0 End=1.2')
+ do( 'ZoomSel')
+ do( 'Pluck' )
+ do( 'Select: Start=0.1 End=1.0')
+ do( 'ZoomSel')
+ multiWindow( 'SpectralNote' )
+
+def makeScale( start, end, count ) :
+ a = math.exp( math.log( end/start) /(count-1 ))
+ makeWayForTracks()
+ do( 'NewMonoTrack' )
+ do( 'Select: Start=0 End=' + str( count/10 ))
+ do( 'Silence' ) #To see it happen...
+ do( 'SetTrack: Track=0 SpecPrefs=1 Display=Spectrogram' )
+ do( 'ZoomSel' )
+ #do( 'SetTrack: Track=0 Display=Spectrogram' )
+ for i in range( 0 , count , 2 ):
+ note = start * ( a ** i )
+ #print( note )
+ do( 'Select: Start=' + str( i / 10) + ' End=' + str( (i+1)/10 ))
+ do( 'Tone: Frequency=' +str( note ) )
+ do( 'Select: Start=' + str( i / 10) + ' End=' + str( ( i / 10) +0.05))
+ do( 'FadeIn' )
+ do( 'Select: Start=' + str( (i+1) / 10 -0.05) + ' End=' + str( (i+1) / 10 ))
+ do( 'FadeOut' )
+ do( 'FitInWindow' )
+ #do( 'Select: Start=0 End=' + str( count/10 ))
+ #do( 'Join' )
+ do( 'Select: Start=0 End=0')
+
+
+def spectro_imagesF():
+ makeScale( 200, 4000, 100 )
+ do( 'SetTrack: Track=0 Display=Spectrogram' )
+ capture( 'ScaleLin.png', 'All_Tracks' )
+ do( 'SetPreference: Name=/Spectrum/ScaleType Value=1 Reload=1')
+ capture( 'ScaleLog.png', 'All_Tracks' )
+ do( 'SetPreference: Name=/Spectrum/ScaleType Value=0 Reload=1')
+
+
#quickTest()
-spectro_image1and2()
-spectro_image3and4()
+do( 'SetPreference: Name="/GUI/Theme" Value=light Reload=1' )
+
+postfix = ''
+spectro_imagesA()
+spectro_imagesB()
+spectro_imagesC()
+spectro_imagesD()
+spectro_imagesE()
+spectro_imagesF()
+
+do( 'SetPreference: Name="/GUI/Theme" Value=dark Reload=1' )
+
+postfix = 'Dark'
+spectro_imagesA()
+spectro_imagesB()
+spectro_imagesC()
+spectro_imagesD()
+spectro_imagesE()
+spectro_imagesF()
+
+do( 'SetPreference: Name="/GUI/Theme" Value=light Reload=1' )
diff --git a/scripts/piped-work/make_html.py b/scripts/piped-work/make_html.py
new file mode 100644
index 000000000..2fca833d7
--- /dev/null
+++ b/scripts/piped-work/make_html.py
@@ -0,0 +1,17 @@
+# Takes an image file directory and makes the web page that lists them.
+# They are listed in creation date/time order.
+
+import glob
+import os
+
+def getFiles() :
+ files = glob.glob("C:\\OpenSourceGit\\AudacityTeamTools\\wit-html\\auto_images\\*.png")
+ files.sort(key=os.path.getmtime)
+ return [ os.path.basename( name ) for name in files ]
+ #print("\n".join(files))
+
+def oneItem( name ) :
+ return "
"+name+"
"
+
+files = getFiles()
+print( "\n".join( [ oneItem(name) for name in files ] ) )
diff --git a/scripts/piped-work/pipeclient.py b/scripts/piped-work/pipeclient.py
new file mode 100644
index 000000000..3cf939501
--- /dev/null
+++ b/scripts/piped-work/pipeclient.py
@@ -0,0 +1,296 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""Automate Audacity via mod-script-pipe.
+
+Pipe Client may be used as a command-line script to send commands to
+Audacity via the mod-script-pipe interface, or loaded as a module.
+Requires Python 2.7 or later. Python 3 recommended.
+
+======================
+Command Line Interface
+======================
+
+ usage: pipeclient.py [-h] [-t] [-s ] [-d]
+
+Arguments
+---------
+ -h,--help: optional
+ show short help and exit
+ -t, --timeout: float, optional
+ timeout for reply in seconds (default: 10)
+ -s, --show-time: bool, optional
+ show command execution time (default: True)
+ -d, --docs: optional
+ show this documentation and exit
+
+Example
+-------
+ $ python3 pipeclient.py -t 20 -s False
+
+ Launches command line interface with 20 second time-out for
+ returned message, and don't show the execution time.
+
+ When prompted, enter the command to send (not quoted), or 'Q' to quit.
+
+ $ Enter command or 'Q' to quit: GetInfo: Type=Tracks Format=LISP
+
+============
+Module Usage
+============
+
+Note that on a critical error (such as broken pipe), the module just exits.
+If a more graceful shutdown is required, replace the sys.exit()'s with
+exceptions.
+
+Example
+-------
+
+ # Import the module:
+ >>> import pipeclient
+
+ # Create a client instance:
+ >>> client = pipeclient.PipeClient()
+
+ # Send a command:
+ >>> client.write("Command", timer=True)
+
+ # Read the last reply:
+ >>> print(client.read())
+
+See Also
+--------
+PipeClient.write : Write a command to _write_pipe.
+PipeClient.read : Read Audacity's reply from pipe.
+
+Copyright Steve Daulton 2018
+Released under terms of the GNU General Public License version 2:
+
+
+"""
+
+import os
+import sys
+import threading
+import time
+import errno
+import argparse
+
+
+if sys.version_info[0] < 3 and sys.version_info[1] < 7:
+ sys.exit('PipeClient Error: Python 2.7 or later required')
+
+# Platform specific constants
+if sys.platform == 'win32':
+ WRITE_NAME = '\\\\.\\pipe\\ToSrvPipe'
+ READ_NAME = '\\\\.\\pipe\\FromSrvPipe'
+ EOL = '\r\n\0'
+else:
+ # Linux or Mac
+ PIPE_BASE = '/tmp/audacity_script_pipe.'
+ WRITE_NAME = PIPE_BASE + 'to.' + str(os.getuid())
+ READ_NAME = PIPE_BASE + 'from.' + str(os.getuid())
+ EOL = '\n'
+
+
+class PipeClient(object):
+ """Write / read client access to Audacity via named pipes.
+
+ Normally there should be just one instance of this class. If
+ more instances are created, they all share the same state.
+
+ __init__ calls _write_thread_start() and _read_thread_start() on
+ first instantiation.
+
+ Parameters
+ ----------
+ None
+
+ Attributes
+ ----------
+ reader_pipe_broken : event object
+ Set if pipe reader fails. Audacity may have crashed
+ reply_ready : event object
+ flag cleared when command sent and set when response received
+ timer : bool
+ When true, time the command execution (default False)
+ reply : string
+ message received when Audacity completes the command
+
+ See Also
+ --------
+ write : Write a command to _write_pipe.
+ read : Read Audacity's reply from pipe.
+
+ """
+
+ reader_pipe_broken = threading.Event()
+ reply_ready = threading.Event()
+
+ _shared_state = {}
+
+ def __new__(cls, *p, **k):
+ self = object.__new__(cls, *p, **k)
+ self.__dict__ = cls._shared_state
+ return self
+
+ def __init__(self):
+ self.timer = False
+ self._start_time = 0
+ self._write_pipe = None
+ self.reply = ''
+ if not self._write_pipe:
+ self._write_thread_start()
+ self._read_thread_start()
+
+ def _write_thread_start(self):
+ """Start _write_pipe thread"""
+ # Pipe is opened in a new thread so that we don't
+ # freeze if Audacity is not running.
+ write_thread = threading.Thread(target=self._write_pipe_open)
+ write_thread.daemon = True
+ write_thread.start()
+ # Allow a little time for connection to be made.
+ time.sleep(0.1)
+ if not self._write_pipe:
+ sys.exit('PipeClientError: Write pipe cannot be opened.')
+
+ def _write_pipe_open(self):
+ """Open _write_pipe."""
+ self._write_pipe = open(WRITE_NAME, 'w')
+
+ def _read_thread_start(self):
+ """Start read_pipe thread."""
+ read_thread = threading.Thread(target=self._reader)
+ read_thread.daemon = True
+ read_thread.start()
+
+ def write(self, command, timer=False):
+ """Write a command to _write_pipe.
+
+ Parameters
+ ----------
+ command : string
+ The command to send to Audacity
+ timer : bool, optional
+ If true, time the execution of the command
+
+ Example
+ -------
+ write("GetInfo: Type=Labels", timer=True):
+
+ """
+ self.timer = timer
+ print('Sending command:', command)
+ self._write_pipe.write(command + EOL)
+ # Check that read pipe is alive
+ if PipeClient.reader_pipe_broken.isSet():
+ sys.exit('PipeClient: Read-pipe error.')
+ try:
+ self._write_pipe.flush()
+ if self.timer:
+ self._start_time = time.time()
+ self.reply = ''
+ PipeClient.reply_ready.clear()
+ except IOError as err:
+ if err.errno == errno.EPIPE:
+ sys.exit('PipeClient: Write-pipe error.')
+ else:
+ raise
+
+ def _reader(self):
+ """Read FIFO in worker thread."""
+ # Thread will wait at this read until it connects.
+ # Connection should occur as soon as _write_pipe has connected.
+ read_pipe = open(READ_NAME, 'r')
+ message = ''
+ while True:
+ line = read_pipe.readline()
+ # Stop timer as soon as we get first line of response.
+ stop_time = time.time()
+ while line != EOL:
+ message += line
+ line = read_pipe.readline()
+ if line == '':
+ # No data in read_pipe indicates that the pipe is broken
+ # (Audacity may have crashed).
+ PipeClient.reader_pipe_broken.set()
+ if self.timer:
+ xtime = (stop_time - self._start_time) * 1000
+ message += 'Execution time: {0:.2f}ms'.format(xtime)
+ self.reply = message
+ PipeClient.reply_ready.set()
+ message = ''
+ read_pipe.close()
+
+ def read(self):
+ """Read Audacity's reply from pipe.
+
+ Returns
+ -------
+ string
+ The reply from the last command sent to Audacity, or null string
+ if reply not received. Null string usually indicates that Audacity
+ is still processing the last command.
+
+ """
+ if not PipeClient.reply_ready.isSet():
+ return ''
+ else:
+ return self.reply
+
+
+def bool_from_string(strval):
+ """Return boolean value from string"""
+ if strval.lower() in ('true', 't', '1', 'yes', 'y'):
+ return True
+ elif strval.lower() in ('false', 'f', '0', 'no', 'n'):
+ return False
+ else:
+ raise argparse.ArgumentTypeError('Boolean value expected.')
+
+def main():
+ """Interactive command-line for PipeClient"""
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-t', '--timeout', type=float, metavar='', default=10,
+ help="timeout for reply in seconds (default: 10")
+ parser.add_argument('-s', '--show-time', metavar='True/False',
+ nargs='?', type=bool_from_string,
+ const='t', default='t', dest='show',
+ help='show command execution time (default: True)')
+ parser.add_argument('-d', '--docs', action='store_true',
+ help='show documentation and exit')
+ args = parser.parse_args()
+
+ if args.docs:
+ print(__doc__)
+ sys.exit(0)
+
+ client = PipeClient()
+ while True:
+ reply = ''
+ if sys.version_info[0] < 3:
+ #pylint: disable=undefined-variable
+ message = raw_input("\nEnter command or 'Q' to quit: ")
+ else:
+ message = input( #pylint: disable=bad-builtin
+ "\nEnter command or 'Q' to quit: ")
+ start = time.time()
+ if message.upper() == 'Q':
+ sys.exit(0)
+ elif message == '':
+ pass
+ else:
+ client.write(message, timer=args.show)
+ while reply == '':
+ time.sleep(0.1) # allow time for reply
+ if time.time() - start > args.timeout:
+ reply = 'PipeClient: Reply timed-out.'
+ else:
+ reply = client.read()
+ print(reply)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/commands/CommandManager.cpp b/src/commands/CommandManager.cpp
index 9d1bb8797..6e833f97a 100644
--- a/src/commands/CommandManager.cpp
+++ b/src/commands/CommandManager.cpp
@@ -947,7 +947,7 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
count, {});
}
-CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
+CommandListEntry *CommandManager::NewIdentifier(const wxString & nameIn,
const wxString & label,
const wxString & accel,
wxMenu *menu,
@@ -958,6 +958,8 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
int count,
const CommandParameter ¶meter)
{
+ wxString name = nameIn;
+
// If we have the identifier already, reuse it.
CommandListEntry *prev = mCommandNameHash[name];
if (!prev);
@@ -975,6 +977,18 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
labelPrefix = mSubMenuList.back()->name;
}
+ // For key bindings for commands with a list, such as align,
+ // the name in prefs is the category name plus the effect name.
+ // This feature is not used for built-in effects.
+ if (multi) {
+ // The name needs to be clean for use by automation.
+ wxString cleanedName = wxString::Format(wxT("%s_%s"), name, label);
+ cleanedName.Replace( "/", "" );
+ cleanedName.Replace( "&", "" );
+ cleanedName.Replace( " ", "" );
+ name = cleanedName;
+ }
+
// wxMac 2.5 and higher will do special things with the
// Preferences, Exit (Quit), and About menu items,
// if we give them the right IDs.
@@ -1024,13 +1038,6 @@ CommandListEntry *CommandManager::NewIdentifier(const wxString & name,
if( mMaxListOnly.Index( entry->key ) !=-1)
entry->key = wxT("");
-
- // For key bindings for commands with a list, such as effects,
- // the name in prefs is the category name plus the effect name.
- if (multi) {
- entry->name = wxString::Format(wxT("%s:%s"), name, label);
- }
-
// Key from preferences overridse the default key given
gPrefs->SetPath(wxT("/NewKeys"));
if (gPrefs->HasEntry(entry->name)) {
@@ -1551,6 +1558,14 @@ bool CommandManager::HandleTextualCommand(const wxString & Str, const CommandCon
return HandleCommandEntry( entry.get(), flags, mask);
}
}
+ else
+ {
+ // Handle multis too...
+ if( Str.IsSameAs( entry->name, false ) )
+ {
+ return HandleCommandEntry( entry.get(), flags, mask);
+ }
+ }
}
// Not one of the singleton commands.
// We could/should try all the list-style commands.
diff --git a/src/commands/DragCommand.cpp b/src/commands/DragCommand.cpp
index cfa39c8fe..15d223ea1 100644
--- a/src/commands/DragCommand.cpp
+++ b/src/commands/DragCommand.cpp
@@ -49,7 +49,7 @@ static const wxString kCoordTypeStrings[nCoordTypes] =
bool DragCommand::DefineParams( ShuttleParams & S ){
wxArrayString coords( nCoordTypes, kCoordTypeStrings );
- S.OptionalN( bHasId ).Define( mId, wxT("Id"), 0.0, 11000.0, 1000000.0);
+ S.OptionalN( bHasId ).Define( mId, wxT("Id"), 11000.0, -100000.0, 1000000.0);
S.OptionalY( bHasWinName ).Define( mWinName, wxT("Window"), "Timeline");
S.OptionalY( bHasFromX ).Define( mFromX, wxT("FromX"), 200.0, 0.0, 1000000.0);
S.OptionalY( bHasFromY ).Define( mFromY, wxT("FromY"), 10.0, 0.0, 1000000.0);
diff --git a/src/commands/ScreenshotCommand.cpp b/src/commands/ScreenshotCommand.cpp
index dcbd95263..a8ff7c6f1 100644
--- a/src/commands/ScreenshotCommand.cpp
+++ b/src/commands/ScreenshotCommand.cpp
@@ -139,9 +139,10 @@ static const wxString kBackgroundStrings[nBackgrounds] =
bool ScreenshotCommand::DefineParams( ShuttleParams & S ){
wxArrayString whats(nCaptureWhats, kCaptureWhatStrings);
wxArrayString backs(nBackgrounds, kBackgroundStrings);
- S.Define( mPath, wxT("Path"), wxT(""));
- S.DefineEnum( mWhat, wxT("CaptureWhat"), wxT("Window"), whats );
- S.OptionalN(bHasBackground).DefineEnum( mBack, wxT("Background"), wxT("None"), backs );
+ S.Define( mPath, wxT("Path"), wxT(""));
+ S.DefineEnum( mWhat, wxT("CaptureWhat"), wxT("Window"), whats );
+ S.OptionalN(bHasBackground).DefineEnum( mBack, wxT("Background"), wxT("None"), backs );
+ S.OptionalN(bHasBringToTop).Define( mbBringToTop, wxT("ToTop"), true );
return true;
};
@@ -153,9 +154,10 @@ void ScreenshotCommand::PopulateOrExchange(ShuttleGui & S)
S.StartMultiColumn(2, wxALIGN_CENTER);
{
- S.TieTextBox( _("Path:"), mPath);
- S.TieChoice( _("Capture What:"), mWhat, &whats);
- S.TieChoice( _("Background:"), mBack, &backs);
+ S.TieTextBox( _("Path:"), mPath);
+ S.TieChoice( _("Capture What:"), mWhat, &whats);
+ S.TieChoice( _("Background:"), mBack, &backs);
+ S.TieCheckBox( _("Bring To Top:"), mbBringToTop);
}
S.EndMultiColumn();
}
@@ -247,16 +249,18 @@ bool ScreenshotCommand::Capture(
int height = r.height;
if( r.width == 0 )
return false;
- if (window) {
- if (window->IsTopLevel()) {
- window->Raise();
- }
- else {
- wxGetTopLevelParent(window)->Raise();
+ if (window ) {
+ wxWindow * win = window;
+ wxTopLevelWindow * top_win= nullptr;
+ if( !window->IsTopLevel())
+ win = wxGetTopLevelParent(window);
+ top_win = dynamic_cast( win );
+ if( (!bHasBringToTop || mbBringToTop) && (!top_win || !top_win->IsActive()) ){
+ win->Raise();
+ Yield();
}
}
- Yield();
int screenW, screenH;
wxDisplaySize(&screenW, &screenH);
diff --git a/src/commands/ScreenshotCommand.h b/src/commands/ScreenshotCommand.h
index 53ad6f41f..c481a4c57 100644
--- a/src/commands/ScreenshotCommand.h
+++ b/src/commands/ScreenshotCommand.h
@@ -33,6 +33,7 @@ class CommandContext;
class ScreenshotCommand : public AudacityCommand
{
public:
+ ScreenshotCommand(){ mbBringToTop=true;};
// CommandDefinitionInterface overrides
wxString GetSymbol() override {return SCREENSHOT_PLUGIN_SYMBOL;};
wxString GetDescription() override {return _("Takes screenshots.");};
@@ -46,7 +47,9 @@ private:
wxString mWhat;
wxString mBack;
wxString mPath;
+ bool mbBringToTop;
bool bHasBackground;
+ bool bHasBringToTop;
friend class ScreenshotCommand;
friend class ScreenFrame;
diff --git a/src/commands/SetEnvelopeCommand.cpp b/src/commands/SetEnvelopeCommand.cpp
index 0cdc20ca0..56854fd49 100644
--- a/src/commands/SetEnvelopeCommand.cpp
+++ b/src/commands/SetEnvelopeCommand.cpp
@@ -35,7 +35,7 @@ bool SetEnvelopeCommand::DefineParams( ShuttleParams & S ){
S.OptionalY( bHasTrackIndex ).Define( mTrackIndex, wxT("Track"), 0, 0, 100 );
S.OptionalN( bHasChannelIndex ).Define( mChannelIndex, wxT("Channel"), 0, 0, 100 );
S.OptionalY( bHasT ).Define( mT, wxT("Time"), 0.0, 0.0, 100000.0);
- S.OptionalY( bHasV ).Define( mV, wxT("Value"), 0.0, 0.0, 2.0);
+ S.OptionalY( bHasV ).Define( mV, wxT("Value"), 1.0, 0.0, 2.0);
S.OptionalN( bHasDelete ).Define( mbDelete, wxT("Delete"), false );
return true;
};
diff --git a/src/commands/SetTrackInfoCommand.cpp b/src/commands/SetTrackInfoCommand.cpp
index b92276aa2..acd20167b 100644
--- a/src/commands/SetTrackInfoCommand.cpp
+++ b/src/commands/SetTrackInfoCommand.cpp
@@ -77,10 +77,27 @@ static const wxString kScaleTypeStrings[nScaleTypes] =
};
+enum kZoomTypes
+{
+ kReset,
+ kTimes2,
+ kHalfWave,
+ nZoomTypes
+};
+
+static const wxString kZoomTypeStrings[nZoomTypes] =
+{
+ XO("Reset"),
+ XO("Times2"),
+ XO("HalfWave"),
+};
+
+
bool SetTrackCommand::DefineParams( ShuttleParams & S ){
wxArrayString colours( nColours, kColourStrings );
wxArrayString displays( nDisplayTypes, kDisplayTypeStrings );
wxArrayString scales( nScaleTypes, kScaleTypeStrings );
+ wxArrayString vzooms( nZoomTypes, kZoomTypeStrings );
S.OptionalY( bHasTrackIndex ).Define( mTrackIndex, wxT("Track"), 0, 0, 100 );
S.OptionalN( bHasChannelIndex ).Define( mChannelIndex, wxT("Channel"), 0, 0, 100 );
@@ -92,6 +109,7 @@ bool SetTrackCommand::DefineParams( ShuttleParams & S ){
S.OptionalN( bHasScaleType ).DefineEnum( mScaleType, wxT("Scale"), kLinear, scales );
S.OptionalN( bHasColour ).DefineEnum( mColour, wxT("Color"), kColour0, colours );
S.OptionalN( bHasUseSpecPrefs ).Define( bUseSpecPrefs, wxT("SpecPrefs"), false );
+ S.OptionalN( bHasVZoom ).DefineEnum( mVZoom, wxT("VZoom"), kReset, vzooms );
S.OptionalN( bHasSpectralSelect ).Define( bSpectralSelect, wxT("SpectralSel"),true );
S.OptionalN( bHasGrayScale ).Define( bGrayScale, wxT("GrayScale"), false );
@@ -108,6 +126,7 @@ void SetTrackCommand::PopulateOrExchange(ShuttleGui & S)
wxArrayString colours( nColours, kColourStrings );
wxArrayString displays( nDisplayTypes, kDisplayTypeStrings );
wxArrayString scales( nScaleTypes, kScaleTypeStrings );
+ wxArrayString vzooms( nZoomTypes, kZoomTypeStrings );
S.AddSpace(0, 5);
@@ -122,6 +141,7 @@ void SetTrackCommand::PopulateOrExchange(ShuttleGui & S)
S.Optional( bHasColour ).TieChoice( _("Colour:"), mColour, &colours );
S.Optional( bHasDisplayType ).TieChoice( _("Display:"), mDisplayType, &displays );
S.Optional( bHasScaleType ).TieChoice( _("Scale:"), mScaleType, &scales );
+ S.Optional( bHasVZoom ).TieChoice( _("VZoom:"), mVZoom, &vzooms );
}
S.EndMultiColumn();
S.StartMultiColumn(2, wxALIGN_CENTER);
@@ -188,11 +208,19 @@ bool SetTrackCommand::Apply(const CommandContext & context)
wt->GetSpectrogramSettings().spectralSelection = bSpectralSelect;
if( wt && bHasGrayScale )
wt->GetSpectrogramSettings().isGrayscale = bGrayScale;
+ if( wt && bHasVZoom ){
+ switch( mVZoom ){
+ default:
+ case kReset: wt->SetDisplayBounds(-1,1); break;
+ case kTimes2: wt->SetDisplayBounds(-2,2); break;
+ case kHalfWave: wt->SetDisplayBounds(0,1); break;
+ }
+ }
// These ones don't make sense on the second channel of a stereo track.
if( !bIsSecondChannel ){
if( bHasSelected )
t->SetSelected(bSelected);
- if( bHasFocused )
+ if( bHasFocused && bFocused)
{
TrackPanel *panel = context.GetProject()->GetTrackPanel();
panel->SetFocusedTrack( t );
diff --git a/src/commands/SetTrackInfoCommand.h b/src/commands/SetTrackInfoCommand.h
index 6bffc26ad..d673d588b 100644
--- a/src/commands/SetTrackInfoCommand.h
+++ b/src/commands/SetTrackInfoCommand.h
@@ -47,6 +47,7 @@ public:
int mHeight;
int mDisplayType;
int mScaleType;
+ int mVZoom;
bool bUseSpecPrefs;
bool bSpectralSelect;
bool bGrayScale;
@@ -65,6 +66,7 @@ public:
bool bHasHeight;
bool bHasDisplayType;
bool bHasScaleType;
+ bool bHasVZoom;
bool bHasUseSpecPrefs;
bool bHasSpectralSelect;
bool bHasGrayScale;
diff --git a/src/toolbars/ControlToolBar.h b/src/toolbars/ControlToolBar.h
index 897871ee1..059bc6b0e 100644
--- a/src/toolbars/ControlToolBar.h
+++ b/src/toolbars/ControlToolBar.h
@@ -141,12 +141,12 @@ class ControlToolBar final : public ToolBar {
enum
{
- ID_PLAY_BUTTON = 11000,
- ID_RECORD_BUTTON,
- ID_PAUSE_BUTTON,
+ ID_PAUSE_BUTTON = 11000,
+ ID_PLAY_BUTTON,
ID_STOP_BUTTON,
ID_FF_BUTTON,
ID_REW_BUTTON,
+ ID_RECORD_BUTTON,
BUTTON_COUNT,
};
diff --git a/src/toolbars/EditToolBar.cpp b/src/toolbars/EditToolBar.cpp
index a2ae1b27a..0c0024965 100644
--- a/src/toolbars/EditToolBar.cpp
+++ b/src/toolbars/EditToolBar.cpp
@@ -69,8 +69,8 @@ const int SEPARATOR_WIDTH = 14;
////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE( EditToolBar, ToolBar )
- EVT_COMMAND_RANGE( ETBCutID,
- ETBCutID + ETBNumButtons - 1,
+ EVT_COMMAND_RANGE( ETBCutID+first_ETB_ID,
+ ETBCutID+first_ETB_ID + ETBNumButtons - 1,
wxEVT_COMMAND_BUTTON_CLICKED,
EditToolBar::OnButton )
END_EVENT_TABLE()
@@ -110,7 +110,7 @@ AButton *EditToolBar::AddButton(
r = ToolBar::MakeButton(pBar,
bmpRecoloredUpSmall, bmpRecoloredDownSmall, bmpRecoloredUpHiliteSmall, bmpRecoloredHiliteSmall,
eEnabledUp, eEnabledDown, eDisabled,
- wxWindowID(id),
+ wxWindowID(id+first_ETB_ID),
wxDefaultPosition,
toggle,
theTheme.ImageSize( bmpRecoloredUpSmall ));
@@ -291,7 +291,7 @@ void EditToolBar::ForAllButtons(int Action)
void EditToolBar::OnButton(wxCommandEvent &event)
{
- int id = event.GetId();
+ int id = event.GetId()-first_ETB_ID;
// Be sure the pop-up happens even if there are exceptions, except for buttons which toggle.
auto cleanup = finally( [&] { mButtons[id]->InteractionOver();});
diff --git a/src/toolbars/EditToolBar.h b/src/toolbars/EditToolBar.h
index 8eba5a155..55dc854be 100644
--- a/src/toolbars/EditToolBar.h
+++ b/src/toolbars/EditToolBar.h
@@ -62,6 +62,8 @@ enum {
ETBNumButtons
};
+const int first_ETB_ID = 11300;
+
// flags so 1,2,4,8 etc.
enum {
ETBActTooltips = 1,
diff --git a/src/toolbars/ToolsToolBar.cpp b/src/toolbars/ToolsToolBar.cpp
index 9de3061fc..f59e73a5e 100644
--- a/src/toolbars/ToolsToolBar.cpp
+++ b/src/toolbars/ToolsToolBar.cpp
@@ -67,8 +67,8 @@ IMPLEMENT_CLASS(ToolsToolBar, ToolBar);
////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(ToolsToolBar, ToolBar)
- EVT_COMMAND_RANGE(firstTool,
- lastTool,
+ EVT_COMMAND_RANGE(firstTool+FirstToolID,
+ lastTool+FirstToolID,
wxEVT_COMMAND_BUTTON_CLICKED,
ToolsToolBar::OnTool)
END_EVENT_TABLE()
@@ -165,7 +165,7 @@ AButton * ToolsToolBar::MakeTool(
bmpRecoloredUpHiliteSmall,
bmpRecoloredDownSmall, // Not bmpRecoloredHiliteSmall as down is inactive.
eTool, eTool, eTool,
- wxWindowID(id),
+ wxWindowID(id + FirstToolID),
wxDefaultPosition, true,
theTheme.ImageSize( bmpRecoloredUpSmall ));
button->SetLabel( label );
@@ -250,7 +250,7 @@ int ToolsToolBar::GetDownTool()
void ToolsToolBar::OnTool(wxCommandEvent & evt)
{
- mCurrentTool = evt.GetId() - firstTool;
+ mCurrentTool = evt.GetId() - firstTool - FirstToolID;
for (int i = 0; i < numTools; i++)
if (i == mCurrentTool)
mTool[i]->PushDown();
diff --git a/src/toolbars/ToolsToolBar.h b/src/toolbars/ToolsToolBar.h
index 3a5a2b2dc..a50cab94a 100644
--- a/src/toolbars/ToolsToolBar.h
+++ b/src/toolbars/ToolsToolBar.h
@@ -41,9 +41,11 @@ enum {
numTools,
firstTool = selectTool,
- lastTool = multiTool
+ lastTool = multiTool,
};
+const int FirstToolID = 11200;
+
class ToolsToolBar final : public ToolBar {
public: