Module utils

Miscellaneous utility functions and constants.

This module doesn't need to be explicitly loaded as all functions are automatically available in the rtk namespace when loading rtk.

Undo constants

For use with reaper.Undo_EndBlock2(). (Reference.)

These are global constants.

UNDO_STATE_ALL

All actions

UNDO_STATE_TRACKCFG

Track/master volume/pan/routing, plus routing/hwout envelopes

UNDO_STATE_FX

Track/master fx, including FX envelopes

UNDO_STATE_ITEMS

Track items

UNDO_STATE_MISCCFG

Loop selection, markers, regions, and extensions

UNDO_STATE_FREEZE

Freeze state

UNDO_STATE_TRACKENV

Non-FX envelopes only

UNDO_STATE_FXENV

FX envelopes only

UNDO_STATE_POOLEDENVS

Contents of automation items not position, length, rate etc of automation items, which is part of envelope state

UNDO_STATE_FX_ARA

ARA state

Functions

Synopsis

Functions
rtk.check_reaper_version()

Compares the given major/minor version against the REAPER version

rtk.clamp()

Clamps a value within a range

rtk.clamprel()

A variant of clamp() that supports fractional relative min/max values

rtk.point_in_box()

Determines whether the given point lies within the given rectangle

rtk.point_in_circle()

Determines whether the given point lies within the given circle

rtk.open_url()

Opens the URL in the system-default web browser

rtk.uuid4()

Generates a random UUID4

rtk.file.read()

Returns the contents of the given filename

rtk.file.write()

Writes the given contents to a file

rtk.file.size()

Returns the size in bytes of the given filename

rtk.file.exists()

Checks to see if a filename exists

rtk.clipboard.get()

Gets the contents of the system clipboard

rtk.clipboard.set()

Sets the contents of the system clipboard

rtk.gfx.roundrect()

Draws a rounded rectangle with optional fill on the curent drawing target

rtk.check_reaper_version(major, minor, exact)

Compares the given major/minor version against the REAPER version.

if rtk.check_reaper_version(5, 975) then
    reaper.MB('Sorry, REAPER version 5.975 or later is required', 'Unsupported', 0)
end
Parameters
major (number)

require at least this major version

minor (number)

require at least this minor version, provided the major version is satisfied. 3-digit minor versions are supported -- for example, this function understands that version 5.98 is greater than version 5.975.

exact (bool or nil)

if true, the given version must exactly match the current REAPER version, otherwise any REAPER version greater than or equal to the given version constraints will pass the check.

Return Values
(bool)

true if the REAPER version satisfies the given version constraints, false otherwise.

rtk.clamp(value, min, max)

Clamps a value within a range.

Min and max may be nil, in which case this behaves like math.min or math.max (depending on which is nil).

Parameters
value (number)

the value to clamp within the range

min (number)

the minimum end of the range

max (number)

the maximum end of the range

Return Values
(number)

the value that's clamped to the range (if necessary)

rtk.clamprel(value, min, max)

A variant of clamp() that supports fractional relative min/max values.

For example, if min is 0.5, then it is calculated as 0.5*value before clamping.

Arguments are as with rtk.clamp().

rtk.point_in_box(x, y, bx, by, bw, bh)

Determines whether the given point lies within the given rectangle.

Parameters
x (number)

the x coordinate of the point to test

y (number)

the y coordinate of the point to test

bx (number)

the x coordinate of the box

by (number)

the y coordinate of the box

bw (number)

the width of the box

bh (number)

the height of the box

Return Values
(boolean)

true if the point falls within the box, or false otherwise

rtk.point_in_circle(x, y, cirx, ciry, radius)

Determines whether the given point lies within the given circle.

Parameters
x (number)

the x coordinate of the point to test

y (number)

the y coordinate of the point to test

cirx (number)

the x coordinate of the center of the circle

ciry (number)

the y coordinate of the center of the circle

radius (number)

the radius of the circle in pixels

Return Values
(boolean)

true if the point falls within the circle, or false otherwise

rtk.open_url(url)

Opens the URL in the system-default web browser.

This works on Windows, Mac OS X, and Linux.

Parameters
url (string)

the URL to open

rtk.uuid4()

Generates a random UUID4.

Return Values
(string)

a standard formatted random UUID4

rtk.file.read(fname)

Returns the contents of the given filename.

Parameters
fname (string)

the path to the file to read

Return Values
1. (string or nil)

the contents of the file, or nil if there was an error

2. (string or nil)

an error message if the read failed, otherwise nil if it succeeded

rtk.file.write(fname, contents)

Writes the given contents to a file.

The file is replaced if it exists.

Parameters
fname (string)

the path to the file to write

contents (string)

the data to write to the file

Return Values
(string or nil)

nil if the write succeeded, otherwise will be an error message indicating the reason for failure

rtk.file.size(fname)

Returns the size in bytes of the given filename.

Parameters
fname (string)

the path to the file whose size to check

Return Values
1. (number or nil)

the number of bytes in the file, or nil if there was an error

2. (string or nil)

an error message if the check failed, otherwise nil if it succeeded

rtk.file.exists(fname)

Checks to see if a filename exists.

Parameters
fname (string)

the path to the file to check for existence

Return Values
(boolean)

true if the file exists, or false otherwise

rtk.clipboard.get()

Gets the contents of the system clipboard.

Note

This function requires the SWS extension. It won't raise an error if SWS isn't available, but you can also check rtk.has_sws_extension before calling if you wish.

Return Values
(string or nil)

the contents of the clipboard (which may be the empty string if the clipboard was empty) or nil if the SWS extension wasn't available.

