aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/Makefile5
-rw-r--r--doc/internal.txt77
-rw-r--r--doc/lua.txt148
-rw-r--r--doc/luax.txt71
-rw-r--r--doc/pdlua.tex156
5 files changed, 457 insertions, 0 deletions
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..9b0f913
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,5 @@
+all: pdlua.pdf
+
+%.pdf: %.tex
+ pdflatex $<
+ pdflatex $<
diff --git a/doc/internal.txt b/doc/internal.txt
new file mode 100644
index 0000000..92e4c37
--- /dev/null
+++ b/doc/internal.txt
@@ -0,0 +1,77 @@
+Internal Stuff
+==============
+
+This is a developer document, not a user document. You probably don't
+need to read this.
+
+
+Private/Internal Variables
+--------------------------
+
+Everything that the user shouldn't dabble with starts with '_'.
+For example 'pd._constructor', 'self._object', etc. This includes
+everything that messes with pointers, for many purposes have a
+stub: function f(self, ...) return _f(self._object, ...) end
+
+Things that the user can use shouldn't start with '_'.
+
+Everything in pdlua should be in the 'pd' global table.
+
+
+Table Indices
+-------------
+
+As per Lua conventions, Lua tables start at index 1. See:
+
+lua.c/pdlua_pushatomtable() (C->Lua)
+lua.c/pdlua_popatomtable() (Lua->C) (makes additional assumptions)
+
+
+Inlet/Outlet Numbers
+--------------------
+
+C code uses 0,1,...
+Lua code uses 1,2,...
+
+Translations are performed in:
+
+lua.c/pdlua_dispatch() (C->Lua)
+lua.c/pdlua_outlet() (Lua->C)
+
+
+Pointers
+--------
+
+Pointers are all Light User Data values. This means there is no type
+safety, make sure you're using the right pointers!
+
+pd._classes :: string => Lua object (class prototypes)
+object._class :: t_class*
+
+pd._objects :: t_pdlua* => Lua object (object instances)
+object._object :: t_pdlua*
+
+pd._clocks :: t_clock* => Lua object (clock instances)
+clock._clock :: t_clock*
+
+pdtable._array :: PDLUA_ARRAY_ELEM*
+
+Pointer atoms are also stored as Light User Data. It's possible for
+things to crash if they are used/stored/etc, as far as I understand the
+way Pd uses them.
+
+
+Architecture Issues
+-------------------
+
+:initialize() is called before the object is created.
+:postinitialize() is called after the object is created.
+
+
+Other Issues
+------------
+
+"#t does not invoke the __len metamethod when t is a table."
+See end of: http://lua-users.org/wiki/GeneralizedPairsAndIpairs
+
+This means pd.Table will remain ugly, with :length() :set() :get()
diff --git a/doc/lua.txt b/doc/lua.txt
new file mode 100644
index 0000000..486380a
--- /dev/null
+++ b/doc/lua.txt
@@ -0,0 +1,148 @@
+pdlua
+===
+
+The Lua loader included in -lib pdlua allows externals for Pd to be
+written in the Lua programming language.
+
+If you try to create an object [foo] in Pd, Pd checks if the class
+"foo" exists. If it doesn't, it tries to load an external file that
+"probably" will contain code for "foo". The Lua loader adds support
+for loading "foo.pd_lua" when you try to create [foo].
+
+
+Class Creation
+--------------
+
+The first expression/statement in the file should be of the form:
+
+ local foo = pd.Class:new():register("foo")
+
+This creates a new Pd class called "foo". The 'local' declaration
+is optional, but recommended -- without it, 'foo' is global, which
+means any Lua code can modify it (possibly by accident).
+
+
+Object Initialization
+---------------------
+
+Then you can add methods to the Pd class. The most important one
+is 'initialize', which is executed when a new object is created.
+
+ function foo:initialize(sel, atoms)
+ -- code
+ end
+
+or equivalently:
+
+ foo.initialize = function (self, sel, atoms)
+ -- code
+ end
+
+'sel' is usually (always?) the class name, 'atoms' are the creation
+arguments in a Lua table. An example:
+
+ Pd :: [foo a b 1 2 3 c]
+ sel == "foo"
+ atoms == { "a", "b", 1, 2, 3, "c" }
+
+Being a method, 'initialize' has a 'self' variable (which is the
+object to be created), and if you want your objects to have inlets
+or outlets you need need to set those fields in this method (Pd
+doesn't support changing the number of inlets or outlets after an
+object is created):
+
+ self.inlets = 1
+ self.outlets = atoms[1]
+
+The default inlet/outlet counts are 0.
+
+The return value of 'initialize' is used to allow objects to fail
+to create (for example, if the creation arguments are bad). Most
+of the time you will 'return true', but if you really can't create
+then you can 'return false'.
+
+If you need to do things after the Pd object is created, but before
+control is returned to Pd, you can use the 'postinitialize' method:
+
+ function foo:postinitialize()
+ -- code
+ end
+
+
+Object Finalization
+-------------------
+
+The 'finalize' method is called when the object is deleted by Pd.
+You can clean up stuff here if needed. The default implementation
+does nothing.
+
+
+Inlet Methods
+-------------
+
+FIXME: write about inlet methods/dispatching
+FIXME: for now, see examples/*.pd_lua and src/pd.lua
+
+
+Sending To Outlets
+------------------
+
+FIXME: write about self:outlet(outletNumber, selector, atoms)
+FIXME: for now, see examples/*.pd_lua and src/pd.lua
+
+
+Sending To Receivers
+--------------------
+
+You can send messages to receivers like this:
+
+ pd.send("receiver", "selector", { "a", "message", 1, 2, 3 }
+
+See examples/lsend.pd_lua for details.
+
+
+Receivers
+---------
+
+You can bind methods to receivers, to get messages from
+[send receiver] and "; receiver message".
+
+See examples/lreceive.pd_lua for details.
+
+Remember to clean up your receivers in object:finalize(), or weird
+things will happen.
+
+
+Clocks
+------
+
+You can bind methods to clocks, for timing based on Pd's logical clock.
+
+See examples/ldelay.pd_lua for details.
+
+Remember to clean up your clocks in object:finalize(), or weird things
+will happen.
+
+
+Miscellaneous Object Methods
+----------------------------
+
+Execute a Lua file using Pd's path to find it:
+
+ self:dofile("filename")
+
+Report an error to Pd's console:
+
+ self:error("message")
+
+
+Miscellaneous Functions
+-----------------------
+
+Print a string to Pd's console:
+
+ pd.post("a string")
+
+Note that pd.post() should not really be used for errors.
+
+FIXME: add pd.error() for error messages
diff --git a/doc/luax.txt b/doc/luax.txt
new file mode 100644
index 0000000..dbaadb4
--- /dev/null
+++ b/doc/luax.txt
@@ -0,0 +1,71 @@
+pdluax
+====
+
+The pdluax class allows "volatile" loading of Lua source code files
+that define Pd object behaviour.
+
+The [pdluax foo] object loads "foo.pd_luax" at object creation time.
+
+
+Advantages
+----------
+
++ You can edit "foo.pd_luax" and new [pdluax foo] objects will reflect
+ the changes in the file.
+
++ Good for rapid development/testing cycles.
+
++ Good for live coding.
+
++ No need to restart Pd if you made a little mistake.
+
+
+Disadvantages
+-------------
+
+- Reloading the file each time is slower.
+
+- Syntax is different to the syntax expected by the Lua loader
+ (see below for discussion).
+
+- There is no "reload" functionality, so you can have multiple
+ objects called [pdluax foo] but that have different behaviours.
+
+- Data shared between objects must be accessible globally.
+
+- The above two points mean some mistakes/changes mean you have
+ to restart Pd anyway.
+
+
+How To Write Code For pdluax
+--------------------------
+
+The last expression/statement in the file should be of the form:
+
+ return function (self, sel, atoms)
+ -- code here
+ end
+
+This function is executed in the context of the 'initialize'
+method of the pdluax class, and has the same arguments:
+
+ 'self' is the object to be created.
+ 'sel' is the name of the class.
+ 'atoms' are the creation arguments.
+
+To add methods to the new object you need to add code inside
+the returned function. There are two syntaxes for this:
+
+ function self:in_1_float(f) ... end
+
+or
+
+ self.in_1_float = function(self, f) ... end
+
+If using the second form, remember the self argument.
+
+If you need a shared state between objects, you need to use a
+global name. Try to pick something unique to avoid conflicts
+with other scripts. You also need to ensure that you don't
+clobber this state - remember the script can be executed more
+than once.
diff --git a/doc/pdlua.tex b/doc/pdlua.tex
new file mode 100644
index 0000000..becceb9
--- /dev/null
+++ b/doc/pdlua.tex
@@ -0,0 +1,156 @@
+\documentclass{article}
+
+\title{pdlua}
+\author{Claude Heiland-Allen
+\\
+\tt{claudiusmaximus@goto10.org}}
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+Pd (aka Pure-data) is a real-time visual programming environment
+primarily used for multimedia processing. Lua is a powerful, fast,
+light-weight, embeddable scripting language. pdlua is a Lua embedding
+for Pd.
+\end{abstract}
+
+\section{Classes and objects}
+
+\begin{verbatim}
+-- example1.pd_lua
+local example1 = pd.Class:new():register("example1")
+function example1:initialize(sel, atoms)
+ return true
+end
+\end{verbatim}
+
+{\tt pd} is a package automatically available to scripts loaded by pdlua.
+pdlua uses a prototype-based object system and {\tt pd.Class} is the
+prototype for classes that define patchable objects in Pd. To create a
+new class, use the {\tt :new()} method. This creates an anonymous class,
+which needs to be registered with Pd using the {\tt :register()} method.
+
+The new class {\tt example1} cannot be instantiated yet, as the default
+{\tt :initialize()} method returns {\tt false}, indicating to pdlua that
+the Pd object should not be created.
+
+With the code above, {\tt example1} can be created in Pd, but it will
+have neither inlets nor outlets.
+
+\section{Inlets and methods}
+
+\begin{verbatim}
+-- example2.pd_lua
+local example2 = pd.Class:new():register("example2")
+function example2:initialize(sel, atoms)
+ self.inlets = 3
+ return true
+end
+\end{verbatim}
+
+Setting {\tt self.inlets} in the {\tt :initialize()} method will give
+the created objects some inlets, in this case three of them. Not very
+interesting yet, as sending messages to these inlets will result in
+errors as there are no methods to respond to messages at these inlets.
+
+Messages arriving at the Pd object's inlets are dispatched to the Lua
+object's {\tt :in\_*()} methods. There are five predefined selectors:
+
+\begin{itemize}
+\item {\tt bang}
+\item {\tt float}
+\item {\tt symbol}
+\item {\tt pointer}
+\item {\tt list}
+\end{itemize}
+
+They can be used like this:
+
+\begin{verbatim}
+function example2:in_1_bang()
+ pd.post("inlet 1 got a bang")
+end
+function example2:in_1_float(f)
+ pd.post("inlet 1 got a float: " .. f)
+end
+function example2:in_1_symbol(s)
+ pd.post("inlet 1 got a symbol: " .. s)
+end
+function example2:in_1_pointer(p)
+ pd.post("inlet 1 got a pointer)
+end
+function example2:in_1_list(atoms)
+ pd.post("inlet 1 got a list: " .. #atoms .. " elements")
+end
+\end{verbatim}
+
+In the above, the methods are defined for the leftmost inlet. To add
+methods for the other inlets, replace {\tt :in\_1\_*()} with
+{\tt :in\_2\_*()} for the second inlet, or {\tt :in\_3\_*()} for the third,
+and so on.
+
+It is possible to add methods for other selectors:
+
+\begin{verbatim}
+function example2:in_2_baabaa(atoms)
+ pd.post("inlet 2 got a baabaa: " .. #atoms .. " elements")
+end
+function example2:in_2_moomoo(atoms)
+ pd.post("inlet 2 got a moomoo: " .. #atoms .. " elements")
+end
+\end{verbatim}
+
+It is also possible to add methods that catch any selector:
+
+\begin{verbatim}
+function example2:in_3(sel, atoms)
+ pd.post("inlet 3 got a " .. sel .. ": .. #atoms .. " elements")
+end
+\end{verbatim}
+
+Or methods that catch messages at any inlet:
+
+\begin{verbatim}
+function example2:in_n_float(i, f)
+ pd.post("inlet " .. i .. " got a float: " .. f)
+end
+function example2:in_n_quack(i, atoms)
+ pd.post("inlet " .. i .. " got a quack: " .. #atoms .. " elements")
+end
+\end{verbatim}
+
+Or even catch any message at any inlet:
+
+\begin{verbatim}
+function example2:in_n(i, sel, atoms)
+ pd.post("inlet " .. i .. " got a " .. sel .. ": " .. #atoms .. " elements")
+end
+\end{verbatim}
+
+The more specific methods are called before the more general methods:
+
+\begin{itemize}
+\item {\tt :in\_1\_selector()}
+\item {\tt :in\_n\_selector()}
+\item {\tt :in\_1()}
+\item {\tt :in\_n()}
+\item {\tt :error("no method found")}
+\end{itemize}
+
+\section{Outlets}
+
+\section{Sends}
+
+\section{Receives}
+
+\section{Values}
+
+\section{Tables}
+
+\section{Clocks}
+
+\section{Paths}
+
+\end{document}