For inspiration and reference, here’s a hack that seems to extract some (most?) of the pattern iterator, which is lua code. I’ve also found some other lua code deep inside the API, but it wasn’t as interesting as this.
Click to view contents
tbl = { }
tbl_mt = {
__index = function()
rprint(debug.getinfo(2))
end
}
setmetatable(tbl, tbl_mt)
for k, v in renoise.song().pattern_iterator.lines_in_song(tbl) do
end
Result:
Click to view contents
------------------------------------------------------------------------------
-- make_note_column_iter
local function make_note_column_iter(song, line_iter, visible_columns_only)
assert(type(line_iter) == 'function')
visible_columns_only = visible_columns_only or false
local pos, line = line_iter()
if (pos == nil or line == nil) then
return nil
end
local columns = line.note_columns
local column_count = #columns
if visible_columns_only then
column_count = song.tracks[
pos.track].visible_note_columns
end
-- we start by increasing the column
pos.column = 0
return function()
pos.column = pos.column + 1
if (pos.column <= column_count) then
return pos, columns[pos.column]
end
-- loop until we found a line with visible columns
while true do
pos, line = line_iter()
if (pos == nil or line == nil) then
return nil
end
columns = line.note_columns
column_count = #columns
if visible_columns_only then
column_count = song.tracks[
pos.track].visible_note_columns
end
if (column_count > 0) then
pos.column = 1
return pos, columns[pos.column]
end
end
return nil
end
end
-- make_effect_column_iter
local function make_effect_column_iter(song, line_iter, visible_columns_only)
assert(type(line_iter) == 'function')
visible_columns_only = visible_columns_only or false
local pos, line = line_iter()
if (pos == nil or line == nil) then
return nil
end
local columns = line.effect_columns
local column_count = #columns
if visible_columns_only then
column_count = song.tracks[
pos.track].visible_effect_columns
end
-- we start by increasing the column
pos.column = 0
return function()
pos.column = pos.column + 1
if (pos.column <= column_count) then
return pos, columns[pos.column]
end
-- loop until we found a line with visible columns
while true do
pos, line = line_iter()
if (pos == nil or line == nil) then
return nil
end
columns = line.effect_columns
column_count = #columns
if visible_columns_only then
column_count = song.tracks[
pos.track].visible_effect_columns
end
if (column_count > 0) then
pos.column = 1
return pos, columns[pos.column]
end
end
return nil
end
end
------------------------------------------------------------------------------
-- renoise.PatternIterator:lines_in_song
------------------------------------------------------------------------------
function renoise.PatternIterator:lines_in_song(visible_patterns_only)
visible_patterns_only = visible_patterns_only or true
local pattern_order = {}
if visible_patterns_only then
local pattern_sequence = self.song.sequencer.pattern_sequence
local referenced_patterns = {}
for seq_index, pattern_index in pairs(pattern_sequence) do
if not referenced_patterns[pattern_index] then
referenced_patterns[pattern_index] = true
pattern_order[#pattern_order + 1] = pattern_index
end
end
else
for pattern_index = 1,#self.song.patterns do
pattern_order[#pattern_order + 1] = pattern_index
end
end
local pattern_order_index = 1
local start_pos = { pattern = pattern_order[1], track = 1, line = 1 }
local pos = { pattern = pattern_order[1], track = 1, line = 1 }
local patterns = self.song.patterns
local pattern = patterns[pos.pattern]
local pattern_tracks = pattern.tracks
local pattern_track = pattern_tracks[pos.track]
-- we start by increasing the line
start_pos.line = start_pos.line - 1
pos.line = pos.line - 1
local function line_iter()
pos.line = pos.line + 1
if pos.line > pattern.number_of_lines then
pos.line = 1; pos.track = pos.track + 1
if pos.track > #pattern_tracks then
pos.track = 1; pattern_order_index = pattern_order_index + 1
if pattern_order_index > #pattern_order then
-- completed: reset and stop
pattern_order_index = 1
pos.pattern = start_pos.pattern
pos.track = start_pos.track
pos.line = start_pos.line
pattern = patterns[pos.pattern]
pattern_tracks = pattern.tracks
pattern_track = pattern_tracks[pos.track]
return nil
else
-- new pattern
pos.pattern = pattern_order[pattern_order_index]
pattern = patterns[pos.pattern]
pattern_tracks = pattern.tracks
pattern_track = pattern_tracks[pos.track]
end
else
-- new track
pattern_track = pattern_tracks[pos.track]
end
else
-- new line
end
return pos, pattern_track:line(pos.line)
end
return line_iter, self
end
-- note_columns_in_song
function renoise.PatternIterator:note_columns_in_song(visible_only)
return make_note_column_iter(self.song, self:lines_in_song(
visible_only), visible_only)
end
-- effect_columns_in_song
function renoise.PatternIterator:effect_columns_in_song(visible_only)
return make_effect_column_iter(self.song, self:lines_in_song(
visible_only), visible_only)
end
------------------------------------------------------------------------------
-- renoise.PatternIterator:lines_in_pattern
------------------------------------------------------------------------------
function renoise.PatternIterator:lines_in_pattern(pattern_index)
assert(type(pattern_index) == 'number', ('pattern_index parameter: ' ..
'expected an index (a number), got a \'%s\' object'):format(type(pattern_index)))
local start_pos = { pattern = pattern_index, track = 1, line = 1 }
local pos = { pattern = pattern_index, track = 1, line = 1 }
local pattern = self.song.patterns[pos.pattern]
local pattern_tracks = pattern.tracks
local pattern_track = pattern_tracks[pos.track]
-- we start by increasing the line
start_pos.line = start_pos.line - 1
pos.line = pos.line - 1
local function line_iter()
pos.line = pos.line + 1
if pos.line > pattern.number_of_lines then
pos.line = 1; pos.track = pos.track + 1
if pos.track > #pattern_tracks then
-- completed: reset and stop
pos.track = start_pos.track
pos.line = start_pos.line
pattern_track = pattern_tracks[pos.track]
return nil
else
-- new track
pattern_track = pattern_tracks[pos.track]
end
else
-- new line
end
return pos, pattern_track:line(pos.line)
end
return line_iter, self
end
-- note_columns_in_pattern
function renoise.PatternIterator:note_columns_in_pattern(pattern_index, visible_only)
return make_note_column_iter(self.song, self:lines_in_pattern(
pattern_index), visible_only)
end
-- effect_columns_in_pattern
function renoise.PatternIterator:effect_columns_in_pattern(pattern_index, visible_only)
return make_effect_column_iter(self.song, self:lines_in_pattern(
pattern_index), visible_only)
end
------------------------------------------------------------------------------
-- renoise.PatternIterator:lines_in_track
------------------------------------------------------------------------------
function renoise.PatternIterator:lines_in_track(track_index, visible_patterns_only)
assert(type(track_index) == 'number', ('track_index parameter: ' ..
'expected an index (a number), got a \'%s\' object'):format(type(track_index)))
visible_patterns_only = visible_patterns_only or true
local pattern_order = {}
if visible_patterns_only then
local pattern_sequence = self.song.sequencer.pattern_sequence
local referenced_patterns = {}
for seq_index, pattern_index in pairs(pattern_sequence) do
if not referenced_patterns[pattern_index] then
referenced_patterns[pattern_index] = true
pattern_order[#pattern_order + 1] = pattern_index
end
end
else
for pattern_index = 1,#self.song.patterns do
pattern_order[#pattern_order + 1] = pattern_index
end
end
local pattern_order_index = 1
local start_pos = { pattern = pattern_order[1], track = track_index, line = 1 }
local pos = { pattern = pattern_order[1], track = track_index, line = 1 }
local patterns = self.song.patterns
local pattern = patterns[pos.pattern]
local pattern_tracks = pattern.tracks
local pattern_track = pattern_tracks[pos.track]
-- we start by increasing the line
start_pos.line = start_pos.line - 1
pos.line = pos.line - 1
local function line_iter()
pos.line = pos.line + 1
if pos.line > pattern.number_of_lines then
pos.line = 1; pattern_order_index = pattern_order_index + 1
if pattern_order_index > #pattern_order then
-- completed: reset and stop
pattern_order_index = 1
pos.pattern = start_pos.pattern
pos.line = start_pos.line
pattern = patterns[pos.pattern]
pattern_tracks = pattern.tracks
pattern_track = pattern_tracks[pos.track]
return nil
else
-- new pattern
pos.pattern = pattern_order[pattern_order_index]
pattern = patterns[pos.pattern]
pattern_tracks = pattern.tracks
pattern_track = pattern_tracks[pos.track]
end
else
-- new line
end
return pos, pattern_track:line(pos.line)
end
return line_iter, self
end
-- note_columns_in_track
function renoise.PatternIterator:note_columns_in_track(track_index, visible_only)
return make_note_column_iter(self.song, self:lines_in_track(
track_index, visible_only), visible_only)
end
-- effect_columns_in_track
function renoise.PatternIterator:effect_columns_in_track(track_index, visible_only)
return make_effect_column_iter(self.song, self:lines_in_track(
track_index, visible_only), visible_only)
end
------------------------------------------------------------------------------
-- renoise.PatternIterator:lines_in_pattern_track
------------------------------------------------------------------------------
function renoise.PatternIterator:lines_in_pattern_track(pattern_index, track_index)
assert(type(pattern_index) == 'number', ('pattern_index parameter: ' ..
'expected an index (a number), got a \'%s\' object'):format(type(pattern_index)))
assert(type(track_index) == 'number', ('track_index parameter: ' ..
'expected an index (a number), got a \'%s\' object'):format(type(track_index)))
local start_pos = { pattern = pattern_index, track = track_index, line = 1 }
local pos = { pattern = pattern_index, track = track_index, line = 1 }
local pattern = self.song.patterns[pos.pattern]
local pattern_tracks = pattern.tracks
local pattern_track = pattern_tracks[pos.track]
-- we start by increasing the line
start_pos.line = start_pos.line - 1
pos.line = pos.line - 1
local function line_iter()
pos.line = pos.line + 1
if pos.line > pattern.number_of_lines then
-- completed: reset and stop
pos.line = start_pos.line
return nil
else
-- new line
end
return pos, pattern_track:line(pos.line)
end
return line_iter, self
end
-- note_columns_in_pattern_track
function renoise.PatternIterator:note_columns_in_pattern_track(
pattern_index, track_index, visible_only)
return make_note_column_iter(self.song, self:lines_in_pattern_track(
pattern_index, track_index), visible_only)
end
-- effect_columns_in_pattern_track
function renoise.PatternIterator:effect_columns_in_pattern_track(
pattern_index, track_index, visible_only)
return make_effect_column_iter(self.song, self:lines_in_pattern_track(
pattern_index, track_index), visible_only)
end