Renoise 3.1: Changes from Lua API version 4 to 5

Mostly adding the internal new features to the Lua API as well, but there are also little other new things here and there. Here’s the complete list of changes:

--[[============================================================================
Renoise.API
============================================================================]]--
 
"--- Changed:"
 
renoise.API_VERSION = 5
 
 
--[[============================================================================
Renoise.ScriptingTool.API
============================================================================]]--
 
 
"--- New:"
 
Menu Entries: new "Phrase Grid" category
 
 
--[[============================================================================
Renoise.ViewBuilder.API
============================================================================]]--
 
--------------------------------------------------------------------------------
-- renoise.Views.TextField
--------------------------------------------------------------------------------
 
"--- New:"
 
-- When false, text is displayed but can not be entered/modified by the user.
-- By default true.
textfield.active
  -> [boolean]
 
 
--------------------------------------------------------------------------------
-- renoise.Views.MultilineTextField
--------------------------------------------------------------------------------
 
"--- New:"
 
-- When false, text is displayed but can not be entered/modified by the user.
-- By default true.
multiline_textfield.active
  -> [boolean]
 
 
--[[============================================================================
Renoise.Document.API
============================================================================]]--
 
--------------------------------------------------------------------------------
-- renoise.Document.ObservableBang (inherits Observable) (new class)
--------------------------------------------------------------------------------
 
"--- New:"
 
-- Observable without a value which sends out notifications when "banging" it.
 
-------- Functions
 
-- fire a notification, calling all registered notifiers.
observable:bang()
 
 
--[[============================================================================
Renoise.Application.API
============================================================================]]--
 
"--- Removed":
 
renoise.MIDDLE_FRAME_INSTRUMENT_SAMPLE_OVERVIEW
 
 
"--- New":
 
-- Load a file into the currently selected components (selected instrument,
-- track, sample, ...) of the song. If no component is selected it will be 
-- created when possible. Any errors during the export are shown to the user. 
-- returns success.
renoise.app():load_track_device_chain(filename) 
  -> [boolean]
renoise.app():load_track_device_preset(filename) 
  -> [boolean]
renoise.app():load_instrument(filename)
  -> [boolean]
renoise.app():load_instrument_multi_sample(filename)
  -> [boolean]
renoise.app():load_instrument_device_chain(filename)
  -> [boolean]
renoise.app():load_instrument_device_preset(filename)
  -> [boolean]
renoise.app():load_instrument_modulation_set(filename)
  -> [boolean]
renoise.app():load_instrument_phrase(filename)
  -> [boolean]
renoise.app():load_instrument_sample(filename)
  -> [boolean]
renoise.app():load_theme(filename)
 
-- Save a currently selected components of the song. Any errors
-- during the export are shown to the user. returns success
renoise.app():save_track_device_chain(filename) 
  -> [boolean]
renoise.app():save_instrument(filename)
  -> [boolean]
renoise.app():save_instrument_multi_sample(filename)
  -> [boolean]
renoise.app():save_instrument_device_chain(filename)
  -> [boolean]
renoise.app():save_instrument_modulation_set(filename)
  -> [boolean]
renoise.app():save_instrument_phrase(filename)
  -> [boolean]
renoise.app():save_instrument_sample(filename)
  -> [boolean]
renoise.app():save_theme(filename)
 
 
--[[============================================================================
renoise.Song.API
============================================================================]]--
 
--------------------------------------------------------------------------------
-- renoise.Song
--------------------------------------------------------------------------------
 
"--- Removed:"
 
-- use new renoise.song().selected_automation_parameter instead
renoise.song().selected_parameter_index
  -> [read-only, number or 0 (when no parameter is selected)]
renoise.song().selected_track_parameter_index
  -> [read-only, number or 0 (when no parameter is selected)]
 
 
"--- Changed:"
 
-- sample_rate: can be one of 22050, 44100, 48000, 88200, 96000, 192000.
renoise.song():render([options,] filename, rendering_done_callback)
  -> [boolean, error_message or nil]
 
-- DEPRECATED - alias for new 'selected_automation_parameter' property
renoise.song().selected_parameter, _observable
  -> [renoise.DeviceParameter object or nil]
 
 
