Skip to content

Commit

Permalink
update to pdlua 0.12.17
Browse files Browse the repository at this point in the history
  • Loading branch information
porres committed Sep 21, 2024
1 parent 041b504 commit 659d475
Show file tree
Hide file tree
Showing 135 changed files with 5,031 additions and 1,622 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ file(GLOB extra_files
set(lua_resources
${CMAKE_CURRENT_SOURCE_DIR}/Source/Audio/scope3d~.pd_lua
${CMAKE_CURRENT_SOURCE_DIR}/Source/Control/lua/pd.lua
${CMAKE_CURRENT_SOURCE_DIR}/Source/Control/lua/pdx.lua
${CMAKE_CURRENT_SOURCE_DIR}/Source/Control/lua/luadoc/hello.lua
${CMAKE_CURRENT_SOURCE_DIR}/Source/Control/lua/luadoc/hello.pd_lua
)
Expand Down
62 changes: 42 additions & 20 deletions Source/Control/lua/README
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ corresponding subdirectories). Originally written by Claude Heiland-Allen,
pdlua has gone through the hands of a few people over the years, including
mrpeach (maintainer since 2011), zmoelnig a.k.a. umlaeute (loader update,
Debian package), and myself (Arch package, Lua 5.3+ support, Purr Data and
plugdata support, tutorial). Please also check my brief account on the history
of pd-lua below.
plugdata support, pdx.lua live-coding extension, tutorial). Please also check
my brief account on the history of pd-lua below.

Lua 5.4 is highly recommended with the latest version, Lua 5.3 works as
well. Reportedly, Lua 5.2 and even 5.1 still work (at least to some extent),
Expand All @@ -42,9 +42,10 @@ https://agraef.github.io/pd-lua/tutorial/pd-lua-intro.html

This contains a fairly gentle introduction to pdlua, walks you through the
creation of a basic example, and then goes on to cover most major features of
pdlua, including the special facilities for tables, clocks, receivers, and
live-coding, in quite some detail. This will be helpful when embarking on your
own projects, or trying to make sense of the included examples.
pdlua, including the special facilities for tables, clocks, receivers, signal
processing, graphics, and live-coding, in quite some detail. This will be
helpful when embarking on your own projects, or trying to make sense of the
included examples.


History and Credits:
Expand All @@ -66,11 +67,11 @@ in turn was based on the 0.7.3 version of pdlua in Pd's svn repository.

