From 607d389cf44a877b7de7b55a4800efe0469848de Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Wed, 1 Feb 2012 20:20:44 +0000 Subject: Editor will open script for pdluax and pdlua objects, added function prototypes in pdlua.c, grouped globals together. svn path=/trunk/externals/loaders/pdlua/; revision=15932 --- src/pd.lua | 40 +++++++++++- src/pdlua.c | 211 +++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 189 insertions(+), 62 deletions(-) diff --git a/src/pd.lua b/src/pd.lua index 311330d..7ad18e9 100644 --- a/src/pd.lua +++ b/src/pd.lua @@ -1,6 +1,7 @@ --[[ pdlua -- a Lua embedding for Pd Copyright (C) 2007,2008 Claude Heiland-Allen +Copyright (C) 2012 Martin Peach martin.peach@sympatico.ca This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -92,6 +93,7 @@ end -- prototypical OO system pd.Prototype = { } + function pd.Prototype:new(o) o = o or {} setmetatable(o, self) @@ -99,9 +101,9 @@ function pd.Prototype:new(o) return o end - -- clocks pd.Clock = pd.Prototype:new() + function pd.Clock:register(object, method) if nil ~= object then if nil ~= object._object then @@ -114,11 +116,13 @@ function pd.Clock:register(object, method) end return nil end + function pd.Clock:destruct() pd._clocks[self._clock] = nil pd._clockfree(self._clock) self._clock = nil end + function pd.Clock:dispatch() local m = self._target[self._method] if type(m) == "function" then @@ -130,18 +134,22 @@ function pd.Clock:dispatch() ) end end + function pd.Clock:set(systime) pd._clockset(self._clock, systime) end + function pd.Clock:delay(delaytime) pd._clockdelay(self._clock, delaytime) end + function pd.Clock:unset() pd._clockunset(self._clock) end -- tables pd.Table = pd.Prototype:new() + function pd.Table:sync(name) self.name = name self._length, self._array = pd._getarray(name) @@ -151,10 +159,12 @@ function pd.Table:sync(name) return self end end + function pd.Table:destruct() self._length = -3 self._array = nil end + function pd.Table:get(i) if type(i) == "number" and 0 <= i and i < self._length then return pd._readarray(self._length, self._array, i) @@ -162,6 +172,7 @@ function pd.Table:get(i) return nil end end + function pd.Table:set(i, f) if type(i) == "number" and type(f) == "number" and 0 <= i and i < self._length then return pd._writearray(self._length, self._array, i, f) @@ -169,6 +180,7 @@ function pd.Table:set(i, f) return nil end end + function pd.Table:length() if self._length >= 0 then return self._length @@ -176,6 +188,7 @@ function pd.Table:length() return nil end end + function pd.Table:redraw() pd._redrawarray(self.name) end @@ -186,7 +199,9 @@ function pd._receivedispatch(receive, sel, atoms) pd._receives[receive]:dispatch(sel, atoms) end end + pd.Receive = pd.Prototype:new() + function pd.Receive:register(object, name, method) if nil ~= object then if nil ~= object._object then @@ -200,6 +215,7 @@ function pd.Receive:register(object, name, method) end return nil end + function pd.Receive:destruct() pd._receives[self._receive] = nil pd._receivefree(self._receive) @@ -208,12 +224,14 @@ function pd.Receive:destruct() self._target = nil self._method = nil end + function pd.Receive:dispatch(sel, atoms) self._target[self._method](self._target, sel, atoms) end -- patchable objects pd.Class = pd.Prototype:new() + function pd.Class:register(name) if nil ~= pd._classes[name] then -- already registered return pd._classes[name] -- return existing @@ -229,6 +247,7 @@ function pd.Class:register(name) return self -- return new end end + function pd.Class:construct(sel, atoms) self._object = pd._create(self._class) self.inlets = 0 @@ -242,11 +261,13 @@ function pd.Class:construct(sel, atoms) return nil end end + function pd.Class:destruct() pd._objects[self] = nil self:finalize() pd._destroy(self._object) end + function pd.Class:dispatch(inlet, sel, atoms) local m = self["in_" .. inlet .. "_" .. sel] if type(m) == "function" then @@ -280,41 +301,52 @@ function pd.Class:dispatch(inlet, sel, atoms) " of Lua object `" .. self._name .. "'" ) end + function pd.Class:outlet(outlet, sel, atoms) pd._outlet(self._object, outlet, sel, atoms) end + function pd.Class:initialize(sel, atoms) end + function pd.Class:postinitialize() end + function pd.Class:finalize() end + function pd.Class:dofile(file) return pd._dofile(self._object, file) end + function pd.Class:error(msg) pd._error(self._object, msg) end + function pd.Class:whoami() return self._scriptname or self._name end + function pd.Class:get_class() -- accessor for t_class* return self._class or nil end local lua = pd.Class:new():register("pdlua") -- global controls (the [pdlua] object only) + function lua:initialize(sel, atoms) self.inlets = 1 self.outlets = 0 -- FIXME: might be nice to have errors go here? return true end + function lua:in_1_load(atoms) -- execute a script self:dofile(atoms[1]) end local luax = pd.Class:new():register("pdluax") -- classless lua externals (like [pdluax foo]) + function luax:initialize(sel, atoms) -- motivation: pd-list 2007-09-23 - local f = self:dofile(atoms[1] .. ".pd_luax") + local f, pathname = self:dofile(atoms[1] .. ".pd_luax") if nil ~= f then - self._scriptname = atoms[1] .. ".pd_luax" -- mrpeach 20111027 + self._scriptname = pathname .. '/' .. atoms[1] .. ".pd_luax" -- mrpeach 20120201 local atomstail = { } -- munge for better lua<->luax compatibility for i,_ in ipairs(atoms) do if i > 1 then @@ -326,3 +358,5 @@ function luax:initialize(sel, atoms) -- motivation: pd-list 2007-09-23 return false -- error message already output by dofile() end end + +-- fin pd.lua diff --git a/src/pdlua.c b/src/pdlua.c index 09e264c..0b946ca 100644 --- a/src/pdlua.c +++ b/src/pdlua.c @@ -82,6 +82,7 @@ /* If defined, PDLUA_DEBUG lets pdlua post a lot of text */ //#define PDLUA_DEBUG + /** Global Lua interpreter state, needed in the constructor. */ static lua_State *L; @@ -92,6 +93,150 @@ typedef struct pdlua_readerdata char buffer[MAXPDSTRING]; /**< Buffer to read into. */ } t_pdlua_readerdata; +/** Pd object data. */ +typedef struct pdlua +{ + t_object pd; /**< We are a Pd object. */ + int inlets; /**< Number of inlets. */ + struct pdlua_proxyinlet *in; /**< The inlets themselves. */ + int outlets; /**< Number of outlets. */ + t_outlet **out; /**< The outlets themselves. */ + t_canvas *canvas; /**< The canvas that the object was created on. */ +} t_pdlua; + +/** Proxy inlet object data. */ +typedef struct pdlua_proxyinlet +{ + t_pd pd; /**< Minimal Pd object. */ + struct pdlua *owner; /**< The owning object to forward inlet messages to. */ + unsigned int id; /**< The number of this inlet. */ +} t_pdlua_proxyinlet; + +/** Proxy receive object data. */ +typedef struct pdlua_proxyreceive +{ + t_pd pd; /**< Minimal Pd object. */ + struct pdlua *owner; /**< The owning object to forward received messages to. */ + t_symbol *name; /**< The receive-symbol to bind to. */ +} t_pdlua_proxyreceive; + +/** Proxy clock object data. */ +typedef struct pdlua_proxyclock +{ + t_pd pd; /**< Minimal Pd object. */ + struct pdlua *owner; /**< Object to forward messages to. */ + t_clock *clock; /** Pd clock to use. */ +} t_pdlua_proxyclock; +/* prototypes*/ + +static const char *pdlua_reader (lua_State *L, void *rr, size_t *size); +/** Proxy inlet 'anything' method. */ +static void pdlua_proxyinlet_anything (t_pdlua_proxyinlet *p, t_symbol *s, int argc, t_atom *argv); +/** Proxy inlet initialization. */ +static void pdlua_proxyinlet_init (t_pdlua_proxyinlet *p, struct pdlua *owner, unsigned int id); +/** Register the proxy inlet class with Pd. */ +static void pdlua_proxyinlet_setup (void); +/** Proxy receive 'anything' method. */ +static void pdlua_proxyreceive_anything (t_pdlua_proxyreceive *r, t_symbol *s, int argc, t_atom *argv); +/** Proxy receive allocation and initialization. */ +static t_pdlua_proxyreceive *pdlua_proxyreceive_new (struct pdlua *owner, t_symbol *name); +/** Proxy receive cleanup and deallocation. */ +static void pdlua_proxyreceive_free (t_pdlua_proxyreceive *r /**< The proxy receive to free. */); +/** Register the proxy receive class with Pd. */ +static void pdlua_proxyreceive_setup (void); +/** Proxy clock 'bang' method. */ +static void pdlua_proxyclock_bang (t_pdlua_proxyclock *c); +/** Proxy clock allocation and initialization. */ +static t_pdlua_proxyclock *pdlua_proxyclock_new (struct pdlua *owner); +/** Register the proxy clock class with Pd. */ +static void pdlua_proxyclock_setup (void); +/** Dump an array of atoms into a Lua table. */ +static void pdlua_pushatomtable (int argc, t_atom *argv); +/** Pd object constructor. */ +static t_pdlua *pdlua_new (t_symbol *s, int argc, t_atom *argv); +/** Pd object destructor. */ +static void pdlua_free (t_pdlua *o ); +/** a handler for the open item in the right-click menu (mrpeach 20111025) */ +/** Here we find the lua code for the object and open it in an editor */ +static void pdlua_menu_open (t_pdlua *o); +/** Lua class registration. This is equivalent to the "setup" method for an ordinary Pd class */ +static int pdlua_class_new (lua_State *L); +/** Lua object creation. */ +static int pdlua_object_new (lua_State *L); +/** Lua object inlet creation. */ +static int pdlua_object_createinlets (lua_State *L); +/** Lua object outlet creation. */ +static int pdlua_object_createoutlets (lua_State *L); +/** Lua object receive creation. */ +static int pdlua_receive_new (lua_State *L); +/** Lua object receive destruction. */ +static int pdlua_receive_free (lua_State *L); +/** Lua object clock creation. */ +static int pdlua_clock_new (lua_State *L); +/** Lua proxy clock delay. */ +static int pdlua_clock_delay (lua_State *L); +/** Lua proxy clock set. */ +static int pdlua_clock_set (lua_State *L); +/** Lua proxy clock unset. */ +static int pdlua_clock_unset (lua_State *L); +/** Lua proxy clock destruction. */ +static int pdlua_clock_free (lua_State *L); +/** Lua object destruction. */ +static int pdlua_object_free (lua_State *L); +/** Dispatch Pd inlet messages to Lua objects. */ +static void pdlua_dispatch (t_pdlua *o, unsigned int inlet, t_symbol *s, int argc, t_atom *argv); +/** Dispatch Pd receive messages to Lua objects. */ +static void pdlua_receivedispatch (t_pdlua_proxyreceive *r, t_symbol *s, int argc, t_atom *argv); +/** Dispatch Pd clock messages to Lua objects. */ +static void pdlua_clockdispatch(t_pdlua_proxyclock *clock); +/** Convert a Lua table into a Pd atom array. */ +static t_atom *pdlua_popatomtable (lua_State *L, int *count, t_pdlua *o); +/** Send a message from a Lua object outlet. */ +static int pdlua_outlet (lua_State *L); +/** Send a message from a Lua object to a Pd receiver. */ +static int pdlua_send (lua_State *L); +/** Set a [value] object's value. */ +static int pdlua_setvalue (lua_State *L); +/** Get a [value] object's value. */ +static int pdlua_getvalue (lua_State *L); +/** Get a [table] object's array. */ +static int pdlua_getarray (lua_State *L); +/** Read from a [table] object's array. */ +static int pdlua_readarray (lua_State *L); +/** Write to a [table] object's array. */ +static int pdlua_writearray (lua_State *L); +/** Redraw a [table] object's graph. */ +static int pdlua_redrawarray (lua_State *L); +/** Post to Pd's console. */ +static int pdlua_post (lua_State *L); +/** Report an error from a Lua object to Pd's console. */ +static int pdlua_error (lua_State *L); +static void pdlua_setrequirepath (lua_State *L, const char *path); +static void pdlua_clearrequirepath (lua_State *L); +/** Run a Lua script using Pd's path. */ +static int pdlua_dofile (lua_State *L); +/** Initialize the pd API for Lua. */ +static void pdlua_init (lua_State *L); +/** Pd loader hook for loading and executing Lua scripts. */ +static int pdlua_loader (t_canvas *canvas, char *name); +/** Start the Lua runtime and register our loader hook. */ +#ifdef _WIN32 +__declspec(dllexport) +#endif +void pdlua_setup (void); +/* end prototypes*/ + +/* globals */ +struct pdlua_proxyinlet; +struct pdlua_proxyreceive; +struct pdlua_proxyclock; +/** Proxy inlet class pointer. */ +static t_class *pdlua_proxyinlet_class; +/** Proxy receive class pointer. */ +static t_class *pdlua_proxyreceive_class; +/** Proxy clock class pointer. */ +static t_class *pdlua_proxyclock_class; + /** Lua file reader callback. */ static const char *pdlua_reader ( @@ -121,38 +266,6 @@ static const char *pdlua_reader } } -/* declare some stuff in advance */ -struct pdlua_proxyinlet; -struct pdlua_proxyreceive; -struct pdlua_proxyclock; - -/** Pd object data. */ -typedef struct pdlua -{ - t_object pd; /**< We are a Pd object. */ - int inlets; /**< Number of inlets. */ - struct pdlua_proxyinlet *in; /**< The inlets themselves. */ - int outlets; /**< Number of outlets. */ - t_outlet **out; /**< The outlets themselves. */ - t_canvas *canvas; /**< The canvas that the object was created on. */ -} t_pdlua; - -/* more forward declarations */ -static void pdlua_dispatch(t_pdlua *o, unsigned int inlet, t_symbol *s, int argc, t_atom *argv); -static void pdlua_receivedispatch(struct pdlua_proxyreceive *r, t_symbol *s, int argc, t_atom *argv); -static void pdlua_clockdispatch(struct pdlua_proxyclock *clock); - -/** Proxy inlet class pointer. */ -static t_class *pdlua_proxyinlet_class; - -/** Proxy inlet object data. */ -typedef struct pdlua_proxyinlet -{ - t_pd pd; /**< Minimal Pd object. */ - struct pdlua *owner; /**< The owning object to forward inlet messages to. */ - unsigned int id; /**< The number of this inlet. */ -} t_pdlua_proxyinlet; - /** Proxy inlet 'anything' method. */ static void pdlua_proxyinlet_anything ( @@ -185,17 +298,6 @@ static void pdlua_proxyinlet_setup(void) class_addanything(pdlua_proxyinlet_class, pdlua_proxyinlet_anything); } -/** Proxy receive class pointer. */ -static t_class *pdlua_proxyreceive_class; - -/** Proxy receive object data. */ -typedef struct pdlua_proxyreceive -{ - t_pd pd; /**< Minimal Pd object. */ - struct pdlua *owner; /**< The owning object to forward received messages to. */ - t_symbol *name; /**< The receive-symbol to bind to. */ -} t_pdlua_proxyreceive; - /** Proxy receive 'anything' method. */ static void pdlua_proxyreceive_anything( t_pdlua_proxyreceive *r, /**< The proxy receive that received the message. */ @@ -239,18 +341,6 @@ static void pdlua_proxyreceive_setup() class_addanything(pdlua_proxyreceive_class, pdlua_proxyreceive_anything); } - -/** Proxy clock class pointer. */ -static t_class *pdlua_proxyclock_class; - -/** Proxy clock object data. */ -typedef struct pdlua_proxyclock -{ - t_pd pd; /**< Minimal Pd object. */ - struct pdlua *owner; /**< Object to forward messages to. */ - t_clock *clock; /** Pd clock to use. */ -} t_pdlua_proxyclock; - /** Proxy clock 'bang' method. */ static void pdlua_proxyclock_bang(t_pdlua_proxyclock *c /**< The proxy clock that received the message. */) { @@ -1173,8 +1263,8 @@ static int pdlua_error(lua_State *L) return 0; } -void pdlua_setrequirepath -( /* FIXME: documentation */ +static void pdlua_setrequirepath +( /* FIXME: documentation (is this of any use at all?) */ lua_State *L, const char *path ) @@ -1191,8 +1281,8 @@ void pdlua_setrequirepath lua_pop(L, 1); } -void pdlua_clearrequirepath -( /* FIXME: documentation */ +static void pdlua_clearrequirepath +( /* FIXME: documentation (is this of any use at all?) */ lua_State *L ) { @@ -1241,6 +1331,7 @@ static int pdlua_dofile(lua_State *L) #ifdef PDLUA_DEBUG post("pdlua_dofile path is %s", buf); #endif // PDLUA_DEBUG + //pdlua_setpathname(o, buf);/* change the scriptname to include its path */ pdlua_setrequirepath(L, buf); reader.fd = fd; if (lua_load(L, pdlua_reader, &reader, filename)) @@ -1271,6 +1362,7 @@ static int pdlua_dofile(lua_State *L) else error("lua: error in object:dofile() - object is null"); } else error("lua: error in object:dofile() - object is wrong type"); + lua_pushstring(L, buf); /* return the path as well so we can open it later with pdlua_menu_open() */ return lua_gettop(L) - n; } @@ -1383,6 +1475,7 @@ static int pdlua_loader reader.fd = fd; if (lua_load(L, pdlua_reader, &reader, name) || lua_pcall(L, 0, 0, 0)) { + error("lua: error loading `%s':\n%s", name, lua_tostring(L, -1)); lua_pop(L, 1); close(fd); -- cgit v1.2.1