Skip to content

Commit

Permalink
Added a more reliable way to get script path, added _reload method to…
Browse files Browse the repository at this point in the history
… reload any object dynamically
  • Loading branch information
timothyschoen committed Dec 22, 2023
1 parent d2b7ddd commit 1bea6f1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
24 changes: 24 additions & 0 deletions pd.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pd._objects = { }
pd._clocks = { }
pd._receives = { }
pd._loadpath = ""
pd._fullpath = ""

-- add a path to Lua's "require" search paths
pd._setrequirepath = function(path)
Expand Down Expand Up @@ -119,6 +120,14 @@ pd._whoami = function (object)
end
end

--whoami method dispatcher
pd._whereami = function (object)
if nil ~= pd._objects[object] then
return pd._objects[object]._fullpath
end
end


--class method dispatcher
pd._get_class = function (object)
if nil ~= pd._objects[object] then
Expand Down Expand Up @@ -295,6 +304,13 @@ function pd.Class:register(name)
self._class = pd._register(name) -- register new class
self._name = name
self._loadpath = fullpath

if pd._fullpath == nil or pd._fullpath == '' then
self._fullpath = fullname .. ".pd_lua"
else
self._fullpath = self._currentpath
end

if name == "pdlua" then
self._scriptname = "pd.lua"
else
Expand Down Expand Up @@ -385,7 +401,9 @@ function pd.Class:dofilex(file)
local pathsave = pd._loadpath
pd._loadname = nil
pd._loadpath = self._loadpath
pd._fullpath = file
local f, path = pd._dofilex(self._class, file)
pd._fullpath = = nil
pd._loadname = namesave
pd._loadpath = pathsave
return f, path
Expand All @@ -399,7 +417,9 @@ function pd.Class:dofile(file)
local pathsave = pd._loadpath
pd._loadname = nil
pd._loadpath = self._loadpath
pd._fullpath = file
local f, path = pd._dofile(self._object, file)
pd._fullpath = = nil
pd._loadname = namesave
pd._loadpath = pathsave
return f, path
Expand All @@ -413,6 +433,10 @@ function pd.Class:whoami()
return self._scriptname or self._name
end

function pd.Class:in_1_reload()
return self:dofile(self._fullpath)
end

function pd.Class:get_class() -- accessor for t_class*
return self._class or nil
end
Expand Down
34 changes: 32 additions & 2 deletions pdlua.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,11 @@ static int pdlua_click(t_gobj *z, t_glist *gl, int xpos, int ypos, int shift, in
}


static void pdlua_reload(t_gobj* z)
{
pdlua_dispatch((t_pdlua *)z, 0, gensym("_reload"), 0, NULL);
}