The current version (0.8 and later) is actively maintained by Albert Gräf,
with contributions by Claude Heiland-Allen (Lua 5.4 update, bugfixes),
Alexandre Porres (documentation updates, Deken package), sebshader (relative
path loading), and Timothy Schoen (plugdata compatibility, signal and graphics
support). This is also the version included in Purr Data
(https://github.com/agraef/purr-data) and Timothy Schoen's plugdata
(https://github.com/plugdata-team/plugdata).
Alexandre Porres (documentation updates), sebshader (relative path loading),
Timothy Schoen (plugdata compatibility, signal and graphics support), and Ben
Wesch (Deken tests and uploads on GitHub). This is also the version included
in Purr Data (https://github.com/agraef/purr-data) and Timothy Schoen's
plugdata (https://github.com/plugdata-team/plugdata).

Please file bugs and requests at https://github.com/agraef/pd-lua. I maintain
a lot of packages and thus it may take a while at times, but I look at all the
Expand All @@ -79,17 +80,21 @@ bug reports and pull requests, and try to respond to them eventually. :)

Ready-Made Packages:

The latest vanilla binaries for Ubuntu, Mac and Windows can always be found on
https://github.com/agraef/pd-lua. The same version is also in the Arch
community repository (maintained by dvzrv, thanks David!). Other packages are
available in Debian (maintained by IOhannes Zmölnig) and Deken (maintained by
Alexandre Porres). You can also compile pdlua yourself from source, which
isn't hard to do (see below). Also, both Purr Data and plugdata ship with
pdlua, so no 3rd party package is needed in those environments.
The latest vanilla binaries for Ubuntu, Mac, and Windows can always be found
on https://github.com/agraef/pd-lua (but see below for the Deken package).
Also, both Purr Data and plugdata ship with pdlua, and have it enabled by
default, so no 3rd party package is needed in those environments.

To enable the pdlua loader in Pd after installation, just add `pdlua` to your
startup libraries (after adding its parent directory to Pd's search path if
necessary) and you should be set.
For vanilla Pd, we recommend installing the Deken package (named `pdlua`),
readily available using Pd's `Find externals` menu option. This package was
originally uploaded by Alexandre Porres, but Ben Wesch recently added Deken
tests and uploads to our GitHub workflow, so that the Deken releases are now
automatized and always in sync with the GitHub releases. Thanks, Ben!

pd-lua is also in the Arch repositories (maintained by dvzrv, thanks David!),
and in the Debian repositories (maintained by IOhannes Zmölnig, thanks
umlaeute!). (During busy times, these may trail our releases for a little bit,
but most of the time they will the latest version.)

Mac users please note that the packages I distribute aren't notarized, so on
recent macOS versions you'll have to jump through the usual hoops to make them
Expand All @@ -98,8 +103,25 @@ usually do the trick, but check the internet for up-to-date information on
Gatekeeper for details.


Enabling pdlua:

Again, this step is only necessary with vanilla Pd; both Purr Data and
plugdata have the pdlua loader enabled by default, so it should be ready to go
immediately.

With vanilla Pd, after installing pdlua, the pdlua loader also needs to be
added to your startup libraries, before Pd will recognize any Lua object in
your patches. This only needs to be done once. (Alternatively, you can also
use the `-lib pdlua` option on the Pd command line, or a `declare -lib pdlua`
object in a patch with Lua objects.) To make any of this work, you may also
have to add the parent directory of the `pdlua` folder to Pd's search path if
pdlua was installed in an unusual location.


Compilation Instructions:

You can also compile pdlua yourself from source, which isn't hard to do.

The source should compile out of the box on (at least) Linux, macOS and
Windows, just make sure that you have Lua and Pd installed and run
`make`. pdlua uses pd-lib-builder by Katja Vetter as its build system, please
Expand Down
72 changes: 33 additions & 39 deletions Source/Control/lua/doc/graphics.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
pdlua graphics
===

pdlua's graphics allow you to draw basic vector graphics and receive mouse events on pure-data and plugdata. Drawing functions are prefixed with 'gfx.', and should only be called from within the "paint" function
pdlua's graphics allow you to draw basic vector graphics and receive mouse events on pure-data and plugdata. Drawing functions are prefixed with 'gfx.', and should only be called from within the "paint" function.

You can enable GUI mode by setting the self.gui variable in the constructor, like this:
NOTE: The "paint" method (see below) is required by all pdlua objects which want to utilize the graphics interface. Defining it automatically puts the object into graphics mode in which all graphics routines work as described below.

function yourclass:initialize(sel, atoms)
self.inlets = 1
self.gui = 1
return true
end

Painting:
--------------
You can paint by defining the "paint" function, for example:
You can paint by defining the "paint" function, for example:

function yourclass:paint()
gfx.set_color(250, 200, 240)
gfx.fill_all()
function yourclass:paint(g)
g:set_color(250, 200, 240)
g:fill_all()
end


Expand All @@ -34,45 +29,46 @@ end
API overview
--------------
-- Callback functions you can define
paint() -- Paint callback. This is the only place where you're allowed to call any of the paint functions

pd:Class:mouse_down(x, y) -- Mouse down callback, called when the mouse is clicked
pd:Class:mouse_up(x, y) -- Mouse up callback, called when the mouse button is released
pd:Class:mouse_move(x, y) -- Mouse move callback, called when the mouse is moved while not being down
pd:Class:mouse_drag(x, y) -- Mouse drag callback, called when the mouse is moved while also being down

-- Functions you can call
pd:Class:repaint() -- Request a repaint, after this the "paint" callback will occur

gfx.set_size(w, h) -- Sets the size of the drawing object.
pd:Class:repaint() -- Request a repaint, after this the "paint" callback will occur
pd:Class:paint(g) -- Paint callback, returns a graphics_context object (commonly called g) that you can call these drawing functions on:
g:set_size(w, h) -- Sets the size of the object.
width, height = g:get_size(w, h) -- Gets the size of the object.

gfx.set_color(r, g, b, a=1.0) -- Sets the color for the next drawing operation.
g:set_color(r, g, b, a=1.0) -- Sets the color for the next drawing operation.

gfx.fill_ellipse(x, y, w, h) -- Draws a filled ellipse at the specified position and size.
gfx.stroke_ellipse(x, y, w, h, line_width) -- Draws the outline of an ellipse at the specified position and size.
g:fill_ellipse(x, y, w, h) -- Draws a filled ellipse at the specified position and size.
g:stroke_ellipse(x, y, w, h, line_width) -- Draws the outline of an ellipse at the specified position and size.

gfx.fill_rect(x, y, w, h) -- Draws a filled rectangle at the specified position and size.
gfx.stroke_rect(x, y, w, h, line_width) -- Draws the outline of a rectangle at the specified position and size.
g:fill_rect(x, y, w, h) -- Draws a filled rectangle at the specified position and size.
g:stroke_rect(x, y, w, h, line_width) -- Draws the outline of a rectangle at the specified position and size.

gfx.fill_rounded_rect(x, y, w, h, corner_radius) -- Draws a filled rounded rectangle at the specified position and size.
gfx.troke_rounded_rect(x, y, w, h, corner_radius, line_width) -- Draws the outline of a rounded rectangle at the specified position and size.
g:fill_rounded_rect(x, y, w, h, corner_radius) -- Draws a filled rounded rectangle at the specified position and size.
g:stroke_rounded_rect(x, y, w, h, corner_radius, line_width) -- Draws the outline of a rounded rectangle at the specified position and size.

gfx.draw_line(x1, y1, x2, y2) -- Draws a line between two points.
gfx.draw_text(text, x, y, w, fontsize) -- Draws text at the specified position and size.
g:draw_line(x1, y1, x2, y2) -- Draws a line between two points.
g:draw_text(text, x, y, w, fontsize) -- Draws text at the specified position and size.

gfx.start_path(x, y) -- Initiates a new path at the specified point.
gfx.line_to(x, y) -- Adds a line segment to the current path.
gfx.quad_to(x1, y1, x2, y2) -- Adds a quadratic Bezier curve to the current path.
gfx.cubic_to(x1, y1, x2, y2, x3, y) -- Adds a cubic Bezier curve to the current path.
gfx.close_path() -- Closes the current path.
gfx.stroke_path(line_width) -- Draws the outline of the current path with the specified line width.
gfx.fill_path() -- Fills the current path.
g:fill_all() -- Fills the entire drawing area with the current color. Also will draw an object outline in the style of the host (ie. pure-data or plugdata)

gfx.fill_all() -- Fills the entire drawing area with the current color. Also will draw an object outline in the style of the host (ie. pure-data or plugdata)
g:translate(tx, ty) -- Translates the coordinate system by the specified amounts.
g:scale(sx, sy) -- Scales the coordinate system by the specified factors. This will always happen after the translation
g:reset_transform() -- Resets current scale and translation

gfx.translate(tx, ty) -- Translates the coordinate system by the specified amounts.
gfx.scale(sx, sy) -- Scales the coordinate system by the specified factors. This will always happen after the translation
gfx.reset_transform() -- Resets current scale and translation
p = Path(x, y) -- Initiates a new path at the specified point
p:line_to(x, y) -- Adds a line segment to the path.
p:quad_to(x1, y1, x2, y2) -- Adds a quadratic Bezier curve to the path.
p:cubic_to(x1, y1, x2, y2, x3, y) -- Adds a cubic Bezier curve to the path.
p:close_path() -- Closes the path.

g:stroke_path(p, line_width) -- Draws the outline of the path with the specified line width.
g:fill_path(p) -- Fills the current path.

Basic example
---------------------
Expand All @@ -85,8 +81,6 @@ function example:initialize(sel, atoms)
self.circle_x = 10
self.circle_y = 10

-- Enabled GUI mode
self.gui = 1
return true
end

Expand All @@ -97,7 +91,7 @@ function example:mouse_drag(x, y)
self.circle_y = y - 15

-- Request a repaint
self:repaint()
self:repaint()
end

function example:paint()
Expand All @@ -108,4 +102,4 @@ function example:paint()
-- Draw an ellipse
gfx.set_color(0, 255, 0, 1)
gfx.fill_ellipse(self.circle_x, self.circle_y, 30, 30)
end
end
4 changes: 2 additions & 2 deletions Source/Control/lua/lua/lapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,9 +417,9 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
o = index2value(L, idx); /* previous call may reallocate the stack */
}
if (len != NULL)
*len = vslen(o);
*len = tsslen(tsvalue(o));
lua_unlock(L);
return svalue(o);
return getstr(tsvalue(o));
}


Expand Down
28 changes: 21 additions & 7 deletions Source/Control/lua/lua/lauxlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) {
int top = lua_gettop(L);
lua_getinfo(L, "f", ar); /* push function */
lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE);
luaL_checkstack(L, 6, "not enough stack"); /* slots for 'findfield' */
if (findfield(L, top + 1, 2)) {
const char *name = lua_tostring(L, -1);
if (strncmp(name, LUA_GNAME ".", 3) == 0) { /* name start with '_G.'? */
Expand Down Expand Up @@ -249,11 +250,13 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
return 1;
}
else {
const char *msg;
luaL_pushfail(L);
msg = (en != 0) ? strerror(en) : "(no extra info)";
if (fname)
lua_pushfstring(L, "%s: %s", fname, strerror(en));
lua_pushfstring(L, "%s: %s", fname, msg);
else
lua_pushstring(L, strerror(en));
lua_pushstring(L, msg);
lua_pushinteger(L, en);
return 3;
}
Expand Down Expand Up @@ -732,9 +735,12 @@ static const char *getF (lua_State *L, void *ud, size_t *size) {


static int errfile (lua_State *L, const char *what, int fnameindex) {
const char *serr = strerror(errno);
int err = errno;
const char *filename = lua_tostring(L, fnameindex) + 1;
lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
if (err != 0)
lua_pushfstring(L, "cannot %s %s: %s", what, filename, strerror(err));
else
lua_pushfstring(L, "cannot %s %s", what, filename);
lua_remove(L, fnameindex);
return LUA_ERRFILE;
}
Expand Down Expand Up @@ -787,6 +793,7 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
}
else {
lua_pushfstring(L, "@%s", filename);
errno = 0;
lf.f = fopen(filename, "r");
if (lf.f == NULL) return errfile(L, "open", fnameindex);
}
Expand All @@ -796,13 +803,15 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename,
if (c == LUA_SIGNATURE[0]) { /* binary file? */
lf.n = 0; /* remove possible newline */
if (filename) { /* "real" file? */
errno = 0;
lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
if (lf.f == NULL) return errfile(L, "reopen", fnameindex);
skipcomment(lf.f, &c); /* re-read initial portion */
}
}
if (c != EOF)
lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */
errno = 0;
status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode);
readstatus = ferror(lf.f);
if (filename) fclose(lf.f); /* close file (even in case of errors) */
Expand Down Expand Up @@ -933,7 +942,7 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
luaL_checkstack(L, nup, "too many upvalues");
for (; l->name != NULL; l++) { /* fill the table with given functions */
if (l->func == NULL) /* place holder? */
if (l->func == NULL) /* placeholder? */
lua_pushboolean(L, 0);
else {
int i;
Expand Down Expand Up @@ -1025,9 +1034,14 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
}


/*
** Standard panic funcion just prints an error message. The test
** with 'lua_type' avoids possible memory errors in 'lua_tostring'.
*/
static int panic (lua_State *L) {
const char *msg = lua_tostring(L, -1);
if (msg == NULL) msg = "error object is not a string";
const char *msg = (lua_type(L, -1) == LUA_TSTRING)
? lua_tostring(L, -1)
: "error object is not a string";
lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n",
msg);
return 0; /* return to Lua to abort */
Expand Down
Loading

0 comments on commit 659d475

Please sign in to comment.