"--- New:"
 
renoise.Song.SUB_COLUMN_SAMPLE_EFFECT_NUMBER
renoise.Song.SUB_COLUMN_SAMPLE_EFFECT_AMOUNT
 
-- Selected parameter in the automation editor. Can be nil.
-- When setting a new parameter, parameter must be automateable and 
-- must be one of the currently selected track device chain.
renoise.song().selected_automation_parameter, _observable
  -> [renoise.DeviceParameter object or nil]
-- parent device of 'selected_automation_parameter'. not settable.
renoise.song().selected_automation_device, _observable
  -> [renoise.AudioDevice object or nil]
 
-- same as 'selection_in_pattern' but for the currently selected phrase (if any).
-- there are no tracks in phrases, so only 'line' and 'column' fields are valid.
renoise.song().selection_in_phrase
  -> [table of start/end values or nil]
 
 
--------------------------------------------------------------------------------
-- renoise.Track
--------------------------------------------------------------------------------
 
"--- Removed:"
 
-- now is renoise.song().tracks[]:set_column_is_muted(column, muted)
renoise.song().tracks[]:mute_column(column, muted) before
 
 
"--- New:"
 
-- Note column mutes. Only valid within (1-track.max_note_columns)
renoise.song().tracks[]:set_column_is_muted(column, muted)
 
-- Note column names. Only valid within (1-track.max_note_columns)
renoise.song().tracks[]:column_name(column)
  -> [string]
renoise.song().tracks[]:column_name_observable(column)
  -> [Observable object]
renoise.song().tracks[]:set_column_name(column, name)

-- Swap the positions of two note or effect columns within a track.
renoise.song().tracks[]:swap_note_columns_at(index1, index2)
renoise.song().tracks[]:swap_effect_columns_at(index1, index2)

-- Set new "local" effect column visibility in pattern tracks
renoise.song().tracks[].sample_effects_column_visible, _observable
  -> [boolean]
 
 
--------------------------------------------------------------------------------
-- renoise.AudioDevice
--------------------------------------------------------------------------------
 
"--- New:"
 
-- Access to the "is_active" parameter of a device
renoise.song().tracks[].devices[].is_active_parameter
  -> [read-only, renoise.DeviceParameter object]
 
 
--------------------------------------------------------------------------------
-- renoise.Instrument
--------------------------------------------------------------------------------
 
"--- Removed:"
 
-- see new "can_insert_phrase_mapping_at(index)"
renoise.song().instruments[]:can_insert_phrase_at(index) 
  -> [boolean]
 
-- Instruments tag list - gone.
renoise.song().instruments[].tags[], _observable
  -> [array of strings]
-- Notifier is called as soon as any paragraph in the tags changed.
renoise.song().tags_assignment_observable
  -> [renoise.Observable object]
 
-- see new "renoise.song().instruments[].phrase_playback_mode, _observable"
renoise.song().instruments[].phrase_playback_enabled, _observable
 -> [boolean]
 
 
"--- Changed:"
 
-- Insert a new phrase behind the given phrase index (1 for the first one).
-- No more mapping checks needed.
renoise.song().instruments[]:insert_phrase_at(index) 
  -> [returns newly created renoise.InstrumentPhrase]
-- Delete a new phrase at the given phrase index.
renoise.song().instruments[]:delete_phrase_at(index)
  
 
"--- New:"
 
-- new phrase playback modes
renoise.Instrument.PHRASES_OFF
renoise.Instrument.PHRASES_PLAY_SELECTIVE
renoise.Instrument.PHRASES_PLAY_KEYMAP
 
renoise.Instrument.MAX_NUMBER_OF_PHRASES
 
-- Returns true if a new phrase mapping can be inserted at the given 
-- phrase mapping index (see See renoise.song().instruments[].phrase_mappings). 
-- Passed phrase must exist and must not have a mapping yet.
-- Phrase note mappings may not overlap and are sorted by note, so there
-- can be max 119 phrases per instrument when each phrase is mapped to
-- a single key only. To make up room for new phrases, access phrases by 
-- index, adjust their note_range, then call 'insert_phrase_mapping_at' again.
renoise.song().instruments[]:can_insert_phrase_mapping_at(index) 
  -> [boolean]
