From baf631961360b1158f25b743f0bedfa60bc428f4 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 11 Apr 2016 14:36:57 +0200 Subject: update and cleanup lua example scripts --- scripts/a_tomsloop.lua | 127 ---------------------------------------- scripts/editor_test.lua | 16 ----- scripts/s_fader_automation.lua | 39 +++++++----- scripts/s_foreach_track.lua | 3 +- scripts/s_plugin_automation.lua | 26 +++++--- scripts/s_selection.lua | 60 +++++++++++++++++++ scripts/tomsloop.lua | 127 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 228 insertions(+), 170 deletions(-) delete mode 100644 scripts/a_tomsloop.lua delete mode 100644 scripts/editor_test.lua create mode 100644 scripts/s_selection.lua create mode 100644 scripts/tomsloop.lua (limited to 'scripts') diff --git a/scripts/a_tomsloop.lua b/scripts/a_tomsloop.lua deleted file mode 100644 index f1bca82068..0000000000 --- a/scripts/a_tomsloop.lua +++ /dev/null @@ -1,127 +0,0 @@ -ardour { ["type"] = "EditorAction", name = "Tom's Loop", - license = "MIT", - author = "Robin Gareus", - email = "robin@gareus.org", - site = "http://gareus.org", - description = [[Bounce the loop-range of all non muted audio tracks, paste N times at playhead]] -} - -function action_params () - return { ["times"] = { title = "Number of copies to add", default = "1"}, } -end - -function factory (params) return function () - -- get options - local p = params or {} - local n_paste = tonumber (p["times"] or 1) - assert (n_paste > 0) - - local proc = ARDOUR.LuaAPI.nil_proc () -- bounce w/o processing - local itt = ARDOUR.InterThreadInfo () -- bounce progress info (unused) - - local loop = Session:locations ():auto_loop_location () - local playhead = Session:transport_frame () - - -- make sure we have a loop, and the playhead (edit point) is after it - if not loop then - print ("A Loop range must be set.") - goto errorout - end - assert (loop:start () < loop:_end ()) - if loop:_end () >= playhead then - print ("The Playhead (paste point) needs to be after the loop.") - goto errorout - end - - -- prepare undo operation - Session:begin_reversible_command ("Tom's Loop") - local add_undo = false -- keep track if something has changed - - -- prefer solo'ed tracks - local soloed_track_found = false - for route in Session:get_tracks ():iter () do - if route:soloed () then - soloed_track_found = true - break - end - end - - -- count regions that are bounced - local n_regions_created = 0 - - -- loop over all tracks in the session - for route in Session:get_tracks ():iter () do - if soloed_track_found then - -- skip not soloed tracks - if not route:soloed () then - goto continue - end - end - - -- skip muted tracks (also applies to soloed + muted) - if route:muted () then - goto continue - end - - -- at this point the track is either soloed (if at least one track is soloed) - -- or not muted (if no track is soloed) - - -- test if bouncing is possible - local track = route:to_track () - if not track:bounceable (proc, false) then - goto continue - end - - -- only audio tracks - local playlist = track:playlist () - if playlist:data_type ():to_string () ~= "audio" then - goto continue - end - - -- check if there is at least one unmuted region in the loop-range - local reg_unmuted_count = 0 - for reg in playlist:regions_touched (loop:start (), loop:_end ()):iter () do - if not reg:muted() then - reg_unmuted_count = reg_unmuted_count + 1 - end - end - - if reg_unmuted_count < 1 then - goto continue - end - - -- clear existing changes, prepare "diff" of state for undo - playlist:to_stateful ():clear_changes () - - -- do the actual work - local region = track:bounce_range (loop:start (), loop:_end (), itt, proc, false) - playlist:add_region (region, playhead, n_paste, false) - - n_regions_created = n_regions_created + 1 - - -- create a diff of the performed work, add it to the session's undo stack - -- and check if it is not empty - if not Session:add_stateful_diff_command (playlist:to_statefuldestructible ()):empty () then - add_undo = true - end - - ::continue:: - end - - --advance playhead so it's just after the newly added regions - if n_regions_created > 0 then - Session:request_locate((playhead + loop:length() * n_paste),false) - end - - -- all done, commit the combined Undo Operation - if add_undo then - -- the 'nil' Command here mean to use the collected diffs added above - Session:commit_reversible_command (nil) - else - Session:abort_reversible_command () - end - - print ("bounced " .. n_regions_created .. " regions from loop range (" .. loop:length() .. " frames) to playhead @ frame # " .. playhead) - - ::errorout:: -end end diff --git a/scripts/editor_test.lua b/scripts/editor_test.lua deleted file mode 100644 index 323d243d97..0000000000 --- a/scripts/editor_test.lua +++ /dev/null @@ -1,16 +0,0 @@ -ardour { - ["type"] = "EditorAction", - name = "Action Test", - license = "MIT", - author = "Robin Gareus", - email = "robin@gareus.org", - site = "http://gareus.org", - description = [[ An Example Ardour Editor Action Plugin.]] -} - -function factory (params) - return function () - for n in pairs(_G) do print(n) end - print ("----") - end -end diff --git a/scripts/s_fader_automation.lua b/scripts/s_fader_automation.lua index e1ee2876e4..aaac7adfe9 100644 --- a/scripts/s_fader_automation.lua +++ b/scripts/s_fader_automation.lua @@ -1,46 +1,53 @@ -ardour { ["type"] = "Snippet", name = "fader automation" } +ardour { ["type"] = "Snippet", name = "Fader Automation" } function factory () return function () local playhead = Session:transport_frame () local samplerate = Session:nominal_frame_rate () -- get selected tracks - rl = Editor:get_selection().tracks:routelist() + rl = Editor:get_selection ().tracks:routelist () + -- prepare undo operation Session:begin_reversible_command ("Fancy Fade Out") local add_undo = false -- keep track if something has changed - -- iterate over selected tracks - for r in rl:iter() do - local ac = r:amp():gain_control() -- ARDOUR:AutomationControl - local acl = ac:alist() -- ARDOUR:AutomationControlList (state, high-level) - local cl = acl:list() -- Evoral:ControlList (actual events) - ac:set_automation_state(ARDOUR.AutoState.Touch) + -- iterate over selected tracks + for r in rl:iter () do + local ac = r:amp ():gain_control () -- ARDOUR:AutomationControl + local al = ac:alist () -- ARDOUR:AutomationList (state, high-level) + local cl = al:list () -- Evoral:ControlList (actual events) - if cl:isnil() then + if cl:isnil () then goto out end + -- set automation state to "Touch" + ac:set_automation_state (ARDOUR.AutoState.Touch) + -- query the value at the playhead position - local g = cl:eval(playhead) + local g = cl:eval (playhead) -- get state for undo - local before = acl:get_state() + local before = al:get_state () -- delete all events after the playhead... cl:truncate_end (playhead) + -- ...and generate some new ones. for i=0,50 do + -- use a sqrt fade-out (the shape is recognizable, and otherwise + -- not be possible to achieve with existing ardour fade shapes) cl:add (playhead + i * samplerate / 50, - g * (1 - math.sqrt (i / 50)), - false, true) + g * (1 - math.sqrt (i / 50)), + false, true) end + -- remove dense events - cl:thin(20) + cl:thin (20) -- save undo - local after = acl:get_state() - Session:add_command (acl:memento_command(before, after)) + local after = al:get_state () + Session:add_command (al:memento_command (before, after)) add_undo = true ::out:: diff --git a/scripts/s_foreach_track.lua b/scripts/s_foreach_track.lua index 7b5d051eba..c1c6ed8da1 100644 --- a/scripts/s_foreach_track.lua +++ b/scripts/s_foreach_track.lua @@ -1,11 +1,10 @@ -ardour { ["type"] = "Snippet", name = "foreach track" } +ardour { ["type"] = "Snippet", name = "Foreach Track" } function factory () return function () for r in Session:get_tracks():iter() do print (r:name()) -- see http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:Track -- for available methods e.g. - -- r:set_active (true, nil) end end end diff --git a/scripts/s_plugin_automation.lua b/scripts/s_plugin_automation.lua index e69de6662a..daec46aa0c 100644 --- a/scripts/s_plugin_automation.lua +++ b/scripts/s_plugin_automation.lua @@ -1,25 +1,33 @@ -ardour { ["type"] = "Snippet", name = "plugin automation2" } +ardour { ["type"] = "Snippet", name = "Plugin automation" } function factory () return function () + -- query playhead position and session sample-rate local playhead = Session:transport_frame () local samplerate = Session:nominal_frame_rate () + -- get Track/Bus with RID 3 local r = Session:route_by_remote_id(3) - -- get AutomationControList, ControlList and ParameterDescriptor - local acl, cl, pd = ARDOUR.LuaAPI.plugin_automation (r:nth_plugin (0), 0) + -- make sure the track object exists + assert (not r:isnil ()) - if not acl:isnil() then + -- get AutomationList, ControlList and ParameterDescriptor + -- of the first plugin's first parameter + -- see http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:LuaAPI + local al, cl, pd = ARDOUR.LuaAPI.plugin_automation (r:nth_plugin (0), 0) + + if not al:isnil () then print ("Parameter Range", pd.lower, pd.upper) - print ("Current value", cl:eval(playhead)) + print ("Current value", cl:eval (playhead)) -- prepare undo operation Session:begin_reversible_command ("Automatix") - local before = acl:get_state() + -- remember current AutomationList state + local before = al:get_state() -- remove future automation cl:truncate_end (playhead) - -- add new data points after the playhead 1 sec min..max + -- add new data points after the playhead 1 sec, min..max -- without guard-points, but with initial (..., false, true) for i=0,10 do cl:add (playhead + i * samplerate / 10, @@ -28,8 +36,8 @@ function factory () return function () end -- save undo - local after = acl:get_state() - Session:add_command (acl:memento_command(before, after)) + local after = al:get_state() + Session:add_command (al:memento_command(before, after)) Session:commit_reversible_command (nil) end end end diff --git a/scripts/s_selection.lua b/scripts/s_selection.lua new file mode 100644 index 0000000000..1963ac1ec5 --- /dev/null +++ b/scripts/s_selection.lua @@ -0,0 +1,60 @@ +ardour { ["type"] = "Snippet", name = "Editor Selection" } + +function factory () return function () + -- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:Selection + -- the Ardour Selection can include multiple items + -- (regions, tracks, ranges, markers, automation, midi-notes etc) + local sel = Editor:get_selection () + + -- + -- At the point of writing the following data items are available + -- + + -- Range selection, total span of all ranges (0, 0 if no time range is selected) + if sel.time:start () < sel.time:end_frame () then + print ("Total Range:", sel.time:start (), sel.time:end_frame ()) + end + + -- Range selection, individual ranges. + for ar in sel.time:iter () do + -- each of the items is a + -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:AudioRange + print ("Range:", ar.id, ar.start, ar._end) + end + + -- Track/Bus Selection + -- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:TrackSelection + for r in sel.tracks:routelist ():iter () do + -- each of the items is a + -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:Route + print ("Route:", r:name ()) + end + + -- Region selection + -- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:RegionSelection + for r in sel.regions:regionlist ():iter () do + -- each of the items is a + -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOUR:Region + print ("Region:", r:name ()) + end + + -- Markers + -- http://manual.ardour.org/lua-scripting/class_reference/#ArdourUI:MarkerSelection + -- Note: Marker selection is not cleared and currently (Ardour-4.7) points + -- to the most recently selected marker. + for m in sel.markers:iter () do + -- each of the items is a + -- http://manual.ardour.org/lua-scripting/class_reference/#ARDOURUI::ArdourMarker + print ("Marker:", m:name (), m:position(), m:_type()) + end + + ---------------------------------------------------------- + -- The total time extents of all selected regions and ranges + local ok, ext = Editor:get_selection_extents (0, 0) + if ok then + print ("Selection Extents:", ext[1], ext[2]) + else + print ("No region or range is selected") + end + +end end diff --git a/scripts/tomsloop.lua b/scripts/tomsloop.lua new file mode 100644 index 0000000000..f1bca82068 --- /dev/null +++ b/scripts/tomsloop.lua @@ -0,0 +1,127 @@ +ardour { ["type"] = "EditorAction", name = "Tom's Loop", + license = "MIT", + author = "Robin Gareus", + email = "robin@gareus.org", + site = "http://gareus.org", + description = [[Bounce the loop-range of all non muted audio tracks, paste N times at playhead]] +} + +function action_params () + return { ["times"] = { title = "Number of copies to add", default = "1"}, } +end + +function factory (params) return function () + -- get options + local p = params or {} + local n_paste = tonumber (p["times"] or 1) + assert (n_paste > 0) + + local proc = ARDOUR.LuaAPI.nil_proc () -- bounce w/o processing + local itt = ARDOUR.InterThreadInfo () -- bounce progress info (unused) + + local loop = Session:locations ():auto_loop_location () + local playhead = Session:transport_frame () + + -- make sure we have a loop, and the playhead (edit point) is after it + if not loop then + print ("A Loop range must be set.") + goto errorout + end + assert (loop:start () < loop:_end ()) + if loop:_end () >= playhead then + print ("The Playhead (paste point) needs to be after the loop.") + goto errorout + end + + -- prepare undo operation + Session:begin_reversible_command ("Tom's Loop") + local add_undo = false -- keep track if something has changed + + -- prefer solo'ed tracks + local soloed_track_found = false + for route in Session:get_tracks ():iter () do + if route:soloed () then + soloed_track_found = true + break + end + end + + -- count regions that are bounced + local n_regions_created = 0 + + -- loop over all tracks in the session + for route in Session:get_tracks ():iter () do + if soloed_track_found then + -- skip not soloed tracks + if not route:soloed () then + goto continue + end + end + + -- skip muted tracks (also applies to soloed + muted) + if route:muted () then + goto continue + end + + -- at this point the track is either soloed (if at least one track is soloed) + -- or not muted (if no track is soloed) + + -- test if bouncing is possible + local track = route:to_track () + if not track:bounceable (proc, false) then + goto continue + end + + -- only audio tracks + local playlist = track:playlist () + if playlist:data_type ():to_string () ~= "audio" then + goto continue + end + + -- check if there is at least one unmuted region in the loop-range + local reg_unmuted_count = 0 + for reg in playlist:regions_touched (loop:start (), loop:_end ()):iter () do + if not reg:muted() then + reg_unmuted_count = reg_unmuted_count + 1 + end + end + + if reg_unmuted_count < 1 then + goto continue + end + + -- clear existing changes, prepare "diff" of state for undo + playlist:to_stateful ():clear_changes () + + -- do the actual work + local region = track:bounce_range (loop:start (), loop:_end (), itt, proc, false) + playlist:add_region (region, playhead, n_paste, false) + + n_regions_created = n_regions_created + 1 + + -- create a diff of the performed work, add it to the session's undo stack + -- and check if it is not empty + if not Session:add_stateful_diff_command (playlist:to_statefuldestructible ()):empty () then + add_undo = true + end + + ::continue:: + end + + --advance playhead so it's just after the newly added regions + if n_regions_created > 0 then + Session:request_locate((playhead + loop:length() * n_paste),false) + end + + -- all done, commit the combined Undo Operation + if add_undo then + -- the 'nil' Command here mean to use the collected diffs added above + Session:commit_reversible_command (nil) + else + Session:abort_reversible_command () + end + + print ("bounced " .. n_regions_created .. " regions from loop range (" .. loop:length() .. " frames) to playhead @ frame # " .. playhead) + + ::errorout:: +end end -- cgit v1.2.3