static void pdlua_displace(t_gobj *z, t_glist *glist, int dx, int dy){
t_pdlua *x = (t_pdlua *)z;
x->pd.te_xpix += dx, x->pd.te_ypix += dy;
Expand Down Expand Up @@ -747,6 +752,28 @@ void plugdata_forward_message(void* x, t_symbol *s, int argc, t_atom *argv);
/** Here we find the lua code for the object and open it in an editor */
static void pdlua_menu_open(t_pdlua *o)
{
#if PLUGDATA
lua_getglobal(__L, "pd");
lua_getfield(__L, -1, "_whereami");
lua_pushstring(__L, o->pd.te_pd->c_name->s_name);

if (lua_pcall(__L, 1, 1, 0))
{
pd_error(NULL, "lua: error in whereami:\n%s", lua_tostring(__L, -1));
lua_pop(__L, 2); /* pop the error string and the global "pd" */
return;
}
if(lua_isstring(__L, -1)) {
const char* fullpath = luaL_checkstring(__L, -1);
if(fullpath) {
t_atom arg;
SETSYMBOL(&arg, gensym(fullpath));
plugdata_forward_message(o, gensym("open_textfile"), 1, &arg);
}
return;
}
#endif

const char *name;
const char *path;
char pathname[FILENAME_MAX];
Expand Down Expand Up @@ -842,9 +869,12 @@ static int pdlua_class_new(lua_State *L)
pdlua_widgetbehavior.w_activatefn = pdlua_activate;
class_setwidget(c, &pdlua_widgetbehavior);

/* a class with a "menu-open" method will have the "Open" item highlighted in the right-click menu */
if (c)

if (c) {
/* a class with a "menu-open" method will have the "Open" item highlighted in the right-click menu */
class_addmethod(c, (t_method)pdlua_menu_open, gensym("menu-open"), A_NULL);/* (mrpeach 20111025) */
class_addmethod(c, (t_method)pdlua_reload, gensym("_reload"), A_NULL);/* (mrpeach 20111025) */
}
/**/

lua_pushlightuserdata(L, c);
Expand Down

8 comments on commit 1bea6f1

@agraef
Copy link
Owner

@agraef agraef commented on 1bea6f1 Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tim, I just came across this old commit (and the followup a98b114, both included in #35) while fixing up the menu open code. It flew under my radar until now, but unfortunately, it now interferes with the changes in the menu open code and my own live-coding extension that I've been working on lately.

First, there's lines 436..439 which inject an inlet method into each and every Lua object. Maybe you added this as a convenience, but defining inlet callback methods in the loader, where the user must override them to get rid of them (if he's aware of them at all) is not a good idea, to put it mildly. :) In any case, live reloading can now be done much easier by just sending a reload message to the global pdluax receiver. This is implemented by the pdx.lua extension which has already been there for a while, but is now enabled by default.

Second, the whereami() method. I have mixed feelings about this, too. It adds infrastructure that needs to be maintained going forward, and it doesn't work with the built-in objects (pdlua and pdluax) where the fullpath data is never set. And we already have that kind of data by means of whoami() and _loadpath. In any case, I've since fixed the bugs in the menu_open code which the whereami() method addressed. So I think that the generic menu open code should just work in plugdata now, and the special-case code you inserted at the beginning of pdlua_menu_open in this commit shouldn't be needed anymore.

Long story short, I've reverted this commit along with rev. a98b114 now, so that we can test the latest implementation and see whether it works with plugdata now.

Do you disagree? Then please let me know! The reversion is just a single commit (rev. 28a0187), so I can easily roll it back if needed. But I'd rather not have to. ;-)

@agraef
Copy link
Owner

@agraef agraef commented on 1bea6f1 Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, getting back to my remarks about whereami() above, it would be easy to add this as an object method if you really want it. Something like this should do the trick (well, you'd probably need to add some more checking to get the corner cases right, but you get the idea):

function pd.Class:whereami()
   return self._loadpath .. self:whoami()
end

@timothyschoen
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi!

Fine with me: in plugdata the reload feature is used whenever you edit a Lua file from the built-in code editor, so that you don't have to restart for changes to take effect. It's not working perfectly right now anyway, so definitely get rid of it! I didn't know there was an extension for this, I should be using that instead anyway

@agraef
Copy link
Owner

@agraef agraef commented on 1bea6f1 Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! I was a bit worried that I might inadvertently break some essential functionality in plugdata with this change.

And yes, pdx.lua makes live-coding a lot easier now. I mean, once you set up the reload message in your patch, you don't even have to think about it any more, it's always at your fingertips.

And of course you can initiate a reload from your code editor if you add some shortcuts for pdsend (we already have that for Emacs and VS Code). To get this working from plugdata, all you have to do is to send the reload message to the pdluax receiver instead. Add the class name (basename of the script without the .pd_lua extension) as an argument to the reload message, and it will just update that one object class. Otherwise it will reload all classes. Easy as pie.

I'm still ironing out some remaining kinks with the new prereload and postreload methods, which btw were suggested by @ben-wes, go Ben! 👍 But this shouldn't take long. Expect a new release in the next 1-2 days. :)

@timothyschoen
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw, I implemented the multi-layer drawing concept for pdlua in plugdata, which works! Though plugdata will be the easiest platform to do this on. For pd (and probably purr-data), we'll need to create a group tag for each layer, send ordering messages to make sure the groups are correctly stacked. I will take a look at that very soon too!

@timothyschoen
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2024-09-05 at 02 20 37

Also getting there with Pd now! Not spectacular demo, but the green bit is on a separate layer

@agraef
Copy link
Owner

@agraef agraef commented on 1bea6f1 Sep 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As promised: https://github.com/agraef/pd-lua/releases/tag/0.12.11. Let me know how it works in plugdata. I thoroughly tested it in vanilla and purr-data, on Linux/Mac/Windows, and it seems that I finally squashed all the nasty bugs at least. :)

Btw, I implemented the multi-layer drawing concept for pdlua in plugdata, which works!

That's awesome! If you can do it in vanilla/tk, I can do it in purr-data/nw.js whose svg support is vastly more powerful. Just send me a PR when it's finished and I'll port it over, no problem.

@agraef
Copy link
Owner

@agraef agraef commented on 1bea6f1 Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timothyschoen Just a quick heads-up that I fixed quite a few more bugs in the meantime, so 0.12.15 is the latest and greatest now.

Please sign in to comment.