-- Insert a new phrase mapping behind the given phrase mapping index.
-- The new phrase mapping will by default use the entire free (note) range 
-- between the previous and next phrase (if any). To adjust the note range 
-- of the new phrase change its 'new_phrase_mapping.note_range' property. 
renoise.song().instruments[]:insert_phrase_mapping_at(index, phrase) 
  -> [returns newly created renoise.InstrumentPhraseMapping]
-- Delete a new phrase mapping at the given phrase mapping index.
renoise.song().instruments[]:delete_phrase_mapping_at(index)
 
-- Set this to true to show the comments dialog after loading a song
renoise.song().instruments[].show_comments_after_loading, _observable 
  -> [boolean]
 
-- Access the MIDI pitch-bend macro
renoise.song().instruments[].pitchbend_macro 
 -> [returns renoise.InstrumentMacro]
-- Access the MIDI modulation-wheel macro
renoise.song().instruments[].modulation_wheel_macro 
 -> [returns renoise.InstrumentMacro]
-- Access the MIDI channel pressure macro
renoise.song().instruments[].channel_pressure_macro 
 -> [returns renoise.InstrumentMacro]
 
 
-- Phrase playback mode. See PHRASES_XXX values.
renoise.song().instruments[].phrase_playback_mode, _observable
 -> [enum=PHRASES]
-- Phrase program: 0 = Off, 1-126 = specific phrase, 127 = keymap.
renoise.song().instruments[].phrase_program, _observable
 -> [number]
 
 
--------------------------------------------------------------------------------
-- renoise.InstrumentTriggerOptions
--------------------------------------------------------------------------------
 
"--- Removed:"
 
-- Hold mode - gone.
renoise.song().instruments[].trigger_options.hold, _observable
  -> [boolean]
 
 
"--- New:"
 
-- Glide amount when monophonic. 0 == off, 255 = instant
renoise.song().instruments[].trigger_options.monophonic_glide, _observable
  -> [number]
 
 
--------------------------------------------------------------------------------
-- renoise.InstrumentPhrase
--------------------------------------------------------------------------------
 
"--- New:"
 
-- See InstrumentPhraseMapping KEY_TRACKING
renoise.InstrumentPhrase.KEY_TRACKING_NONE
renoise.InstrumentPhrase.KEY_TRACKING_TRANSPOSE
renoise.InstrumentPhrase.KEY_TRACKING_OFFSET
 
-- Note column mute states. Only valid within (1-MAX_NUMBER_OF_NOTE_COLUMNS)
renoise.song().tracks[]:column_is_muted(column)
  -> [boolean]
renoise.song().tracks[]:column_is_muted_observable(column)
  -> [Observable object]
renoise.song().tracks[]:set_column_is_muted(column, muted)
 
-- Note column names. Only valid within (1-MAX_NUMBER_OF_NOTE_COLUMNS)
renoise.song().tracks[]:column_name(column)
  -> [string]
renoise.song().tracks[]:column_name_observable(column)
  -> [Observable object]
renoise.song().tracks[]:set_column_name(column, name)
 
-- Swap the positions of two note of effect columns within a phrase.
renoise.song().instruments[].phrases[]:swap_note_columns_at(index1, index2)
renoise.song().instruments[].phrases[]:swap_effect_columns_at(index1, index2)
 
-- Phrases key-tracking mode.
renoise.song().instruments[].phrases[].key_tracking, _observable 
  -> [enum = KEY_TRACKING]
 
-- Phrases base-note. Only relevant when key_tracking is set to transpose.
renoise.song().instruments[].phrases[].base_note, _observable 
  -> [number, 0-119, c-4=48]
 
-- Loop mode. The phrase plays as one-shot when disabled.
renoise.song().instruments[].phrases[].looping, _observable 
  -> [boolean]
 
-- Loop start. Playback will start from the beginning before entering loop
renoise.song().instruments[].phrases[].loop_start, _observable 
  -> [number, 1-number_of_lines]
