diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README.txt | 59 | ||||
-rw-r--r-- | tclpd.c | 2 | ||||
-rw-r--r-- | tclpd.tcl (renamed from pdlib.tcl) | 5 |
4 files changed, 26 insertions, 44 deletions
@@ -25,7 +25,7 @@ TCLPD_SOURCES = hashtable.c tcl_class.c tcl_loader.c tcl_proxyinlet.c tcl_typema # list them here. This can be anything from header files, test patches, # documentation, etc. README.txt and LICENSE.txt are required and therefore # automatically included -EXTRA_DIST = tcl.i tcl_extras.h pdlib.tcl $(TCLPD_SOURCES) ChangeLog.txt AUTHORS.txt TODO.txt +EXTRA_DIST = tcl.i tcl_extras.h tclpd.tcl $(TCLPD_SOURCES) ChangeLog.txt AUTHORS.txt TODO.txt @@ -312,7 +312,7 @@ single_install: $(LIBRARY_NAME) install-doc install-examples install-manual $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION) - $(INSTALL_DATA) pdlib.tcl $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) + $(INSTALL_DATA) tclpd.tcl $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) ifeq ($(UNAME),Darwin) # force tclpd to use the Tcl.framework built into Pd-extended install_name_tool -change \ @@ -3,14 +3,12 @@ ========== This library allows to to write externals for Pd using the Tcl language. - -It is based on the standard API of PD (defined in m_pd.h, plus some other -private header files, like g_canvas.h, s_stuff.h, ...). +It wraps quite closely the pd API (m_pd.h, plus some private functions) Also a library of Tcl helper functions is provided. It is not mandatory to use it (moreover: it requires Tcl 8.5, while the tclpd external alone requires only Tcl 8.4), but it is a syntactic sugar and can simplify a lot the code. -Using it is as simple as sourcing pdlib.tcl in your Tcl external. +To use it simply add 'package require TclpdLib' in your Tcl external. Anyway, disregarding any approach chosen to develop Tcl externals, a general knowledge of Pd internals (atoms, symbols, symbol table, inlets, objects) is @@ -37,40 +35,29 @@ pure-data). ===================== Pd is split into two processes: pd (the core) and pd-gui. -A simple pd external just runs in the core. A simple Tcl externals still runs -in the core, because tclpd creates a Tcl interpreter for that. - -Instead, pd-gui has its own Tcl interpreter. In order to to GUI things (i.e. -draw on the canvas, or react to mouse events), the core process needs to -communicate with the pd-gui process (generally sending Tk commands, or calling -procedures defined in the pd-gui interp. -This is done with the sys_gui() function, if using the plain API. - -Also pdlib.tcl provide means to simplify this task, with the guiproc function, -which defines procedures directly into the pd-gui interpreter. +A pd external executes in the core. The same applies for a Tcl external loaded +by tclpd, because tclpd creates a Tcl interpreter for that, running in the +same process as pd. -As a counterexample, I'd like to cite tot/toxy/widget externals, which you may -be familiar with. -Such externals run in the pd-gui process. That was fine for writing simple gui -externals, that don't need to react to any message. -But, for instance, you cannot do a metronome or anything which is timing -accurate, or heavy IO, as that is not the purpose of the gui process. -Tclpd instead, by running in the core process, allows that. +On the gui side (pd-gui) there is another Tcl interpreter living in a separate +process, which communicates with pd using a network socket. +Communication happens in one way (pd to gui) with the sys_gui function, and in +the other way using ::pdsend. (needs to set up a receiver using pdbind, check +the examples). Data conversion between Tcl <=> Pd ================================== -In pd exists 'atoms'. An atom is a float, a symbol, a list item, and such. -Tcl does not have data types. In Tcl everything is a string, also numbers and -lists. Just when something needs to be read as number, then evaluation comes -in. -This leads to loss of information about atom types. Imagine a -symbol '456' comes into tclpd, you won't know anymore if "456" -is a symbol or a float. +In pd objects communicate using messages, and messages are made up of atoms. +An atom could be a float, a symbol, a list, and so on. +Tcl usually doesn't make distinction between strings and numbers. This means +that simply translating a message text into a string could lose information +about the atom type (to pd, symbol 456 is different from float 456, but if we +just convert it as a string "456" the type information is lost). -Here a little convention comes in: in tclpd an atom gets converted into a -two-item list, where first item is atom type, and second item is its value. +To maintain atom type infrmation, pd atoms are represented in Tcl as two +element lists, where the first element indicates the atom type. Some examples of this conversion: @@ -87,15 +74,7 @@ Some examples of this conversion: Examples ======== -I provided small examples. -after loading pd with option '-lib tcl', just type the filename -(minus the .tcl extension) to load the Tcl externals examples. - -actually there is one simple example: list_change (behaves like -[change] object, but work with lists only) - -examples make use of pdlib.tcl. It's still possible to port the example to use -only the plain Pd api. Contributions are welcome. +Some examples externals are provided, including their helpfile. Authors @@ -25,7 +25,7 @@ void tclpd_setup(void) { t_class* foo_class = class_new(gensym("tclpd_init"), 0, 0, 0, 0, 0); char buf[PATH_MAX]; - snprintf(buf, PATH_MAX, "%s/pdlib.tcl", foo_class->c_externdir->s_name); + snprintf(buf, PATH_MAX, "%s/tclpd.tcl", foo_class->c_externdir->s_name); if(Tcl_EvalFile(tcl_for_pd, buf) != TCL_OK) { error("tclpd loader: error loading %s", buf); } @@ -122,7 +122,10 @@ namespace eval ::pd { } elseif {\$function == \"widgetbehavior\"} { set subfunction \[lindex \$args 0\] set argsr \[lrange \$args 1 end\] - uplevel \[linsert \$argsr 0 ::${classname}::\${function}_\${subfunction} \$self] + set f ::${classname}::\${function}_\${subfunction} + if {\[info procs \$f\] != {}} { + uplevel \[linsert \$argsr 0 \$f \$self] + } } else { uplevel \[linsert \$args 0 ::${classname}::\$function \$self\] } |