rtk.clipboard.set(data)

Sets the contents of the system clipboard.

Note

This function requires the SWS extension. It won't raise an error if SWS isn't available, but you can also check rtk.has_sws_extension before calling if you wish.

Return Values
(boolean)

false if the SWS extension wasn't available, true otherwise.

rtk.gfx.roundrect(x, y, w, h, r, thickness, aa)

Draws a rounded rectangle with optional fill on the curent drawing target.

Parameters
x (number)

the left edge of the rectangle in pixels

y (number)

the top edge of the rectangle in pixels

w (number)

the width of the rectangle in pixels

h (number)

the height of the rectangle in pixels

r (number)

the radius of the rounded border

thickness (number or nil)

the pixel thickness of the rectangle's border, where 0 means the rectangle will be filled (default 1, which means a non-filled rectangle with a 1 pixel border)

aa (boolean or nil)

whether the edges of the border should be anti-aliased (default true)

Monkey Patches

Several functions are added to native Lua namespaces.

Synopsis

Fields
math.inf

A value representing infinity

Functions
math.round()

Rounds a decimal value to the nearest integer

string.startswith()

Checks if a string starts with the given prefix

string.split()

Splits a string into an array based on the given delimiter

string.strip()

Removes any leading or trailing whitespace from a string

string.hash()

Hashes the string to a 63-bit number

table.tostring()

Converts a table to a printable string

table.fromstring()

Parses a stringified table into an actual Lua table

table.merge()

Merges the fields from one table into another

table.shallow_copy()

Creates a shallow copy of a table

table.keys()

Returns an array of field names (or keys) from the given table

table.values()

Returns an array of field values from the given table

Fields

math.inf

A value representing infinity.

Useful for conditional expressions involving math.min() or math.max(), e.g.

val = math.min(should_clamp and minval or math.inf, val)

Functions

math.round(n)

Rounds a decimal value to the nearest integer.

Fractional values greater than or equal to 0.5 are rounded up, otherwise will be rounded down.

Parameters
n (number)

the value to round

Return Values
(number)

the rounded value

string.startswith(s, prefix, insensitive)

Checks if a string starts with the given prefix.

Example
if line:startswith('--') then
    continue
end
Parameters
s (string)

the string whose prefix to check

prefix (string)

the string to check if s begins with

insensitive (boolean or nil)

whether the test should be case-insensitive (defaults to false)

Return Values
(boolean)

true if the string starts with the prefix, false otherwise

string.split(s, delim, filter)

Splits a string into an array based on the given delimiter.

The delimiter is not included in the array elements.

Example
local line = 'Bob:Smith:42'
local first, last, age = table.unpack(line:split(':'))
Parameters
s (string)

the string to split

delim (string or nil)

the delimiter that separates the parts (defaults to any whitespace character)

filter (bool or nil)

if true, filters out empty string fields from the result (default false)

Return Values
(table)

the individual parts (without the delimiter)

string.strip(s)

Removes any leading or trailing whitespace from a string.

Parameters
s (string)

the string to strip

Return Values
(string)

the string any leading or trailing whitespace removed.

string.hash(s)

Hashes the string to a 63-bit number.

This uses a simple but fast algorithm with reasonably good distribution by Daniel Bernstein called djb2.

Parameters
s (string)

the string to hash

table.tostring(tbl)

Converts a table to a printable string.

This is the reverse of table.fromstring().

Note

Circular references are not handled and will blow the stack, and so this is useful for debugging but not much else.

Parameters
tbl (table)

the table to stringify

Return Values
(string)

the stringified table, e.g. {1, 2, foo='bar', [5]=42}

table.fromstring(str)

Parses a stringified table into an actual Lua table.

This is the reverse of table.tostring().

If the string is not a syntactically valid Lua table, a runtime error will be thrown. You can use rtk.call() to handle it (or of course Lua's native xpcall().

Not safe

The implementation uses Lua's load() which means this is not safe for untrusted data. If you need a proper serialization solution, consider using something like json instead.

Parameters
str (string)

the table represented as a string

Return Values
(table)

the parsed table

table.merge(dst, src)

Merges the fields from one table into another.

Fields that already exist in the destination table will be replaced if they exist in the source.

Example
self.attrs = table.merge(attrs, {
    foo='hello',
    bar='world',
)
Parameters
dst (table)

the table to update

src (table)

the table whose values to copy into dst

Return Values
(table)

returns dst back for convenience, however dst will be modified in place and a new table is not created.

table.shallow_copy(t, merge)

Creates a shallow copy of a table.

A shallow copy is one where the new table has all the same fields as the original table, but any nested tables are not copied and will be referenced in both the original and new table.

Parameters
t (table)

the table to shallow-copy

merge (table or nil)

if not nil, the fields from this table will be merged into the shallow copy (see rtk.merge()).

Return Values
(table)

a new table with the same fields as t plus merge if provided

table.keys(t)

Returns an array of field names (or keys) from the given table.

Order is not deterministic.

Example
local t = {foo=42, bar='hello', baz='world'}
-- Prints {"foo", "bar", "baz"} (or possibly in a different order)
log.info('keys are %s', table.tostring(table.keys(t))
Parameters
t (table)

the table whose keys to return

Return Values
(table)

a new table containing all the field names (or indices) in t

table.values(t)

Returns an array of field values from the given table.

Example
local t = {foo=42, bar='hello', baz='world'}
-- Prints {42, "hello", "world"} (or possibly in a different order)
log.info('values are %s', table.tostring(table.values(t))
Parameters
t (table)

the table whose values to return

Return Values
(table)

a new table containing all the field values in t