-- Loop end. Needs to be > loop_start and <= number_of_lines
renoise.song().instruments[].phrases[].loop_end, _observable 
  -> [number, loop_start-number_of_lines]
 
-- Shuffle groove amount for a phrase. 
-- 0.0 = no shuffle (off), 1.0 = full shuffle 
renoise.song().instruments[].phrase.shuffle_amount
  -> [number, 0-1]
 
-- Column visibility.
renoise.song().instruments[].phrases[].instrument_column_visible, _observable
  -> [boolean]
renoise.song().instruments[].phrases[].sample_effects_column_visible, _observable 
  -> [boolean]
 
 
--------------------------------------------------------------------------------
-- renoise.InstrumentPhraseMapping
--------------------------------------------------------------------------------
 
"--- New:"
 
renoise.song().instruments[].phrases[].mapping.loop_start, _observable 
  -> [number]
renoise.song().instruments[].phrases[].mapping.loop_end, _observable 
  -> [number]
 
 
--------------------------------------------------------------------------------
-- renoise.SampleModulationDevice
--------------------------------------------------------------------------------
 
"--- New:"
 
renoise.SampleModulationDevice.TARGET_DRIVE
 
 
--------------------------------------------------------------------------------
-- renoise.SampleEnvelopeModulationDevice
--------------------------------------------------------------------------------
 
"--- New:"
 
-- Remove points in the given [from, to) time range from the envelope.
renoise.song().instruments[].sample_modulation_sets[].devices[]:clear_points_in_range(
-- from_time, to_time)
 
 
--------------------------------------------------------------------------------
-- renoise.SampleStepperModulationDevice (new class)
--------------------------------------------------------------------------------
 
"--- New:"
 
--------- Constants
 
renoise.SampleStepperModulationDevice.PLAYMODE_POINTS
renoise.SampleStepperModulationDevice.PLAYMODE_LINEAR
renoise.SampleStepperModulationDevice.PLAYMODE_CUBIC
 
renoise.SampleStepperModulationDevice.MIN_NUMBER_OF_POINTS
renoise.SampleStepperModulationDevice.MAX_NUMBER_OF_POINTS
 
 
-------- Functions
 
-- Reset the envelope back to its default initial state.
renoise.song().instruments[].sample_modulation_sets[].devices[]:init()
 
-- Copy all properties from another SampleStepperModulation object.
renoise.song().instruments[].sample_modulation_sets[].devices[]:copy_from(
  other renoise.SampleStepperModulationDevice object)
 
-- Remove all points from the envelope.
renoise.song().instruments[].sample_modulation_sets[].devices[]:clear_points()
-- Remove points in the given [from, to) time range from the envelope.
renoise.song().instruments[].sample_modulation_sets[].devices[]:clear_points_in_range(
-- from_time, to_time)
 
-- Copy all points from another SampleStepperModulation object.
renoise.song().instruments[].sample_modulation_sets[].devices[]:copy_points_from(
  other SampleStepperModulationDevice object)
 
-- Test if a point exists at the given time.
renoise.song().instruments[].sample_modulation_sets[].devices[]:has_point_at(time)
  -> [boolean]
-- Add a new point value (or replace any existing value) at time. 
renoise.song().instruments[].sample_modulation_sets[].devices[]:add_point_at(time, value)
-- Removes a point at the given time. Point must exist.
renoise.song().instruments[].sample_modulation_sets[].devices[]:remove_point_at(time)
 
 
-------- Properties
 
-- Play mode (interpolation mode).
renoise.song().instruments[].sample_modulation_sets[].devices[].play_mode, _observable
  -> [enum = PLAYMODE]
 
-- Step size. -1 is the same as choosing RANDOM
renoise.song().instruments[].sample_modulation_sets[].devices[].play_step, _observable
  -> [number, -1-16]
 
-- Envelope length.
renoise.song().instruments[].sample_modulation_sets[].devices[].length, _observable
  -> [number, 1-256]
 
-- Get all points of the envelope. When setting a new list of points,
-- items may be unsorted by time, but there may not be multiple points
-- for the same time. Returns a copy of the list, so changing
-- `points[1].value` will not do anything. Instead, change them via
-- `points = { something }`.
renoise.song().instruments[].sample_modulation_sets[].devices[].points[], _observable
  -> [array of {time, value} tables]
 
-- An envelope points time.
renoise.song().instruments[].sample_modulation_sets[].devices[].points[].time
  -> [number, 1-envelope.length]
-- An envelope points value.
renoise.song().instruments[].sample_modulation_sets[].devices[].points[].value
  -> [number, 0.0-1.0]
 
 
--------------------------------------------------------------------------------
-- renoise.SampleModulationSet
--------------------------------------------------------------------------------
 
"--- Removed:"
 
all renoise.SampleModulationSet.FILTER_XXX constants
 
 
"--- Changed:"
 
-- was an enum, is a string now
renoise.song().instruments[].sample_modulation_sets[]:filter_type, _observable
  -> [string, one of 'available_filter_types']
 
 
"--- New:"
 
 -- upgrade filter type to the latest version. Tries to find a somewhat matching
 -- filter in the new version, but things quite likely wont sound the same.
renoise.song().instruments[].sample_modulation_sets[]:upgrade_filter_version()
 
 
-- Input value for the volume domain
renoise.song().instruments[].sample_modulation_sets[].volume_input
  -> [renoise.DeviceParameter object]
 
-- Input value for the panning domain
renoise.song().instruments[].sample_modulation_sets[].panning_input
  -> [renoise.DeviceParameter object]
 
-- Input value for the pitch domain
renoise.song().instruments[].sample_modulation_sets[].pitch_input
  -> [renoise.DeviceParameter object]
 
-- Input value for the cutoff domain
renoise.song().instruments[].sample_modulation_sets[].cutoff_input
  -> [renoise.DeviceParameter object]
 
-- Input value for the resonance domain
renoise.song().instruments[].sample_modulation_sets[].resonance_input
  -> [renoise.DeviceParameter object]
 
-- Input value for the drive domain
renoise.song().instruments[].sample_modulation_sets[].drive_input
  -> [renoise.DeviceParameter object]
 
-- Pitch range in semitones
renoise.song().instruments[].sample_modulation_sets[].pitch_range, _observable 
  -> [number, 1 - 96]  
 
 
-- Filter version. See also function 'upgrade_filter_version'
renoise.song().instruments[].sample_modulation_sets[].filter_version, observable
  -> [read-only, number - 1,2 or 3 which is the latest version]
 
-- Filter type.
renoise.song().instruments[].sample_modulation_sets[].available_filter_types
  -> [read-only, list of strings]
 
 
--------------------------------------------------------------------------------
-- renoise.InstrumentPluginProperties
--------------------------------------------------------------------------------
 
"--- New:"
 
-- Valid for loaded and unloaded plugins. target instrument index or 0 of the 
-- plugins MIDI output (when present)
renoise.song().instruments[].plugin_properties.midi_output_routing_index 
  -> [read-only, number. 0 when no routing is set]
  
 
 
--------------------------------------------------------------------------------
-- renoise.Sample
--------------------------------------------------------------------------------
 
"--- Changed:"
 
-- max was 8, is now 15
renoise.song().instruments[].samples[].mute_group, _observable 
  -> [number, 0-15 with 0=none]
 
 
"--- New:"
 
renoise.song().instruments[].samples[].oversample_enabled, _observable 
  -> [boolean]
 
 
--------------------------------------------------------------------------------
-- renoise.PatternTrackAutomation
--------------------------------------------------------------------------------
 
"--- New:"
 
-- Remove all existing points in the given [from, to) time range from the 
-- automation.
renoise.song().patterns[].tracks[].automation[]:clear_range(from_time, to_time)
 
-- Selection range as visible in the automation editor. always valid. 
-- returns the automation range no selection is present in the UI.
renoise.song().patterns[].tracks[].automation[].selection_start, _observable
  -> [number >= 1 <= automation.length+1]
renoise.song().patterns[].tracks[].automation[].selection_end, _observable
  -> [number >= 1 <= automation.length+1]
-- Get or set selection range. when setting an empty table, the existing 
-- selection, if any, will be cleared.
renoise.song().patterns[].tracks[].automation[].selection_range[], _observable
  -> [array of two numbers, 1-automation.length+1]
 
 
--------------------------------------------------------------------------------
-- renoise.NoteColumn
--------------------------------------------------------------------------------
 
"--- New:"
 
renoise.song().patterns[].tracks[].lines[].note_columns[].effect_number_value
  -> [int, 0-65535 in the form 0x0000xxyy where xx=effect char 1 and yy=effect char 2]
song().patterns[].tracks[].lines[].note_columns[].effect_number_string
  -> [string, '00' - 'ZZ']
 
renoise.song().patterns[].tracks[].lines[].note_columns[].effect_amount_value 
  -> [int, 0-255]
renoise.song().patterns[].tracks[].lines[].note_columns[].effect_amount_string
  -> [string, '00' - 'FF']

renoise.app():load_track_device_chain(filename) etc. yay
observable:bang() yay? i think
renoise.song().tracks[].devices[].is_active_parameter yay
renoise.song().instruments[].macro yay
:clear_points_in_range yay
sample_modulation_sets[].volume_input yay
automation[].selection_range[] yay

would be really nice to have automation[].cursor_pos

How do I read/write the note column name? Could not find it in the list above.

renoise.song().selected_automation_parameter

can now be set, big yay!

5995 automation2.PNG

How do I read/write the note column name? Could not find it in the list above.

Forgot those guys. Will add it to the next beta.

Forgot those guys. Will add it to the next beta.

Cool

It is possible to append device chains, too, in renoise… Can we have this in lua, too, please? Like
renoise.app():append_track_device_chain(filename) or LOADING_MODE etc.

Can you give access to the function play current line a.k.a. Pressing return?

Thx

It is possible to append device chains, too, in renoise… Can we have this in lua, too, please? Like
renoise.app():append_track_device_chain(filename) or LOADING_MODE etc

It’s the same function, so if you have it set in the menu to append the current chain, it will.

It’s the same function, so if you have it set in the menu to append the current chain, it will.

Oh ok thx. But then, wouldn’t it be practical if you can at least read this option, if a tool requires appending?

The tools page needs a little update to accept API V5, it displays as unknown currently.

The tools page needs a little update to accept API V5, it displays as unknown currently.

Yup, will do that today. Done.

New in Beta3:

-- parent device of 'selected_automation_parameter'. not settable.
renoise.song().selected_automation_device, _observable
-> [renoise.AudioDevice object or nil]

Should line 488 be?

renoise.song().instruments[].sample_modulation_sets[].filter_type, _observable

[Edit: Corrected documentation]

Should it be?

renoise.song().instruments[].sample_modulation_sets[].filter_type, _observable

Yup.

renoise.app():load_instrument(filename)

This function doesn’t load sfz files. Would it be possible to add this? So we could write quick and dirty sfz2rni converters.

renoise.app():load_instrument(filename)

This function doesn’t load sfz files. Would it be possible to add this? So we could write quick and dirty sfz2rni converters.

renoise.app():load_instrument_multi_sample(filename)
-> [boolean]

will.

Thx taktik, works great:

https://gist.github.com/ryrun/a1e9be02a000bf978bbd

Is it possible to raise the limit forrenoise.app():prompt_for_multiple_filenames_to_read?

New in Beta3:

-- parent device of 'selected_automation_parameter'. not settable.
renoise.song().selected_automation_device, _observable
-> [renoise.AudioDevice object or nil]

Quick snippet to get the index too using rawequal(). Might need some extra nil checks too.

function get_selected_automation_device_index() 

  local song = renoise.song()
  
  --loop devices of selected track
  for device = 1,#song.selected_track.devices do
    --see which track device matches the selected_automation_device and return its index
    if rawequal(song.selected_automation_device,song.selected_track:device(device)) ~= false then
      return device
    end
  end
      
  --no match found so return nil
  return nil
end

Could be great if we can read selected_track_device.preset_name in order to search a specific device though the whole song by it’s preset name but i could have missed it…

Anyway, thanks for the new loading file function, that will be really helpful.

Kaneton: We can, just not like that, oprint renoise.song().seleted_track_device