diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index e18d9289514bf54cb7f495546dbcd0b83aeb2241..0000000000000000000000000000000000000000 --- a/doc/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -#==============================================================================# -# -# Centralized build system for "doc". -# -# see for instructions: http://puredata.org/docs/developer/build -# <hans@at.or.at> -# -#==============================================================================# - -CWD := $(shell pwd) - -# these are designed to be overridden by the packages/Makefile -cvs_root_dir := $(shell cd $(CWD)/.. && pwd) -DESTDIR = $(CWD)/build/ -BUILDLAYOUT_DIR = $(cvs_root_dir)/packages - -CURL := curl --connect-timeout 600 --max-time 3600 - -# default target -all: - @echo "this currently does nothing" - -include $(BUILDLAYOUT_DIR)/Makefile.buildlayout - -#==============================================================================# -# -# OVERARCHING BUILD TARGETS -# -#==============================================================================# - -DOC_TARGETS = media - -# clean up after everything is installed -final_setup: - chmod -R ugo-w $(pddocdir) - -install: $(objectsdir) $(helpdir) $(manualsdir) $(examplesdir) \ -$(patsubst %, %_install,$(DOC_TARGETS)) - @echo " " - @echo "doc install succeeded!" - - -#==============================================================================# -# -# PROJECT-SPECIFIC TARGETS -# -#==============================================================================# - - -#------------------------------------------------------------------------------# -# TEMPLATE -TEMPLATE_NAME = template -template_install: $(manualsdir) - install -d $(helpdir)$(manualsdir)/$(TEMPLATE_NAME) - install -p $(doc_src)/template/*.* \ - $(helpdir)$(manualsdir)/$(TEMPLATE_NAME) - -template_clean: - -rm -f -- $(helpdir)$(manualsdir)/$(TEMPLATE_NAME)/*.* - -rmdir -- $(helpdir)$(manualsdir)/$(TEMPLATE_NAME) - - -#------------------------------------------------------------------------------# -# MEDIA -MEDIA_NAME = media -media_install: $(pddocdir) - install -d $(DESTDIR)$(pddocdir)/$(MEDIA_NAME) - install -p $(doc_src)/media/*.* \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME) -# ln is cp on MinGW, so these won't work since the target files don't exist at -# the time that the media_install target is generally run. For MinGW, this is -# instead handled in packages/win32_inno/pd-inno.iss.in -ifneq (MINGW,$(findstring MINGW,$(UNAME))) -# random sound files - ln -sf ../../doc/sound/bell.aiff \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/bell.aiff - ln -sf ../../doc/sound/voice.wav \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/voice.wav - ln -sf ../../doc/sound/voice2.wav \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/voice2.wav - ln -sf ../../extra/bsaylor/examples/noiseburst.wav \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/noiseburst.wav - ln -sf ../../extra/ekext/examples/stink.wav \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/stink.wav - ln -sf ../../extra/ekext/examples/beauty.wav \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/beauty.wav - ln -sf ../../extra/ekext/examples/drummach.wav \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/drummach.wav -# Gem videos - ln -sf ../../extra/Gem/examples/data/alea.mpg \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/alea.mpg - ln -sf ../../extra/Gem/examples/data/homer.avi \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/homer.avi - ln -sf ../../extra/Gem/examples/data/anim-1.mov \ - $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/anim-1.mov -endif - -media_clean: - -rm -f -- $(DESTDIR)$(pddocdir)/$(MEDIA_NAME)/*.* - -rmdir -- $(DESTDIR)$(pddocdir)/$(MEDIA_NAME) - -#==============================================================================# -# -# CLEAN TARGETS -# -#==============================================================================# - -# the destination-specific clean targets are in Makefile.buildlayout -clean: $(patsubst %, %_clean,$(DOC_TARGETS)) - -distclean: clean cruft_clean - - - - -test_locations: - @echo "PD_VERSION: $(PD_VERSION)" - @echo "PACKAGE_VERSION: $(PACKAGE_VERSION)" - @echo "CWD $(CWD)" - @echo "DESTDIR $(DESTDIR)" - @echo "PREFIX $(prefix)" - @echo "BINDIR $(bindir)" - @echo "LIBDIR $(libdir)" - @echo "OBJECTSDIR $(objectsdir)" - @echo "PDDOCDIR $(pddocdir)" - @echo "LIBPDDIR $(libpddir)" - @echo "LIBPDBINDIR $(libpdbindir)" - @echo "HELPDIR $(helpdir)" - @echo "MANUALSDIR $(manualsdir)" - @echo "EXAMPLESDIR $(examplesdir)" diff --git a/doc/TODO b/doc/TODO deleted file mode 100644 index a6a3a76776d8bff5042487f75cbb081e1d139f91..0000000000000000000000000000000000000000 --- a/doc/TODO +++ /dev/null @@ -1,19 +0,0 @@ - -- add externals HOWTO to manuals/Pd - -- create Makefile for Pd-extended build system - -- add pd-fileformat doc: http://student-kmt.hku.nl/%7Etjeerd/pd/pd_fileformat.html - -- replace [pddp] with "pddp" in all help files so that it doesn't cause bugs - with the pddp/pddp.pd meta file, and other things in the future. Here's a - pattern: sed -n 's|obj \([0-9]*\) \([0-9]*\) pddp;|msg \1 \2 pddp;|p' *.pd - -- add doc/pddp/about, help, etc. to doc/Makefile - -- mv doc/pddp/pddp.pd to doc/pddp/about/pddp-about.pd - -- add [symbol 1( and [1 ( test messages to the bottom right example in - [pd some odd cases of list handling] in - doc/pddp/all_about_lists_vs_anythings.pd - diff --git a/doc/media/bach.mid b/doc/media/bach.mid deleted file mode 100644 index 301546cdcb85e6fb0ffe4b49785e47d6857084af..0000000000000000000000000000000000000000 Binary files a/doc/media/bach.mid and /dev/null differ diff --git a/doc/media/kanon.mid b/doc/media/kanon.mid deleted file mode 100644 index a07f5ecaca33130e66304d6eb1ae20bb96910416..0000000000000000000000000000000000000000 Binary files a/doc/media/kanon.mid and /dev/null differ diff --git a/doc/media/nixon.aiff b/doc/media/nixon.aiff deleted file mode 100644 index 3a58dc2b50274a478ac59eea4503a2b330250b82..0000000000000000000000000000000000000000 Binary files a/doc/media/nixon.aiff and /dev/null differ diff --git a/doc/tutorials/externals-howto/HOWTO-externals-de.tex b/doc/tutorials/externals-howto/HOWTO-externals-de.tex deleted file mode 100644 index 73b2eedbd1b305f536f3b5c5e2d3bc1320a793cf..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/HOWTO-externals-de.tex +++ /dev/null @@ -1,1806 +0,0 @@ -% format latexg -*- latex -*- - -\documentclass[12pt, a4paper,austrian, titlepage]{article} - - -%% HOWTO write an external for Pd -%% Copyright (c) 2001-2006 by IOhannes m zmölnig -%% -%% Permission is granted to copy, distribute and/or modify this document -%% under the terms of the GNU Free Documentation License, Version 1.2 -%% or any later version published by the Free Software Foundation; -%% with no Invariant Sections, no Front-Cover Texts, and no Back-Cover -%% Texts. A copy of the license is included in the LICENSE.txt file. - -%sprache -\usepackage[latin1]{inputenc} -\usepackage[T1]{fontenc} -\usepackage{babel} - -% add hypertext support (fine for latex2html) -\usepackage{html} - -% add landscape support (for rotating text through 90deg) -\usepackage{lscape} - - -%\begin{latexonly} -% pdf kompatibilität -\newif\ifpdf -\ifx\pdfoutput\undefined - \pdffalse % we are not running PDFLatex -\else - \pdfoutput=1 % yes, we are running PDFLatex - \pdftrue -\fi - -\latexhtml{ -\ifpdf - \usepackage[pdftex]{graphicx} - \pdfcompresslevel=9 -\else - \usepackage{graphicx} -\fi -}{ -\usepackage{graphicx} -} - - -\title{ -HOWTO \\ -write an External \\ -for {\em Pure data} -} - -\author{ -johannes m zmölnig \\ -\\ -{\em -\latexhtml{institut für elektronische musik und akustik} -{\htmladdnormalink{institut für elektronische musik und akustik}{http://iem.at}} -} -} - -\date{} - -\begin {document} -\maketitle - -\hyphenation{Echt-zeit} -\hyphenation{Computer-musik-program-men} -\hyphenation{Echt-zeit-Computer-musik-pro-gramm} - -\begin{abstract} -Pd ist ein graphisches Computermusiksystem in der Tradition von IRCAMs {\em ISPW-max}. - -Obwohl eine Fülle von Funktionen von Pd selbst zur Verfügung gestellt -werden, stößt man doch manchmal an die Grenzen dessen, -das mit diesen Primitiven und ihren Kombinationen möglich ist. - -Deswegen bietet Pd die Möglichkeit, eigene Primitive (``objects'', Objekte) in komplexen -Programmiersprachen wie {\tt C/C++} zu erstellen. - -In diesem Dokument soll beschrieben werden, wie man solche Primitive mit Hilfe der -Sprache {\tt C}, in der auch Pd selbst realisiert wurde, schreibt. -\end{abstract} - - -\vfill -\newpage - -\tableofcontents - -\vfill -\newpage - -\section{Voraussetzungen und Begriffsbestimmungen} - -Pd bezieht sich auf das graphische Echtzeit-Computermusikprogramm von -Miller~S.~Puckette. -{\em Pure data}. - -Zum Verständnis dieses Dokumentes wird der Umgang mit Pd sowie -Verständnis von Programmiertechniken, insbesondere {\tt C} vorausgesetzt. - -Zum Schreiben von eigenen Primitiven wird weiters ein {\tt C}-Compiler, -der dem {\tt ANSI-C}-Standard genügt, notwendig sein. -Solche Compiler sind beispielsweise der {\em Gnu C-Compiler} (gcc) auf linux-Systemen oder -{\em Visual-C++} auf Windows-Systemen. - -\subsection{Klassen, Instanzen und Objekte} -Pd ist in der Programmiersprache {\tt C} geschrieben. -Allerdings ist Pd auf Grund seiner graphischen Natur ein {\em objektorientiertes} System. -Da {\tt C} die Verwendung von Klassen nicht sehr gut unterstützt, ist der resultierende -Quellcode nicht so elegant wie er zum Beispiel unter {\tt C++} wäre. - -Der Ausdruck {\em Klasse} bezieht sich in diesem Dokument auf die Realisierung eines -Konzeptes, bei dem Daten und Manipulatoren eine Einheit bilden. - -Konkrete {\em Instanzen einer Klasse} sind {\em Objekte}. - -\subsection{Internals, Externals und Libraries} -Um Begriffsverwirrungen von vorneherein auszuschließen, seien hier kurz die Ausdrücke -{\em Internal}, {\em External} und {\em Library} erklärt. - -\paragraph{Internal} -Ein {\em Internal} ist eine Klasse, die in Pd eingebaut ist. -Viele Primitive wie ``+'', ``pack'' oder ``sig\~\/`` sind {\em Internals} - -\paragraph{External} -Ein {\em External} ist eine Klasse, die nicht in Pd eingebaut ist und erst zur Laufzeit -nachgeladen wird. -Sind sie einmal im Speicher von Pd, so sind {\em Externals} nicht mehr von {\em Internals} zu -unterscheiden. - -\paragraph{Library} -Eine {\em Library} bezeichnet eine Sammlung von {\em Externals}, -die gemeinsam in eine Binärdatei kompiliert werden. - -{\em Library}-Dateien müssen eine betriebssystemabhängige Namenskonvention einhalten: - -\begin{tabular}{c||c|c|c} -Bibliothek&linux&irix&Win32 \\ -\hline -{\tt my\_lib}&{\tt my\_lib.pd\_linux}&{\tt my\_lib.pd\_irix}& -{\tt my\_lib.dll}\\ -\end{tabular} - -Die einfachste Form einer {\em Library} beinhaltet genau ein {\em External}, -das den selben Name trägt, wie auch die {\em Library} - -Im Gegensatz zu Externals können {\em Libraries} mit bestimmten Befehlen -von Pd importiert werden. -Ist eine {\em Library} importiert worden, -so sind alle {\em Externals}, die sie beinhaltet, -in den Speicher geladen und stehen als Objekte zur Verfügung. - -Pd stellt zwei Methoden zur Verfügung, um {\em Libraries} zu laden: -\begin{itemize} -\item mit der commandline-Option ``{\tt -lib my\_lib}'' -\item durch Kreieren eines Objektes ``{\tt my\_lib}'' -\end{itemize} - -Die erste Methode lädt die {\em Library} sofort beim Starten von Pd. -Dies ist die zu bevorzugende Methode für {\em Libraries}, -die mehrere {\em Externals} beinhalten. - -Die zweite Methode ist für {\em Libraries} zu bevorzugen, die genau -ein {\em External} mit dem selben Namen beinhalten. -Bei der zweiten Methode wird zuerst geprüft, ob eine Klasse namens ``my\_lib'' bereits -in den Speicher geladen ist. -Ist dies nicht der Fall\footnote -{Ist eine solche Klasse bereits im Speicher, wird ein -Objekt namens ``my\_lib'' instanziiert und der Vorgang bricht ab. -Es wird also keine neue {\em Library} geladen. -Man kann daher keine {\em Libraries} mit bereits verwendeten Klassennamen, -wie zum Beispiel ``abs'', laden.} -so werden alle Pfade untersucht, -ob darin eine Datei namens ``{\tt my\_lib.pd\_linux}''\footnote{ -oder einer anderen betriebssystemabhängigen Dateinamenerweiterung (s.o.)} -existiert. -Wird eine solche Datei gefunden, so werden alle in ihr enthaltenen {\em Externals} -in den Speicher geladen. -Danach wird nachgesehen, ob nun eine Klasse namens ``my\_lib'' -als (neu geladenes) {\em External} im Speicher existiert. -Ist dies der Fall, so wird eine Instanz dieser Klasse geschaffen. -Ansonsten wird eine Fehlermeldung ausgegeben, die Instanziierung ist gescheitert. - - -\section{mein erstes External: {\tt helloworld}} -Wie das beim Erlernen von Programmiersprachen so üblich ist, -beginnen wir mit ``Hello world''. - -Ein Objekt soll geschaffen werden, dass jedesmal, wenn es -mit ``bang'' getriggert wird, die Zeile ``Hello world!!'' auf -die Standardausgabe schreibt. - -\subsection{die Schnittstelle zu Pd} -Um ein Pd-External zu schreiben, braucht man eine wohldefinierte Schnittstelle. -Diese wird in der Datei ``m\_pd.h'' zur Verfügung gestellt. - -\begin{verbatim} -#include "m_pd.h" -\end{verbatim} - - -\subsection{eine Klasse und ihr Datenraum} -Als nächstes muß eine neue Klasse vorbereitet und der -Datenraum für diese Klasse definiert werden. - -\begin{verbatim} -static t_class *helloworld_class; - -typedef struct _helloworld { - t_object x_obj; -} t_helloworld; -\end{verbatim} - -\verb+hello_worldclass+ wird der Zeiger auf die neue Klasse. - -Die Struktur \verb+t_helloworld+ (vom Typ \verb+_helloworld+) -stellt den Datenraum der Klasse dar. -Ein unverzichtbares Element ist dabei eine Variable des Type \verb+t_object+. -In ihr werden interne Objekteigenschaften abgelegt, wie zum Beispiel -die Größe der Objekt-Box bei der graphischen Darstellung, aber auch -Daten über Inlets und Outlets. -\verb+t_object+ muss der erste Eintrag in die Struktur sein ! - -Da bei einer einfachen ``Hello world''-Anwendung keine Variablen gebraucht werden, -ist die Struktur ansonsten leer. - -\subsection{Methodenraum} -Zu einer Klasse gehören neben einem Datenraum auch ein Satz von -Manipulatoren (Methoden) mit denen diese Daten manipuliert werden können. - -Wird eine Message an eine Instanz unserer Klasse geschickt, -so wird eine Methoden aufgerufen. -Diese Mehtoden, die die Schnittstelle zum Messagesystem von Pd bilden, -haben grundsätzlich kein Rückgabeargument, sind also vom Typ \verb+void+. - -\begin{verbatim} -void helloworld_bang(t_helloworld *x) -{ - post("Hello world !!"); -} -\end{verbatim} - -Diese Methode hat ein Übergabeargument vom Typ \verb+t_helloworld+, -sodass wir also unseren Datenraum manipulieren könnten. - -Da wir nur ``Hello world!'' ausgeben wollen (und ausserdem unser Datenraum -recht spärlich ist), verzichten wir auf eine Manipulation. - -Mit dem Befehl \verb+post(char *c,...)+ wird eine Meldung an die Standardausgabe -geschickt. -Ein Zeilenumbruch wird automatisch angehängt. -Ansonsten funktioniert \verb+post()+ gleich wie der {\tt C}-Befehl \verb+printf()+. - -\subsection{Generierung einer neuen Klasse} -Um eine neue Klasse zu generieren, müssen Angaben über -den Datenraum und den Methodenraum dieser Klasse -beim Laden einer Library an Pd übergeben werden. - -Wird eine neue Library ``my\_lib'' geladen, -so versucht Pd eine Funktion ``my\_lib\_setup()'' aufzurufen. -Diese Funktion (oder von ihr aufgerufene Funktionen) teilt Pd mit, -welche Eigenschaften die neuen Klassen haben. -Sie wird nur einmal, beim Laden der Library aufgerufen. - -\begin{verbatim} -void helloworld_setup(void) -{ - helloworld_class = class_new(gensym("helloworld"), - (t_newmethod)helloworld_new, - 0, sizeof(t_helloworld), - CLASS_DEFAULT, 0); - - class_addbang(helloworld_class, helloworld_bang); -} -\end{verbatim} - -\paragraph{class\_new} - -Der Befehl \verb+class_new+ kreiert eine neue Klasse und gibt einen Zeiger auf diesen -Prototyp zurück. - -Das erste Argument ist der symbolische Name der Klasse. - -Die nächsten beiden Argumente definieren Konstruktor und Destruktor der Klasse. -Wenn in einen Pd-Patch ein Objekt kreiert wird, -instanziiert der Konstruktor \verb+(t_newmethod)helloworld_new+ diesses Objekt -und initialisiert den Datenraum. -Wird ein Pd-Patch geschlossen oder ein Objekt daraus entfernt, -so gibt der Destruktor, wenn notwendig, dynamisch reservierten Speicher wieder frei. -Der Speicherplatz für den Datenraum selbst wird von Pd automatisch freigegeben. -Deshalb kann in diesem Beispiel auf einen Destruktor verzichtet werden, -folglich wird dieses Argument auf ``0'' gesetzt. - -Damit Pd genug Speicher für den Datenraum allozieren und wieder freigeben kann, -wird die Größe dieser Datenstruktur als viertes Argument übergeben. - -Das fünfte Argument bestimmt, wie Klasseninstanzen graphisch dargestellt werden und -ob sie mit anderen Objekten verknüpfbar sind. -Der Standardwert \verb+CLASS_DEFAULT+ (oder einfacher: ``0'') bezieht sich auf -ein Objekt mit mindestens einem Inlet. -Würde man keinen Eingang wollen (wie zum Beispiel beim Internal ``receive''), -so kann man diesen Wert auf \verb+CLASS_NOINLET+ setzen. - -Die restlichen Argumente definieren die Übergabeargumente eines Objektes und deren Typ. - -Bis zu sechs numerische und symbolische Objektargumente können in beliebiger Reihenfolge -mit \verb+A_DEFFLOAT+ und \verb+A_DEFSYMBOL+ angegeben werden. -Sollen mehr Argumente übergeben werden oder die Atomtyp-Reihenfolge flexibler sein, -so bietet \verb+A_GIMME+ die Übergabe einer beliebigen Liste von Atomen. - -Die Objektargumentliste wird mit ``0'' terminiert. -In unserem Beispiel sind also keine Übergabeargumente für die Klasse vorgesehen. - -\paragraph{class\_addbang} -Jetzt muss zur Klasse noch ein Methodenraum hinzugefügt werden. - -Mit \verb+class_addbang+ wird der durch das erste Argument definierten Klasse -eine Methode für eine ``bang''-Message hinzuzugefügt. -Diese Methode ist das zweite Argument. - - - -\subsection{Konstruktor: Instanziierung eines Objektes} -Jedesmal, wenn in einem Pd-Patch ein Objekt einer Klasse kreiert wird, -schafft der mit \verb+class_new+ angegebene Konstruktor eine neue Instanz der Klasse. - -Der Konstruktor ist immer vom Typ \verb+void *+ - -\begin{verbatim} -void *helloworld_new(void) -{ - t_helloworld *x = (t_helloworld *)pd_new(helloworld_class); - - return (void *)x; -} -\end{verbatim} - -Die Übergabeargumente der Konstruktorfunktion hängen von den mit -\verb+class_new+ angegebenen Objektargumenten ab. - -\begin{tabular}{l|l} -\verb+class_new+-Argument&Konstruktorargument\\ -\hline -\verb+A_DEFFLOAT+&\verb+t_floatarg f+ \\ -\verb+A_DEFSYMBOL+&\verb+t_symbol *s+ \\ -\verb+A_GIMME+&\verb+t_symbol *s, int argc, t_atom *argv+ -\end{tabular} - -Da in diesem Beispiel keine Objektargumente existieren, hat auch -der Konstruktor keine. - -Die Funktion \verb+pd_new+ reserviert Speicher für den Datenraum, initialisiert -die objektinternen Variablen und gibt einen Zeiger auf den Datenraum zurück. - -Der Typ-Cast auf den Datenraum ist notwendig. - -Normalerweise würden im Konstruktor auch die Objektvariablen initialisiert werden. -In diesem Beispiel ist dies aber nicht notwendig. - -Der Konstruktor muss einen Zeiger auf den instanziierten Datenraum zurückgeben. - -\subsection{der Code: \tt helloworld} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *helloworld_class; - -typedef struct _helloworld { - t_object x_obj; -} t_helloworld; - -void helloworld_bang(t_helloworld *x) -{ - post("Hello world !!"); -} - -void *helloworld_new(void) -{ - t_helloworld *x = (t_helloworld *)pd_new(helloworld_class); - - return (void *)x; -} - -void helloworld_setup(void) { - helloworld_class = class_new(gensym("helloworld"), - (t_newmethod)helloworld_new, - 0, sizeof(t_helloworld), - CLASS_DEFAULT, 0); - class_addbang(helloworld_class, helloworld_bang); -} -\end{verbatim} - - -\section{ein komplexes External: {\tt counter}} - -Als nächstes soll ein einfacher Zähler als External geschrieben werden. -Ein ``bang''-Trigger soll den aktuellen Zählerstand am Outlet ausgeben -und anschließend um 1 erhöhen. - -Diese Klasse unterscheidet sich nicht sonderlich von der vorherigen, -ausser dass nun eine interne Variable ``Zählerstand'' benötigt -wird und das Ergebnis nicht mehr auf die Standardausgabe geschrieben sondern -als Message zu einem Outlet geschickt wird. - -\subsection{Variablen eines Objektes} -Ein Zähler braucht natürlich eine Zustandsvariable, -in der der aktueller Zählerstand gespeichert ist. - -Solche zum Objekt gehörigen Zustandsvariablen werden im Datenraum abgelegt. - -\begin{verbatim} -typedef struct _counter { - t_object x_obj; - t_int i_count; -} t_counter; -\end{verbatim} - -Die Ganzzahlvariable \verb+i_count+ beschreibt den Zählerstand. -Natürlich könnte man sie auch als Gleitkommawert realisieren, -doch traditionell werden Zähler ganzzahlig ausgeführt. - -\subsection{Übergabeargumente} -Für einen Zähler ist es durchaus sinnvoll, wenn man den Startwert festlegen kann. -Hier soll der Startwert dem Objekt bei der Kreation übergeben werden. - -\begin{verbatim} -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addbang(counter_class, counter_bang); -} -\end{verbatim} - -Es ist also ein Argument zur Funktion \verb+class_new+ hinzugekommen: - -\verb+A_DEFFLOAT+ teilt mit, dass das Objekt ein Übergabeargument -vom Typ \verb+t_floatarg+ hat. - - - -\subsection{Konstruktor} -Dem Konstruktor kommen nun mehrere neue Aufgaben zu. -Zum ersten muss eine Variable initialisiert werden, -zum anderen muss auch ein Outlet für das Objekt geschaffen werden. -\begin{verbatim} -void *counter_new(t_floatarg f) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - - x->i_count=f; - outlet_new(&x->x_obj, &s_float); - - return (void *)x; -} -\end{verbatim} - -Die Konstruktorfunktion hat jetzt ein Argument fom Typ \verb+t_floatarg+, wie es in -der Setup-Routine \verb+class_new+ deklariert worden ist. -Dieses Argument initialisiert den Zähler. - -Einer neuer Outlet wird mit der Funktion \verb+outlet_new+ geschaffen. -Das erste Argument ist ein Zeiger auf die Objektinterna, -in denen der neue Ausgang geschaffen wird. - -Das zweite Argument ist eine symbolische Typbeschreibung des Ausgangs. -Da der Zähler numerische Werte ausgeben soll, ist er vom Typ ``float''. -Sollte der Ausgang für Messages mit verschiedenen Selectoren verwendet werden, -so ist dieser Wert ``0''. - -\verb+outlet_new+ gibt einen Zeiger auf den neuen Outlet zurück und speichert diesen -Zeiger in der \verb+t_object+-Variablen \verb+x_obj.ob_outlet+. -Wird nur ein Outlet verwendet, muss daher der Zeiger nicht extra im Datenraum gespeichert -werden. -Werden mehrere Outlets verwendet, so müssen diese Zeiger im Datenraum gespeichert werden. - -\subsection{die Zählermethode} -Bei einem Triggerevent soll der alte Zählerstand ausgegeben und um eins inkrementiert werden. - -\begin{verbatim} -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - x->i_count++; - outlet_float(x->x_obj.ob_outlet, f); -} -\end{verbatim} - -Die Funktion \verb+outlet_float+ gibt an dem Outlet, auf den das erste Argument verweist, -eine Gleitkommazahl (zweites Argument) aus. - -Hier wird zuerst der Zählerstand in eine Gleitkomma-Buffervariable gespeichert. -Danach wird er inkrementiert und dann wird erst die Buffervariable ausgegeben. - -Was auf den ersten Blick unnötig erscheint, macht bei näherer Betrachtung Sinn: -Die Buffervariable wurde gleich als \verb+t_float+ realisiert, -da sich \verb+outlet_float+ sowieso einen Gleitkommawert erwartet -und ein Cast unvermeidlich ist. - -Würde der Zählerstand zuerst an den Outlet geschickt werden und -danach erst inkrementiert werden, würde dies unter Umständen zu einem etwas seltsamen -Verhalten führen. -Wenn nämlich der Zählerausgang wieder an den Inlet zurückgeführt würde, der -Zähler sich also selbst triggerte, so würde die Zählermethode erneut -aufgerufen, ohne dass der Zählerstand inkrementiert worden wäre. -Dies ist im Allgemeinen aber unerwünscht. - -Man kann übrigens das gleiche Ergebnis wie hier mit nur einer einzigen Zeile erreichen, -doch sieht man das {\em Reentrant}-Problem dann nicht sehr gut. - -\subsection{der Code: \tt counter} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *counter_class; - -typedef struct _counter { - t_object x_obj; - t_int i_count; -} t_counter; - -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - x->i_count++; - outlet_float(x->x_obj.ob_outlet, f); -} - -void *counter_new(t_floatarg f) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - - x->i_count=f; - outlet_new(&x->x_obj, &s_float); - - return (void *)x; -} - -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addbang(counter_class, counter_bang); -} -\end{verbatim} - - -\section{ein komplexeres External: \tt counter} - -Man kann natürlich auch einen einfache Zähler ein bißchen komplexer gestalten. -Es wäre zum Beispiel sinnvoll, -wenn der Zählerstand auf einen Startwert zurückgesetzt werden könnte, -wenn man Start- und Endwert bestimmen könnte und auch die Schrittweite variabel wäre. - -Bei jedem Zählerüberlauf soll ein zweiter Outlet eine ``bang''-Message schicken und der -Zähler auf den Startwert zurückgesetzt werden. - -\subsection{erweiterter Datenraum} - -\begin{verbatim} -typedef struct _counter { - t_object x_obj; - t_int i_count; - t_float step; - t_int i_down, i_up; - t_outlet *f_out, *b_out; -} t_counter; -\end{verbatim} - -Der Datenraum wurde also erweitert um Variablen für Schrittweite und Start- bzw. Stopwert. -Weiters werden Zeiger auf zwei Outlets zur Verfügung gestellt. - -\subsection{Erweiterung der Klasse} -Da nun die Klassenobjekte verschiedene Messages, wie ``set'' und ``reset'', -verstehen können sollen, mussen der Methodenraum entsprechend erweitert werden. - -\begin{verbatim} - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_GIMME, 0); -\end{verbatim} - -Der Klassengenerator \verb+class_new+ ist um das Objektübergabeargument -\verb+A_GIMME+ erweitert. -Damit kann eine dynamische Anzahl von Argumenten bei der Objektinstanziierung -verwaltet werden. - -\begin{verbatim} - class_addmethod(counter_class, - (t_method)counter_reset, - gensym("reset"), 0); -\end{verbatim} - -\verb+class_addmethod+ fügt einer Klasse eine Methode mit für einen -beliebigen Selector hinzu. - -Das erste Argument ist die Klasse, -zu der die Methode (zweites Argument) hinzugefügt wird. - -Das dritte Argument ist der symbolische Selector, -der mit der Methode assoziiert wird. - -Die restlichen ``0''-terminierten Argumente -beschreiben die Atomliste, die dem Selector folgt. - -\begin{verbatim} - class_addmethod(counter_class, - (t_method)counter_set, gensym("set"), - A_DEFFLOAT, 0); - class_addmethod(counter_class, - (t_method)counter_bound, gensym("bound"), - A_DEFFLOAT, A_DEFFLOAT, 0); -\end{verbatim} - -Eine Methode für den Selector ``set'', gefolgt von einem numerischen Wert, -wird hinzugefügt. - -Für den Selector ``bound'', gefolgt von zwei numerischen Werten, -wird ebenfalls eine Methode zur Klasse hinzugefügt. - -\begin{verbatim} - class_sethelpsymbol(counter_class, gensym("help-counter")); -\end{verbatim} - -Clickt man mit der rechten Maustaste auf ein Pd-Objekt, -so kann man sich einen Hilfe-Patch für die zugehörige Objektklasse anzeigen lasse. -Standardmäßig wird ist dies ein Patch mit dem symbolischen Klassennamen -im Verzeichnis ``{\em doc/5.reference/}'' gesucht. -Mit dem Befehl \verb+class_sethelpsymbol+ kann ein alternativer Patch angegeben werden. - -\subsection{Konstruktion von In- und Outlets} - -Bei der Objektkreation sollten dem Objekt verschiedene Argumente übergeben -werden. - -\begin{verbatim} -void *counter_new(t_symbol *s, int argc, t_atom *argv) -\end{verbatim} -Durch die Argumentendeklaration in der \verb+class_new+-Funktion -mit \verb+A_GIMME+, werden dem Konstruktor folgende Argumente -übergeben: - -\begin{tabular}{c|l} -\verb+t_symbol *s+ & der symbolische Namen,\\ -& mit dem das Objekt kreiert wurde \\ -\verb+int argc+ & die Anzahl, der dem Objekt übergebenen Argumente\\ -\verb+t_atom *argv+ & ein Zeiger auf eine Liste von {\tt argc} Atomen -\end{tabular} - -\begin{verbatim} - t_float f1=0, f2=0; - - x->step=1; - switch(argc){ - default: - case 3: - x->step=atom_getfloat(argv+2); - case 2: - f2=atom_getfloat(argv+1); - case 1: - f1=atom_getfloat(argv); - break; - case 0: - break; - } - if (argc<2)f2=f1; - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; - - x->i_count=x->i_down; -\end{verbatim} - -Werden drei Argumente übergeben, so sollten dies {\em untere Zählergrenze}, -{\em obere Zählergrenze} und {\em Schrittgröße} sein. -Werden nur zwei Argumente übergeben, -so wird die Schrittgröße standardmäßig auf ``1'' gesetzt. -Bei nur einem Argument, sei dies der {\em Startwert} des Zählers, -die {\em Schrittgröße} sei ``1''. - -\begin{verbatim} - inlet_new(&x->x_obj, &x->x_obj.ob_pd, - gensym("list"), gensym("bound")); -\end{verbatim} -Die Funktion \verb+inlet_new+ erzeugt einen neuen ``aktiven'' Inlet. -``Aktiv'' heißt, dass eine Klassenmethode ausgeführt wird, -wenn eine Message in den einen ``aktiven'' Inlet geschickt wird. - -Von der Software-Architektur her ist der erste Inlet immer ``aktiv''. - -Die ersten beiden Argumente der \verb+inlet_new+-Funktion -sind Zeiger auf die Objektinterna und die graphische Darstellung des Objektes. - -Der symbolische Selector, der durch das dritte Argument spezifiziert wird, -wird für diesen Inlet durch einen anderen symbolischen Selector (viertes Argument) -substituiert. - -Durch die Substitution von Selectoren kann eine Message -an einem bestimmten rechten Eingang wie eine Message mit einem bestimmten Selector -am linken Eingang betrachtet werden. - -Dies bedeutet -\begin{itemize} -\item Der substituierende Selector muss mit \verb+class_addmethod+ angegeben werden. -\item Man kann einen bestimmten rechten Eingang simulieren, -indem man dem ersten Eingang eine Message mit dem Selector dieses Eingangs schickt. -\item Es ist nicht möglich, einem rechten Eingang Methoden für mehr als einen Selector -zuzuweisen. Insbesondere ist es nicht möglich, ihm eine allgemeine Methode -für einen beliebigen Selector zuzuweisen. -\end{itemize} - -\begin{verbatim} - floatinlet_new(&x->x_obj, &x->step); -\end{verbatim} -\verb+floatinlet_new+ generiert einen ``passiven'' Inlet für numerische Werte. -``Passive'' Eingänge erlauben, dass ein Speicherplatz bestimmten Typs im -Variablenraum des Objektes von außen direkt beschrieben werden kann. -Dadurch ist zum Beispiel eine Abfrage nach illegalen Eingaben nicht möglich. -Das erste Argument ist dabei ein Zeiger auf die interne Objektinfrastruktur. -Das zweite Argument ist ein Zeiger auf den Speicherplatz, auf den geschrieben wird. - -Es können ``passive'' Eingänge für numerische (Gleitkomma\footnote{ -Deswegen ist der {\tt step}-Wert des Klassendatenraums als {\tt t\_float} realisiert.}) --Werte, symbolische Werte und Pointer geschaffen werden. - -\begin{verbatim} - x->f_out = outlet_new(&x->x_obj, &s_float); - x->b_out = outlet_new(&x->x_obj, &s_bang); -\end{verbatim} - -Die von \verb+outlet_new+ zurückgegebenen Zeiger auf die geschaffenen Outlets, -müssen im Klassendatenraum gespeichert werden, -damit sie später von den Ausgaberoutinen angesprochen werden. - -Die Reihenfolge der Generierung von In- und Outlets ist wichtig, -da sie der Reihenfolge der Ein- und Ausgänge der graphischen Repräsentation -des Objektes entsprechen. - -\subsection{erweiterter Methodenraum} - -Der Methode für die ``bang''-Message muss natürlich der komplexeren Zählerstruktur -genüge tun. - - -\begin{verbatim} -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - t_int step = x->step; - x->i_count+=step; - if (x->i_down-x->i_up) { - if ((step>0) && (x->i_count > x->i_up)) { - x->i_count = x->i_down; - outlet_bang(x->b_out); - } else if (x->i_count < x->i_down) { - x->i_count = x->i_up; - outlet_bang(x->b_out); - } - } - outlet_float(x->f_out, f); -} -\end{verbatim} - -Die einzelnen Outlets werden von den \verb+outlet_...+-Funktionen über -die Zeiger auf diese Ausgänge identifiziert. - -Die übrigen Methoden müssen noch implementiert werden: - -\begin{verbatim} -void counter_reset(t_counter *x) -{ - x->i_count = x->i_down; -} - -void counter_set(t_counter *x, t_floatarg f) -{ - x->i_count = f; -} - -void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2) -{ - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; -} -\end{verbatim} - -\subsection{der Code: \tt counter} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *counter_class; - -typedef struct _counter { - t_object x_obj; - t_int i_count; - t_float step; - t_int i_down, i_up; - t_outlet *f_out, *b_out; -} t_counter; - -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - t_int step = x->step; - x->i_count+=step; - - if (x->i_down-x->i_up) { - if ((step>0) && (x->i_count > x->i_up)) { - x->i_count = x->i_down; - outlet_bang(x->b_out); - } else if (x->i_count < x->i_down) { - x->i_count = x->i_up; - outlet_bang(x->b_out); - } - } - - outlet_float(x->f_out, f); -} - -void counter_reset(t_counter *x) -{ - x->i_count = x->i_down; -} - -void counter_set(t_counter *x, t_floatarg f) -{ - x->i_count = f; -} - -void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2) -{ - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; -} - -void *counter_new(t_symbol *s, int argc, t_atom *argv) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - t_float f1=0, f2=0; - - x->step=1; - switch(argc){ - default: - case 3: - x->step=atom_getfloat(argv+2); - case 2: - f2=atom_getfloat(argv+1); - case 1: - f1=atom_getfloat(argv); - break; - case 0: - break; - } - if (argc<2)f2=f1; - - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; - - x->i_count=x->i_down; - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, - gensym("list"), gensym("bound")); - floatinlet_new(&x->x_obj, &x->step); - - x->f_out = outlet_new(&x->x_obj, &s_float); - x->b_out = outlet_new(&x->x_obj, &s_bang); - - return (void *)x; -} - -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_GIMME, 0); - - class_addbang (counter_class, counter_bang); - class_addmethod(counter_class, - (t_method)counter_reset, gensym("reset"), 0); - class_addmethod(counter_class, - (t_method)counter_set, gensym("set"), - A_DEFFLOAT, 0); - class_addmethod(counter_class, - (t_method)counter_bound, gensym("bound"), - A_DEFFLOAT, A_DEFFLOAT, 0); - - class_sethelpsymbol(counter_class, gensym("help-counter")); -} -\end{verbatim} - - -\section{ein Signal-External: {\tt pan\~\/}} -Signalklassen sind normale Klassen, die zusätzlich Methoden -für Signale bereitstellen. - -Alle Methoden und Konzepte die mit normalen Objektklassen realisierbar sind, -sind also auch mit Signalklassen zuverwirklichen. - -Per Konvention enden die symbolischen Namen mit einer Tilde \~\/. - -Anhand einer Klasse ``pan\~\/`` soll demonstriert werden wie Signalklassen geschrieben -werden können. - -Ein Signal am linken Inlet wird mit einem Signal am zweiten Inlet gemischt. -Der Mischungsgrad wird als \verb+t_float+-Message an einen dritten Eingang festgelegt. - -\subsection{Variablen einer Signalklasse} -Da eine Signalklasse nur eine erweiterte normale Klasse ist, -gibt es keine prinzipielle Unterschiede zwischen den Datenräumen. - -\begin{verbatim} -typedef struct _pan_tilde { - t_object x_obj; - - t_sample f_pan; - t_float f; -} t_pan_tilde; -\end{verbatim} - -Es wird nur eine Variable für den {\em Mischfaktor} der Panningfunktion benötigt. - -Die Variable \verb+f+ wird gebraucht, falls kein Signal am Signalinlet liegt. -Wird dann an diesen Signalinlet ein numerischer Wert als Message geschickt, -so ersetzt dieser das Signal und wird in der Variable \verb+f+ gespeichert. - -\subsection{Signalklassen} - -\begin{verbatim} -void pan_tilde_setup(void) { - pan_tilde_class = class_new(gensym("pan~"), - (t_newmethod)pan_tilde_new, - 0, sizeof(t_pan_tilde), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addmethod(pan_tilde_class, - (t_method)pan_tilde_dsp, gensym("dsp"), 0); - CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f); -} -\end{verbatim} - -Jeder Signalklasse muss eine Methode für die Signalverarbeitung zugeordnet werden. -Wenn die Audioengine von Pd gestartet wird, wird allen Objekten eine -Message mit dem Selector ``\verb+dsp+'' geschickt. -Alle Klassen, die eine Methode für die ``dsp''-Message haben, sind Signalklassen. - -Signalklassen, die Signal-Inlets zur Verfügung stellen wollen, -müssen dies mit dem \verb+CLASS_MAINSIGNALIN+-Makro anmelden. -Dadurch ist der erste Inlet als Signalinlet deklariert. -\verb+t_float+-Messages können nicht mehr an einen solchen Eingang -gesendet werden. - -Das erste Argument des Makros ist ein Zeiger auf die Signalklasse. -Das zweite Argument ist der Typ des Datenraums der Klasse. -Das dritte Argument ist eine Dummy-Variable aus dem Datenraum, die gebraucht wird, -um bei nicht vorhandenen Signalen am Signalinlet diese durch \verb+t_float+-Messages -einfach ersetzen zu können. - -\subsection{Konstruktion von Signal-In- und Outlets} - -\begin{verbatim} -void *pan_tilde_new(t_floatarg f) -{ - t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class); - - x->f_pan = f; - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - floatinlet_new (&x->x_obj, &x->f_pan); - - outlet_new(&x->x_obj, &s_signal); - - return (void *)x; -} -\end{verbatim} - -Zusätzliche Signal-Eingänge werden normal mit der Routine \verb+inlet_new+ -hinzugefügt. -Die letzen beiden Argumente sind dann jeweils ein Verweis auf den symbolischen Selector -``signal'' in der lookup-Tabelle. - -Signal-Outlets werden ebenfalls wie Message-Outlets generiert, deren Outlet mit dem -Selector ``signal'' versehen ist. - - -\subsection{DSP-Methode} -Wenn die Audio-Engine von Pd eingeschalten wird, -so teilen ihr alle Signal-Objekte mit, -welche Methode von ihrer Klasse zur digitalen Signalverarbeitung herangezogen werden soll. - -Die ``DSP''-Methode hat als Argumente einen Zeiger auf den Klassendatenraum und -einen Zeiger auf ein Array von Signalen. - -Die Signale im Array sind so angeordnet, dass sie am graphischen Objekt -im Uhrzeigersinn gelesen werden.\footnote{ -Sofern linke und rechte Ein- und Ausgangssignale vorhanden sind, gilt also: -Zuerst kommt das linke Eingangssignal, danach die rechten Eingangssignale; -nach den rechten Ausgangssignalen kommt das linke Ausgangssignal. -} - -\begin{verbatim} -void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp) -{ - dsp_add(pan_tilde_perform, 5, x, - sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); -} -\end{verbatim} - -\verb+dsp_add+ fügt eine ``Perform''-Routine (erstes Argument) zum DSP-Baum hinzu. -Das zweite Argument ist die Anzahl der nachfolgenden Zeiger auf diverse Variablen. -Welche Zeiger auf welche Variablen übergeben werden, unterliegt keiner Beschränkung. - -sp[0] bezeichnet hier das erste Eingangssignal, sp[1] das zweite Eingangssignal, -sp[3] das Ausgangssignal. - -Die Struktur \verb+t_signal+ enthält einen Zeiger auf den -zugehörigen Signalvektor \verb+.s_vec+ (ein Array von Samples \verb+t_sample+), -sowie die Länge dieses Signalvektors \verb+.s_n+. -Da innerhalb eines Patches alle Signalvektoren die gleiche Länge haben, -genügt es, die Länge eines dieser Vektoren abzufragen. - -\subsection{perform-Routine} -Die perform-Routine ist das eigentliche DSP-Herzstück einer Signalklasse. - -Ihr wird ein Zeiger auf ein Integer-Array übergeben. -In diesem Array sind die Zeiger gespeichert, die mit \verb+dsp_add+ übergeben wurden. -Sie müssen auf ihren ursprünglichen Typ zurückgecastet werden. - -Die perform-Routine muß einen Zeiger auf Integer zurückgeben, der hinter den -Speicherplatz zeigt, in dem die eigenen Zeiger gespeichert sind. -Dies bedeutet, dass das Rückgabeargument gleich dem Übergabeargument plus der -Anzahl der eigenen Zeigervariablen (wie sie als zweites Argument in -\verb+dsp_add+ angegeben wurde) plus eins. - -\begin{verbatim} -t_int *pan_tilde_perform(t_int *w) -{ - t_pan_tilde *x = (t_pan_tilde *)(w[1]); - t_sample *in1 = (t_sample *)(w[2]); - t_sample *in2 = (t_sample *)(w[3]); - t_sample *out = (t_sample *)(w[4]); - int n = (int)(w[5]); - - t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan; - - while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan; - - return (w+6); -} -\end{verbatim} - -In der \verb+while+-Schleife wird jedes Sample der Signalvektoren einzeln -abgearbeitet. - -Eine Optimierungsroutine bei der Erstellung des DSP-Baumes wird darauf geachtet, -keine unnötigen Kopieroperationen durchzuführen. -Es kann daher geschehen, dass ein Eingangs- und ein Ausgangssignal an der -gleichen Stelle im Speicher stehen. -Es ist daher in solchem Falle darauf zu achten, -dass nicht in das Ausgangssignal geschrieben wird, -bevor dort das Eingangssignal ausgelesen wurde. - -\subsection{der Code: \tt pan\~\/} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *pan_tilde_class; - -typedef struct _pan_tilde { - t_object x_obj; - t_sample f_pan; - t_sample f; -} t_pan_tilde; - -t_int *pan_tilde_perform(t_int *w) -{ - t_pan_tilde *x = (t_pan_tilde *)(w[1]); - t_sample *in1 = (t_sample *)(w[2]); - t_sample *in2 = (t_sample *)(w[3]); - t_sample *out = (t_sample *)(w[4]); - int n = (int)(w[5]); - t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan; - - while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan; - - return (w+6); -} - -void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp) -{ - dsp_add(pan_tilde_perform, 5, x, - sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); -} - -void *pan_tilde_new(t_floatarg f) -{ - t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class); - - x->f_pan = f; - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - floatinlet_new (&x->x_obj, &x->f_pan); - outlet_new(&x->x_obj, &s_signal); - - return (void *)x; -} - -void pan_tilde_setup(void) { - pan_tilde_class = class_new(gensym("pan~"), - (t_newmethod)pan_tilde_new, - 0, sizeof(t_pan_tilde), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addmethod(pan_tilde_class, - (t_method)pan_tilde_dsp, gensym("dsp"), 0); - CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f); -} -\end{verbatim} - - - - -\vfill -\newpage -\begin{appendix} - -\section{das Message-System von \em pd} -Nicht-Audio-Daten werden über ein Message-System verteilt. -Jede Message besteht aus einem ``Selector'' und einer Liste von Atomen. - -\subsection{Atome} - -Es gibt drei Arten von Atomen: -\begin{itemize} -\item {\em A\_FLOAT}: ein numerischer Wert (Gleitkommazahl) -\item {\em A\_SYMBOL}: ein symbolischer Wert (String) -\item {\em A\_POINTER}: ein Zeiger -\end{itemize} - -Numerische Werte werden immer als Floating-Point-Werte (\verb+double+) dargestellt, -auch wenn es sich um Ganzzahlwerte handelt. - -Jedes Symbol wird aus Performancegründen in einer lookup-Tabelle abgelegt. -Der Befehl \verb+gensym+ speichert, wenn nötig, -einen String in dieser Symboltabelle und gibt seine Addresse in der Tabelle zurück. - -Atome vom Typ {\em A\_POINTER} haben in der Praxis -(für einfache Externals) eher untergeordnete Bedeutung. - -Der Typ eines Atoms \verb+a+ wird im Strukturelement \verb+a.a_type+ gespeichert. - -\subsection{Selectoren} - -Der Selector ist ein Symbol und bestimmt, welchen Typ eine Message hat. -Es gibt fünf vordefinierte Selectoren: -\begin{itemize} -\item ``{\tt bang}'' bezeichnet ein Triggerevent. -Die Message besteht nur aus dem Selector und enthält keine Liste von Atomen. -\item ``{\tt float}'' bezeichnet einen numerischen Wert. Die Liste enthält nur ein Atom. -\item ``{\tt symbol}'' bezeichnet einen symbolischen Wert. Die Liste enthält nur ein Atom. -\item ``{\tt pointer}'' bezeichnet einen Zeiger. Die Liste enthält nur ein Atom. -\item ``{\tt list}'' bezeichnet eine Liste von mehreren Atomen. -\end{itemize} - -Da die Symbole für diese Selectoren relativ häufig verwendet werden, -kann man deren Symboltabellen-Adresse auch direkt, -ohne den Umweg über \verb+gensym+ abfragen: - -\begin{tabular}{l||l|l} -Selector&lookup-Routine&lookup-Addresse\\ -\hline -\tt bang &\verb+gensym("bang")+ & \verb+&s_bang+ \\ -\tt float &\verb+gensym("float")+ & \verb+&s_float+ \\ -\tt symbol &\verb+gensym("symbol")+ & \verb+&s_symbol+ \\ -\tt pointer &\verb+gensym("pointer")+ & \verb+&s_pointer+ \\ -\tt list &\verb+gensym("list")+ & \verb+&s_list+ \\ ---- (Signal) &\verb+gensym("signal")+&\verb+&s_symbol+ -\end{tabular} - -Es können auch andere Selectoren verwendet werden, -doch muss dann die Empfängerklasse entweder selbst eine Methode -für diesen Selector zur verfügung stellen, -oder eine Methode für ``anything'', also jeden beliebigen Selector, anbieten. - -Messages die ohne Selector sofort mit einem Zahlenwert beginnen, werden automatisch -entweder als numerischer Wert (nur ein Atom) oder als Liste (mehrere Atome) erkannt. - -Zum Beispiel sind also die Messages ``\verb+12.429+'' und ``\verb+float 12.429+'' ident. -Ebenfalls ident sind auch die Listen-Messages -``\verb+list 1 kleines Haus+'' und ``\verb+1 kleines Haus+''. - -\section{Pd-Typen} -Da Pd auf mehreren Plattformen benutzt wird, -werden viele gewöhnliche Variablentypen, wie \verb|int|, neu definiert. -Um portablen Code zu schreiben ist es daher angebracht, die von Pd bereitgestellten -Typen zu verwenden. - -Weiters gibt es viele vordefinierte Typen, -die das Leben des Programmierers vereinfachen sollten. -Pd-Typen beginnen im Allgemeinen mit \verb|t_|. - -\begin{tabular}{c|l} -Pd-Type & Beschreibung \\ -\hline\hline -\verb+t_atom+& Atom \\ -\verb+t_float+ & Gleitkomma-Zahl \\ -\verb+t_symbol+ & Symbol \\ -\verb+t_gpointer+ & Zeiger (auf graphische Objekte) \\ -\hline -\verb+t_int+ & Ganzzahl \\ -\verb+t_signal+ & Struktur auf ein Signal \\ -\verb+t_sample+ & Audio-Signalwert (Gleitkomma)\\ -\verb+t_outlet+ & Outlet eines Objekts \\ -\verb+t_inlet+ & Inlet eines Objekts \\ -\verb+t_object+ & Objekt-Interna \\ -\hline -\verb+t_class+ & eine Pd-Klasse \\ -\verb+t_method+ & Zeiger auf Klassenmethode \\ -\verb+t_newmethod+ & Zeiger auf Klasseninstanziierungsmethode (new-Routine) \\ -\end{tabular} - - -\section{Wichtige Funktionen aus ``m\_pd.h''} -\subsection{Funktionen: Atome} - -\subsubsection{SETFLOAT} -\begin{verbatim} -SETFLOAT(atom, f) -\end{verbatim} -Dieses Makro setzt den Typ von \verb+atom+ auf \verb+A_FLOAT+ -und setzt den numerischen Wert dieses Atoms auf \verb+f+. - -\subsubsection{SETSYMBOL} -\begin{verbatim} -SETSYMBOL(atom, s) -\end{verbatim} -Dieses Makro setzt den Typ von \verb+atom+ auf \verb+A_SYMBOL+ -und setzt den symbolischen Wert dieses Atoms auf \verb+s+. - -\subsubsection{SETPOINTER} -\begin{verbatim} -SETPOINTER(atom, pt) -\end{verbatim} -Dieses Makro setzt den Typ von \verb+atom+ auf \verb+A_POINTER+ -und setzt den Zeiger-Wert dieses Atoms auf \verb+pt+. - -\subsubsection{atom\_getfloat} -\begin{verbatim} -t_float atom_getfloat(t_atom *a); -\end{verbatim} -Wenn der Typ des Atoms \verb+a+ \verb+A_FLOAT+ ist, wird dessen numerischer Wert, -ansonsten ``0.0'' zurückgegeben. - -\subsubsection{atom\_getfloatarg} -\begin{verbatim} -t_float atom_getfloatarg(int which, int argc, t_atom *argv) -\end{verbatim} -Wenn das Atom, -das in der Atomliste \verb+argv+ mit der Länge \verb+argc+ an der Stelle \verb+which+ -zu finden ist, -vom Typ \verb+A_FLOAT+ ist, wird dessen numerischer Wert, -ansonsten ``0.0'' zurückgegeben. - -\subsubsection{atom\_getint} -\begin{verbatim} -t_int atom_getint(t_atom *a); -\end{verbatim} -Wenn der Typ des Atoms \verb+a+ \verb+A_FLOAT+ ist, wird dessen numerischer -Wert als Ganzzahlwert, ansonsten ``0'' zurückgegeben. - -\subsubsection{atom\_getsymbol} -\begin{verbatim} -t_symbol atom_getsymbol(t_atom *a); -\end{verbatim} -Wenn der Typ des Atoms \verb+a+ \verb+A_SYMBOL+ ist, wird ein Zeiger -auf dessen Symbol ansonsten auf das Symbol ``float'' zurückgegeben. - -\subsubsection{atom\_gensym} -\begin{verbatim} -t_symbol *atom_gensym(t_atom *a); -\end{verbatim} -Wenn der Typ des Atoms \verb+a+ \verb+A_SYMBOL+ ist, wird ein Zeiger -auf dessen Symbol zurückgegeben. - -Atome anderen Typs werden zuerst ``sinnvoll'' in Strings umgewandelt. -Diese Strings werden, falls nötig, in die Symbol-Tabelle eingetragen. -Die Zeiger auf das Symbol wird zurückgegeben. - - -\subsubsection{atom\_string} -\begin{verbatim} -void atom_string(t_atom *a, char *buf, unsigned int bufsize); -\end{verbatim} -Konvertiert ein Atom \verb+a+ in einen {\tt C}-String \verb+buf+. -Der char-Buffer muss selbst reserviert und seine Länge in \verb+bufsize+ angegeben werden. - -\subsubsection{gensym} -\begin{verbatim} -t_symbol *gensym(char *s); -\end{verbatim} -Prüft, ob für den C-String \verb+*s+ bereits ein Eintrag in der Symbol-lookup-Tabelle -vorhanden ist. -Ist noch kein Eintrag vorhanden, so wird einer angelegt. -Ein Zeiger auf das Symbol in der Tabelle wird zurückgegeben. - - -\subsection{Funktionen: Klassen} -\subsubsection{class\_new} -\begin{verbatim} -t_class *class_new(t_symbol *name, - t_newmethod newmethod, t_method freemethod, - size_t size, int flags, - t_atomtype arg1, ...); -\end{verbatim} -Generiert eine neue Klasse mit dem symbolischen Namen \verb+name+. - -\verb+newmethod+ ist eine Konstruktorfunktion, -die eine Instanz der Klasse konstruiert und einen Zeiger auf diese Instanz zurückgibt. - -Wird manuell dynamischer Speicher reserviert, -so muss dieser bei Zerstörung eines Objektes -mit der Destruktormethode \verb+freemethod+ (kein Rückgabeargument) -wieder freigegeben werden. - -\verb+size+ ist statische die Größe des Klassendatenraumes, -die mit der Funktion \verb+sizeof(t_mydata)+ berechnet werden kann. - -\verb+flags+ bestimmen das Aussehen des graphischen Objektes. -Eine beliebige Kombination folgender Flags ist möglich: - -\begin{tabular}{l|l} -Flag&Bedeutung\\ -\hline -\verb+CLASS_DEFAULT+ &Ein normales Objekt mit einem Inlet \\ -\verb+CLASS_PD+ & \em Objekte ohne Graphikdarstellung\\ -\verb+CLASS_GOBJ+ & \em reine Graphikobjekte (wie Arrays, Graphen,...)\\ -\verb+CLASS_PATCHABLE+ & \em normales Objekt (mit einem Inlet) \\ -\verb+CLASS_NOINLET+ & Der standardmäßige Inlet wird unterdrückt \\ -\end{tabular} - -Flags, deren Bedeutung {\em kursiv} gedruckt ist, -haben geringe Bedeutung beim Schreiben von Externals. - -Die restlichen Argumente \verb+arg1,...+ definieren -die Typen die Übergabeargumente bei der Objektkreation. -Höchstens sechs typgeprüfte Argumente können einem Objekt übergeben werden. -Die Argumententypeliste wird ``0'' terminiert. - -Mögliche Argumententypen sind: - -\begin{tabular}{l|l} -\verb+A_DEFFLOAT+ & ein numerischer Wert \\ -\verb+A_DEFSYMBOL+ & ein symbolischer Wert \\ -\verb+A_GIMME+ & eine Atomliste beliebiger Länge und Typen \\ -\end{tabular} - -Sollten mehr als sechs Argumente übergeben werden, muss man -\verb+A_GIMME+ verwenden und eine händische Typprüfung durchführen. - -\subsubsection{class\_addmethod} -\begin{verbatim} -void class_addmethod(t_class *c, t_method fn, t_symbol *sel, - t_atomtype arg1, ...); -\end{verbatim} -Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ für -eine Message mit dem Selector \verb+sel+ hinzu. - -Die restlichen Argumente \verb+arg1,...+ definieren -die Typen der Atomliste die dem Selector folgt. -Höchstens sechs typgeprüfte Argumente angegeben werden. -Sollten mehr als sechs Argumente übergeben werden, muss man -\verb+A_GIMME+ verwenden und eine händische Typprüfung durchführen. - -Die Argumententypeliste wird ``0'' terminiert. - -Mögliche Argumententypen sind: - -\begin{tabular}{l|l} -\verb+A_DEFFLOAT+ & ein numerischer Wert \\ -\verb+A_DEFSYMBOL+ & ein symbolischer Wert \\ -\verb+A_POINTER+ & eine Zeiger \\ -\verb+A_GIMME+ & eine Atomliste beliebiger Länge und Typen \\ -\end{tabular} - -\subsubsection{class\_addbang} -\begin{verbatim} -void class_addbang(t_class *c, t_method fn); -\end{verbatim} -Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ -für eine ``bang''-Message hinzu. -Die ``bang''-Methode hat als Übergabeargument einen Zeiger auf den Klassendatenraum: - -\verb+void my_bang_method(t_mydata *x);+ - -\subsubsection{class\_addfloat} -\begin{verbatim} -void class_addfloat(t_class *c, t_method fn); -\end{verbatim} -Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ -für eine ``float''-Message hinzu. -Die ``float''-Methode hat als Übergabeargument einen Zeiger auf den Klassendatenraum und -ein Gleitkommaargument: - -\verb+void my_float_method(t_mydata *x, t_floatarg f);+ - -\subsubsection{class\_addsymbol} -\begin{verbatim} -void class_addsymbol(t_class *c, t_method fn); -\end{verbatim} -Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ -für eine ``symbol''-Message hinzu. -Die ``symbol''-Methode hat als Übergabeargument einen Zeiger auf den Klassendatenraum und -einen Zeiger auf das übergebene Symbol: - -\verb+void my_symbol_method(t_mydata *x, t_symbol *s);+ - -\subsubsection{class\_addpointer} -\begin{verbatim} -void class_addpointer(t_class *c, t_method fn); -\end{verbatim} -Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ -für eine ``pointer''-Message hinzu. -Die ``pointer''-Methode hat als Übergabeargument einen Zeiger -auf den Klassendatenraum und einen Zeiger auf einen Pointer: - -\verb+void my_pointer_method(t_mydata *x, t_gpointer *pt);+ - -\subsubsection{class\_addlist} -\begin{verbatim} -void class_addlist(t_class *c, t_method fn); -\end{verbatim} -Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ -für eine ``list''-Message hinzu. -Die ``list''-Methode hat als Übergabeargument neben einem Zeiger -auf den Klassendatenraum einen Zeiger auf das Selectorsymbol -(immer \verb+&s_list+), -die Anzahl der Atome in der Liste sowie einen Zeiger auf die Atomliste: - -\verb+void my_list_method(t_mydata *x,+ - -\verb+ t_symbol *s, int argc, t_atom *argv);+ - - -%\begin{verbatim} -%void my_list_method(t_mydata *x, -% t_symbol *s, int argc, t_atom *argv); -%\end{verbatim} - - - -\subsubsection{class\_addanything} -\begin{verbatim} -void class_addanything(t_class *c, t_method fn); -\end{verbatim} -Fügt der Klasse, auf die \verb+c+ zeigt, die Methode \verb+fn+ -für eine beliebige Message hinzu. -Die anything-Methode hat als Übergabeargument neben einem Zeiger -auf den Klassendatenraum einen Zeiger auf das Selectorsymbol, -die Anzahl der Atome in der Liste sowie einen Zeiger auf die Atomliste: - - -\verb+void my_any_method(t_mydata *x,+ - -\verb+ t_symbol *s, int argc, t_atom *argv);+ - - -%\begin{verbatim} -%void my_any_method(t_mydata *x, -% t_symbol *s, int argc, t_atom *argv); -%\end{verbatim} - -\subsubsection{class\_addcreator} -\begin{verbatim} - void class_addcreator(t_newmethod newmethod, t_symbol *s, - t_atomtype type1, ...); -\end{verbatim} -Fügt zu einem Konstruktor \verb+newmethod+ ein zum Klassennamen alternatives -Kreatorsymbol \verb+s+ hinzu. -Dadurch können Objekte mit dem richtigen Klassennamen und einem Aliasnamen -(zum Beispiel eine Abkürzung, wie das Internal ``float'' bzw. ``f'') kreiert werden. - -Die ``0''-terminierte Typenliste entspricht der von \verb+class_new+. - -\subsubsection{class\_sethelpsymbol} -\begin{verbatim} -void class_sethelpsymbol(t_class *c, t_symbol *s); -\end{verbatim} - -Clickt man mit der rechten Maustaste auf ein Pd-Objekt, -so kann man sich einen Hilfe-Patch für die zugehörige Objektklasse anzeigen lasse. -Standardmäßig wird ist dies ein Patch mit dem symbolischen Klassennamen -im Verzeichnis ``{\em doc/5.reference/}'' gesucht. - -Für die Klasse, auf die \verb+c+ zeigt, wird der Name des Hilfepatches auf den -symbolischen Wert \verb+s+ geändert. - -Dadurch können sich mehrere verwandte Klassen einen Hilfepatch teilen. - -Pfadangaben erfolgen relativ zum Standardhilfepfad {\em doc/5.reference/}. - -\subsubsection{pd\_new} -\begin{verbatim} -t_pd *pd_new(t_class *cls); -\end{verbatim} -Generiert eine neue Instanz der Klasse \verb+cls+ und gibt einen Zeiger auf diese -Instanz zurück. - -\subsection{Funktionen: In- und Outlets} -Alle Inlet- und Outletroutinen benötigen eine Referenz auf die Objektinterna -der Klasseninstanz. -Die notwendige Variable vom Typ \verb+t_object+ im Datenraum wird bei der -Objektinstanziierung initialisiert. -Diese Variable muß als \verb+owner+-Objekt den Inlet- und Outletroutinen übergeben werden. - -\subsubsection{inlet\_new} -\begin{verbatim} -t_inlet *inlet_new(t_object *owner, t_pd *dest, - t_symbol *s1, t_symbol *s2); -\end{verbatim} -Generiert einen zusätzlichen ``aktiven'' Inlet des Objektes, auf das \verb+owner+ zeigt. -\verb+dest+ zeigt im Allgemeinen auf ``\verb+owner.ob_pd+''. - -Der Selector \verb+s1+ am neuen Inlet, wird durch den Selector \verb+s2+ substituiert. - -Tritt also eine Message mit dem Selector \verb+s1+ am neuen Inlet auf, -wird die Klassenmethode für den Selector \verb+s2+ ausgeführt. - -Dies bedeutet -\begin{itemize} -\item Der substituierende Selector muss mit \verb+class_addmethod+ angegeben werden. -\item Man kann einen bestimmten rechten Eingang simulieren, -indem man dem ersten Eingang eine Message mit dem Selector dieses Eingangs schickt. - -Verwendet man ein leeres Symbol (\verb+gensym("")+) als Selector, -so erreicht man, dass der rechte Eingang nicht über den ersten angesprochen werden kann. -\item Es ist nicht möglich, einem rechten Eingang Methoden für mehr als einen Selector -zuzuweisen. Insbesondere ist es nicht möglich, ihm eine allgemeine Methode -für einen beliebigen Selector zuzuweisen. -\end{itemize} - -\subsubsection{floatinlet\_new} -\begin{verbatim} -t_inlet *floatinlet_new(t_object *owner, t_float *fp); -\end{verbatim} -Schafft einen neuen ``passiven'' Eingang für das Objekt, auf das \verb+owner+ zeigt, -der es erlaubt, einen numerischen Wert von außen direkt auf einen -Speicherplatz \verb+fp+ zu schreiben, ohne eine eigene Methode aufzurufen. - -\subsubsection{symbolinlet\_new} -\begin{verbatim} -t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp); -\end{verbatim} -Schafft einen neuen ``passiven'' Eingang für das Objekt, auf das \verb+owner+ zeigt, -der es erlaubt, einen symbolischen Wert von außen direkt auf einen -Speicherplatz \verb+sp+ zu schreiben, ohne eine eigene Methode aufzurufen. - -\subsubsection{pointerinlet\_new} -\begin{verbatim} -t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp); -\end{verbatim} -Schafft einen neuen ``passiven'' Eingang für das Objekt, auf das \verb+owner+ zeigt, -der es erlaubt, einen Zeigerwert von außen direkt auf einen -Speicherplatz \verb+gp+ zu schreiben, ohne eine eigene Methode aufzurufen. - -\subsubsection{outlet\_new} -\begin{verbatim} -t_outlet *outlet_new(t_object *owner, t_symbol *s); -\end{verbatim} -Generiert einen neuen Ausgang für das Objekt, auf das \verb+owner+ zeigt. -Das Symbol, auf das \verb+s+ zeigt, zeigt den Typ des Ausgangs an. - -\begin{tabular}{c|l||l} -Symbolwert & Symboladresse & Outlet-Typus \\ -\hline\hline -``bang'' & \verb+&s_bang+ & Message (Bang)\\ -``float'' & \verb+&s_float+ & Message (Float)\\ -``symbol'' & \verb+&s_symbol+ & Message (Symbol) \\ -``pointer'' & \verb+&s_gpointer+ & Message (List)\\ -``list'' & \verb+&s_list+ & Message \\ ---- & 0 & Message \\ -\hline -``signal'' & \verb+&s_signal+ & Signal \\ -\end{tabular} - -Zwischen den verschiedenen Message-Outlet-Typen gibt es keinen Unterschied. -Allerdings macht es den Code leichter lesbar, -wenn schon bei der Outlet-Generierung angezeigt wird, wozu der Ausgang verwendet wird. -Für allgemeine Message-Outlets verwendet man einen ``0''-Pointer. - -Variablen vom Typ \verb+t_object+ stellen einen Zeiger auf einen Outlet zur Verfügung. -Bei der Generierung eines neuen Outlets, -wird seine Addresse in der Objektvariablen \verb+(*owner).ob_outlet+ gespeichert. - -Werden mehrere Message-Ausgänge benötigt, müssen die Outletzeiger, -die von \verb+outlet_new+ zurückgegeben werden, manuell im Datenraum gespeichert werden, -um die jeweiligen Ausgänge ansprechen zu können. - -\subsubsection{outlet\_bang} -\begin{verbatim} -void outlet_bang(t_outlet *x); -\end{verbatim} -Gibt am Outlet, auf den \verb+x+ zeigt, eine ``bang''-Message aus. - -\subsubsection{outlet\_float} -\begin{verbatim} -void outlet_float(t_outlet *x, t_float f); -\end{verbatim} -Gibt am Outlet, auf den \verb+x+ zeigt, eine ``float''-Message mit dem -numerischen Wert \verb+f+ aus. - -\subsubsection{outlet\_symbol} -\begin{verbatim} -void outlet_symbol(t_outlet *x, t_symbol *s); -\end{verbatim} -Gibt am Outlet, auf den \verb+x+ zeigt, eine ``symbol''-Message mit dem -symbolischen Wert von \verb+s+ aus. - -\subsubsection{outlet\_pointer} -\begin{verbatim} -void outlet_pointer(t_outlet *x, t_gpointer *gp); -\end{verbatim} -Gibt am Outlet, auf den \verb+x+ zeigt, eine ``pointer''-Message mit dem -Zeiger \verb+gp+ aus. - -\subsubsection{outlet\_list} -\begin{verbatim} -void outlet_list(t_outlet *x, - t_symbol *s, int argc, t_atom *argv); -\end{verbatim} -Gibt am Outlet, auf den \verb+x+ zeigt, eine ``list''-Message mit -\verb+argc+ Atomen aus. -\verb+argv+ zeigt auf das erste Atom der Liste. - -Unabhängig davon, auf welches Symbol \verb+s+ zeigt, wird der Selector -``list'' der Liste vorangestellt. - -Aus Lesbarkeitsgründen sollte man aber trotzdem einen Zeiger auf das -Symbol ``list'' (\verb+gensym("list")+ oder \verb+&s_list+) angeben. - -\subsubsection{outlet\_anything} -\begin{verbatim} -void outlet_anything(t_outlet *x, - t_symbol *s, int argc, t_atom *argv); -\end{verbatim} -Gibt am Outlet, auf den \verb+x+ zeigt, eine Message mit -dem Selector, auf den \verb+s+ zeigt, aus. -Dem Selector folgen \verb+argc+ Atome. -\verb+argv+ zeigt auf das erste Atom dieser Liste. - - -\subsection{Funktionen: DSP} -Soll eine Klasse Methoden zur digitalen Signalsverarbeitung zur Verfügung stellen, -so muss ihr eine Methode für den Selector ``dsp'' hinzugefügt werden. - -Wird die Audio-Engine gestartet, so werden alle Objekte, die eine ``dsp''-Methode -zur Verfügung stellen, als Instanzen von Signalklassen identifiziert. - -\paragraph{DSP-Methode} - -\begin{verbatim} -void my_dsp_method(t_mydata *x, t_signal **sp) -\end{verbatim} - -In der ``dsp''-Methode wird mit der Funktion \verb+dsp_add+ die -Klassenroutine für Signalverarbeitung in den DSP-Baum eingebunden. - -Neben dem eigenen Datenraum \verb+x+, wird auch ein Array von Signalen übergeben. -Die Signale im Array sind so angeordnet, dass sie am graphischen Objekt -im Uhrzeigersinn gelesen werden. - -Sofern je zwei Ein- und Ausgangssignale vorhanden sind, gilt also: - -\begin{tabular}{c|r} -Zeiger & auf Signal \\ -\hline\hline -sp[0] & linkes Eingangssignal \\ -sp[1] & rechtes Eingangssignal \\ -sp[2] & rechtes Ausgangssignal \\ -sp[3] & linkes Ausgangssignal \\ -\end{tabular} - -Die Signalstruktur enthält unter anderem: - -\begin{tabular}{c|l} -Strukturelement & Bedeutung \\ -\hline -\verb+s_n+ & Länge des Signalvektors \\ -\verb+s_vec+ & Zeiger auf den Signalvektor \\ -\end{tabular} - -Der Signalvektor ist ein Array auf Samples vom Typ \verb+t_sample+. - -\paragraph{Perform-Routine} -\begin{verbatim} -t_int *my_perform_routine(t_int *w) -\end{verbatim} - -Der Perform-Routine die mit \verb+class_add+ in den DSP-Baum eingefügt wurde, -wird ein Zeiger \verb+w+ auf ein (Integer-)Array übergeben. -In diesem Array sind die Zeiger gespeichert, die mit \verb+dsp_add+ übergeben wurden. -Sie müssen auf ihren ursprünglichen Typ zurückgecastet werden. -Der erste Zeiger ist an der Stelle \verb+w[1]+ gespeichert !!! - -Die perform-Routine muß einen Zeiger auf Integer zurückgeben, der hinter den -Speicherplatz zeigt, in dem die eigenen Zeiger gespeichert sind. -Dies bedeutet, dass das Rückgabeargument gleich dem Übergabeargument plus der -Anzahl der eigenen Zeigervariablen (wie sie als zweites Argument in -\verb+dsp_add+ angegeben wurde) plus eins. - - - - -\subsubsection{CLASS\_MAINSIGNALIN} -\begin{verbatim} -CLASS_MAINSIGNALIN(<class_name>, <class_data>, <f>); -\end{verbatim} -Das Makro \verb+CLASS_MAINSIGNALIN+ meldet an, dass die Klasse -Signal-Inlets brauchts. - -Das erste Argument des Makros ist ein Zeiger auf die Signalklasse. -Das zweite Argument ist der Typ des Datenraums der Klasse. -Das dritte Argument ist eine (Dummy-)Gleitkomma-Variable aus dem Datenraum, -die gebraucht wird, um bei nicht vorhandenen Signalen am Signalinlet, -``float''-Messages wie Signale behandeln zu können. - -An so kreierten Signaleingängen können daher keine zusätzlichen ``float''-Messages -geschickt werden. - -\subsubsection{dsp\_add} -\begin{verbatim} -void dsp_add(t_perfroutine f, int n, ...); -\end{verbatim} -Fügt dem DSP-Baum eine Perform-Routine \verb+f+ hinzu, -die jeden DSP-Zyklus neu aufgerufen wird. - -Das zweite Argument \verb+n+ legt die Anzahl der nachfolgenden Zeigerargumente fest. - -Welche Zeiger auf welche Variablen übergeben werden, unterliegt keiner Beschränkung. -Sinnvoll sind im Allgemeinen Zeiger auf den Datenraum und auf die Signalvektoren. -Auch die Länge der Signalvektoren sollte übergeben werden, -um effektiv Signale manipulieren zu können. - -\subsubsection{sys\_getsr} -\begin{verbatim} -float sys_getsr(void); -\end{verbatim} -Gibt die Abtastrate des Systems zurück. - -\subsection{Funktion: Memory} -\subsubsection{getbytes} -\begin{verbatim} -void *getbytes(size_t nbytes); -\end{verbatim} -Reserviert \verb+nbytes+ Bytes und gibt einen Zeiger auf den reservierten Speicher zurück. - -\subsubsection{copybytes} -\begin{verbatim} -void *copybytes(void *src, size_t nbytes); -\end{verbatim} -Kopiert \verb+nbytes+ Bytes von \verb+*src+ in einen neu alloziierten Speicher. -Die Addresse dieses Speichers wird zurückgegeben. - -\subsubsection{freebytes} -\begin{verbatim} -void freebytes(void *x, size_t nbytes); -\end{verbatim} -Gibt \verb+nbytes+ Bytes an der Addresse \verb+*x+ frei. - -\subsection{Funktionen: Ausgabe} -\subsubsection{post} -\begin{verbatim} -void post(char *fmt, ...); -\end{verbatim} - -Schreibt einen {\tt C}-String auf den Standarderror (Shell). - -\subsubsection{error} -\begin{verbatim} -void error(char *fmt, ...); -\end{verbatim} - -Schreibt einen {\tt C}-String als Fehlermeldung auf den Standarderror (Shell). -Das Objekt, das die Fehlermeldung ausgegeben hat, wird markiert und -ist über das Pd-Menü {\em Find->Find last error} identifizierbar. - -\end{appendix} - -\end{document} - diff --git a/doc/tutorials/externals-howto/HOWTO-externals-en.tex b/doc/tutorials/externals-howto/HOWTO-externals-en.tex deleted file mode 100644 index 26faae2b5a1bf3c8c5e0e8390d6ba2d7f50d7a6b..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/HOWTO-externals-en.tex +++ /dev/null @@ -1,1747 +0,0 @@ -% format latexg -*- latex -*- - -\documentclass[12pt, a4paper,english,titlepage]{article} - -%% HOWTO write an external for pd -%% Copyright (c) 2001-2006 by IOhannes m zmölnig -%% -%% Permission is granted to copy, distribute and/or modify this document -%% under the terms of the GNU Free Documentation License, Version 1.2 -%% or any later version published by the Free Software Foundation; -%% with no Invariant Sections, no Front-Cover Texts, and no Back-Cover -%% Texts. A copy of the license is included in the LICENSE.txt file. - -\usepackage[latin1]{inputenc} -\usepackage[T1]{fontenc} -\usepackage{babel} - -\title{ -HOWTO \\ -write an External \\ -for {\em Pure Data} -} - -\author{ -johannes m zmölnig \\ -\\ -{\em institute of electronic music and acoustics\footnote{http://iem.at}} -} - -\date{} - -\begin{document} -\maketitle - -\begin{abstract} -Pd is a graphical real-time computer-music system that follows the tradition of -IRCAMs {\em ISPW-max}. - -Although plenty of functions are built into Pd, -it is sometimes a pain or simply impossible to create a patch with a certain -functionality out of the given primitives and combinations of these. - -Therefore, Pd can be extended with self made primitives (``objects'') -that are written in complex programming-languages, like {\tt C/C++}. - -This document aims to explain, how to write such primitives in {\tt C}, -the popular language that was used to realize Pd. -\end{abstract} - - -\vfill -\newpage - -\tableofcontents - -\vfill -\newpage - -\section{definitions and prerequisites} -Pd refers to the graphical real-time computer-music environment {\em Pure Data} -by Miller~S.~Puckette. - -To fully understand this document, it is necessary to -be acquainted with Pd and to -have a general understanding of programming techniques especially in {\tt C}. - -To write externals yourself, a {\tt C}-compiler that supports the -{\tt ANSI-C}-Standard, like the {\em Gnu C-compiler} (gcc) on linux-systems or -{\em Visual-C++} on windos-plattforms, will be necessary. - -\subsection{classes, instances, objects} -Pd is written in the programming-language {\tt C}. -Due to its graphical nature, Pd is a {\em object-oriented} system. -Unfortunately {\tt C} does not support very well the use of classes. -Thus the resulting source-code is not as elegant as {\tt C++}-code would be, for instance. - -In this document, the expression {\em class} refers to the realisation of a concept -combining data and manipulators on this data. - -Concrete {\em instances of a class} are called {\em objects}. - -\subsection{internals, externals und libraries} - -To avoid confusion of ideas, the expressions {\em internal}, {\em external} and -{\em library} should be explained here. - -\paragraph{Internal} -An {\em internal} is a class that is built into Pd. -Plenty of primitives, such as ``+'', ``pack'' or ``sig\~\/'' are {\em internals}. - -\paragraph{External} -An {\em external} is a class that is not built into Pd but is loaded at runtime. -Once loaded into Pd's memory, {\em externals} cannot be distinguished from -{\em internals} any more. - -\paragraph{Library} -A {\em library} is a collection of {\em externals} that are compiled into a -single binary-file. - -{\em Library}-files have to follow a system dependent naming convention: - -\begin{tabular}{c||c|c|c} -library & linux&irix&Win32 \\ -\hline -{\tt my\_lib}&{\tt my\_lib.pd\_linux}&{\tt my\_lib.pd\_irix}& -{\tt my\_lib.dll}\\ -\end{tabular} - -The simplest form of a {\em library} includes exactly one {\em external} -bearing the same name as the {\em library}. - -Unlike {\em externals}, {\em libraries} can be imported by Pd with special operations. -After a {\em library} has been imported, -all included {\em externals} have been loaded into memory and are available as objects. - -Pd supports to modes to import {\em libraries}: - -\begin{itemize} -\item via the command line-option ``{\tt -lib my\_lib}'' -\item by creating an object ``{\tt my\_lib}'' -\end{itemize} - -The first method loads a {\em library} when Pd is started. -This method is preferably used for {\em libraries} that contain several {\em externals}. - -The other method should be used for {\em libraries} that contain exactly -one {\em external} bearing the same name. -Pd checks first, whether a class named ``my\_lib'' is already loaded. -If this is not the case\footnote{ -If a class ``my\_lib'' is already existent, an object ``my\_lib'' will be instantiated -and the procedure is done. -Thus, no {\em library} has been loaded. -Therefore no {\em library} that is named like an already used class-name like, say, ``abs'', -can be loaded.}, all paths are searched for a file called -``{\tt my\_lib.pd\_linux}''\footnote{or another system-dependent filename-extensions (s.a.)}. -If such file is found, all included {\em externals} are loaded into memory by calling a -routine \verb+my_lib_setup()+. -After loading, a class ``my\_lib'' is (again) looked for as a (newly loaded) {\em external}. -If so, an instance of this class is created, else the instantiation fails and an error is -printed. -Anyhow, all {\em external}-classes declared in the {\em library} are loaded by now. - - -\section{my first external: {\tt helloworld}} -Usually the first attempt learning a programming-language is a ``hello world''-application. - -In our case, an object class should be created, that prints the line ``hello world!!'' to -the standard error every time it is triggered with a ``bang''-message. - - - -\subsection{the interface to Pd} -To write a Pd-external a well-defined interface is needed. -This is provided in the header-file ``m\_pd.h''. - -\begin{verbatim} -#include "m_pd.h" -\end{verbatim} - -\subsection{a class and its data space} -First a new class has to be prepared and the data space for this class has to be defined. - -\begin{verbatim} -static t_class *helloworld_class; - -typedef struct _helloworld { - t_object x_obj; -} t_helloworld; -\end{verbatim} - -\verb+hello_worldclass+ is going to be a pointer to the new class. - -The structure \verb+t_helloworld+ (of the type \verb+_helloworld+) is -the data space of the class. - -An absolutely necessary element of the data space is a variable of the type -\verb+t_object+, which is used to store internal object-properties like -the graphical presentation of the object or data about inlets and outlets. - -\verb+t_object+ has to be the first entry in the structure ! - -Because a simple ``hello world''-application needs no variables, -the structure is empty apart from the \verb+t_object+. - - -\subsection{method space} -Apart from the data space, a class needs a set of manipulators (methods) to -manipulate the data with. - -If a message is sent to an instance of our class, a method is called. -These methods are the interfaces to the message system of Pd. -On principal they have no return argument and are therefore are of the -type \verb+void+. - -\begin{verbatim} -void helloworld_bang(t_helloworld *x) -{ - post("Hello world !!"); -} -\end{verbatim} - - -This method has an argument of the type \verb+t_helloworld+, -which would enable us to manipulate the data space. - -Since we only want to output ``Hello world!'' -(and, by the way, our data space is quite sparse), -we renounce a manipulation. - -The command \verb+post(char *c,...)+ sends a string to the standard error. -A carriage return is added automatically. -Apart from this, the \verb+post+-command works like the {\tt C}-command \verb+printf()+. - -\subsection{generation of a new class} -To generate a new class, information of the data space and the method space of this class, -have to be passed to Pd when a library is loaded. - -On loading a new library ``my\_lib'', -Pd tries to call a function ``my\_lib\_setup()''. -This function (or functions called by it) -declares the new classes and their properties. -It is only called once, when the library is loaded. -If the function-call fails (e.g., because no function of the specified name is present) -no external of the library will be loaded. - -\begin{verbatim} -void helloworld_setup(void) -{ - helloworld_class = class_new(gensym("helloworld"), - (t_newmethod)helloworld_new, - 0, sizeof(t_helloworld), - CLASS_DEFAULT, 0); - - class_addbang(helloworld_class, helloworld_bang); -} -\end{verbatim} - -\paragraph{class\_new} - -The function \verb+class_new+ creates a new class and returns a pointer to this prototype. - -The first argument is the symbolic name of the class. - -The next two arguments define the constructor and destructor of the class. - -Whenever a class object is created in a Pd-patch, -the class-constructor \verb+(t_newmethod)helloworld_new+ instantiates the object -and initialises the data space. - -Whenever an object is destroyed -(either by closing the containing patch or by deleting the object from the patch) -the destructor frees the dynamically reserved memory. -The allocated memory for the static data space is automatically reserved and freed. - -Therefore we do not have to provide a destructor in this example, the argument -is set to ``0''. - -To enable Pd to reserve and free enough memory for the static data space, -the size of the data structure has to be passed as the fourth argument. - -The fifth argument has influence on the graphical representation of the class objects. -The default-value is \verb+CLASS_DEFAULT+ or simply ``0''. - -The remaining arguments define the arguments of an object and its type. - -Up to six numeric and symbolic object-arguments can be defined via -\verb+A_DEFFLOAT+ and \verb+A_DEFSYMBOL+. -If more arguments are to be passed to the object -or if the order of atom types should by more flexible, -\verb+A_GIMME+ can be used for passing an arbitrary list of atoms. - -The list of object-arguments is terminated by ``0''. -In this example we have no object-arguments at all for the class. - -\paragraph{class\_addbang} -We still have to add a method space to the class. - -\verb+class_addbang+ adds a method for a ``bang''-message to the class that is -defined in the first argument. -The added method is defined in the second argument. - - -\subsection{constructor: instantiation of an object} -Each time, an object is created in a Pd-patch, the -constructor that is defined with the \verb+class_new+-command, -generates a new instance of the class. - -The constructor has to be of type \verb+void *+. - -\begin{verbatim} -void *helloworld_new(void) -{ - t_helloworld *x = (t_helloworld *)pd_new(helloworld_class); - - return (void *)x; -} -\end{verbatim} - - -The arguments of the constructor-method depend on the object-arguments -defined with \verb+class_new+. - -\begin{tabular}{l|l} -\verb+class_new+-argument&constructor-argument\\ -\hline -\verb+A_DEFFLOAT+&\verb+t_floatarg f+ \\ -\verb+A_DEFSYMBOL+&\verb+t_symbol *s+ \\ -\verb+A_GIMME+&\verb+t_symbol *s, int argc, t_atom *argv+ -\end{tabular} - -Because there are no object-arguments for our ``hello world''-class, -the constructor has anon too. - -The function \verb+pd_new+ reserves memory for the data space, -initialises the variables that are internal to the object and -returns a pointer to the data space. - -The type-cast to the data space is necessary. - -Normally, the constructor would initialise the object-variables. -However, since we have none, this is not necessary. - - -The constructor has to return a pointer to the instantiated data space. - -\subsection{the code: \tt helloworld} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *helloworld_class; - -typedef struct _helloworld { - t_object x_obj; -} t_helloworld; - -void helloworld_bang(t_helloworld *x) -{ - post("Hello world !!"); -} - -void *helloworld_new(void) -{ - t_helloworld *x = (t_helloworld *)pd_new(helloworld_class); - - return (void *)x; -} - -void helloworld_setup(void) { - helloworld_class = class_new(gensym("helloworld"), - (t_newmethod)helloworld_new, - 0, sizeof(t_helloworld), - CLASS_DEFAULT, 0); - class_addbang(helloworld_class, helloworld_bang); -} -\end{verbatim} - - -\section{a simple external: {\tt counter}} - -Now we want to realize a simple counter as an external. -A ``bang''-trigger outputs the counter-value on the outlet and -afterwards increases the counter-value by 1. - -This class is similar to the previous one, -but the data space is extended by a variable ``counter'' and the -result is written as a message to an outlet instead of -a string to the standard error. - -\subsection{object-variables} -Of course, a counter needs a state-variable to store the actual counter-value. - -State-variables that belong to class instances belong to the data space. - -\begin{verbatim} -typedef struct _counter { - t_object x_obj; - t_int i_count; -} t_counter; -\end{verbatim} - -The integer variable \verb+i_count+ stores the counter-value. - -\subsection{object-arguments} -It is quite useful for a counter, if a initial value can be defined by the user. -Therefore this initial value should be passed to the object at creation-time. - -\begin{verbatim} -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addbang(counter_class, counter_bang); -} -\end{verbatim} - -So we have an additional argument in the function \verb+class_new+: -\verb+A_DEFFLOAT+ tells Pd, that the object needs one argument of the -type \verb+t_floatarg+. -If no argument is passed, this will default to ``0''. - -\subsection{constructor} -The constructor has some new tasks. -On the one hand, a variable value has to be initialised, -on the other hand, an outlet for the object has to be created. - -\begin{verbatim} -void *counter_new(t_floatarg f) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - - x->i_count=f; - outlet_new(&x->x_obj, &s_float); - - return (void *)x; -} -\end{verbatim} - -The constructor-method has one argument of type \verb+t_floatarg+ as declared -in the setup-routine by \verb+class_new+. -This argument is used to initialise the counter. - -A new outlet is created with the function \verb+outlet_new+. -The first argument is a pointer to the interna of the object -the new outlet is created for. - -The second argument is a symbolic description of the outlet-type. -Since out counter should output numeric values it is of type ``float''. - -\verb+outlet_new+ returns a pointer to the new outlet and saves this very pointer -in the \verb+t_object+-variable \verb+x_obj.ob_outlet+. -If only one outlet is used, the pointer need not additionally be stored in the data space. -If more than one outlets are used, the pointers have to be stored in the data space, -because the \verb+t_object+-variable can only hold one outlet pointer. - -\subsection{the counter method} -When triggered, the counter value should be sent to the outlet -and afterwards be incremented by 1. - -\begin{verbatim} -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - x->i_count++; - outlet_float(x->x_obj.ob_outlet, f); -} -\end{verbatim} - -The function \verb+outlet_float+ sends a floating-point-value (second argument) to the outlet -that is specified by the first argument. - -We first store the counter in a floating point-buffer. -Afterwards the counter is incremented and not before that the buffer variable is sent -to the outlet. - -What appears to be unnecessary on the first glance, makes sense after further -inspection: -The buffer variable has been realized as \verb+t_float+, -since \verb+outlet_float+ expects a floating point-value and a typecast is -inevitable. - -If the counter value was sent to the outlet before being incremented, -this could result in an unwanted (though well defined) behaviour: -If the counter-outlet directly triggered its own inlet, -the counter-method would be called although the counter value was not yet incremented. -Normally this is not what we want. - -The same (correct) result could of course be obtained with a single line, -but this would obscure the {\em reentrant}-problem. - -\subsection{the code: \tt counter} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *counter_class; - -typedef struct _counter { - t_object x_obj; - t_int i_count; -} t_counter; - -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - x->i_count++; - outlet_float(x->x_obj.ob_outlet, f); -} - -void *counter_new(t_floatarg f) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - - x->i_count=f; - outlet_new(&x->x_obj, &s_float); - - return (void *)x; -} - -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addbang(counter_class, counter_bang); -} -\end{verbatim} - - -\section{a complex external: \tt counter} - -The simple counter of the previous chapter can easily be extended to more complexity. -It might be quite useful to be able to reset the counter to an initial value, -to set upper and lower boundaries and to control the step-width. -Each overrun should send a ``bang''-Message to a second outlet and reset the counter to -the initial value. - -\subsection{extended data space} - -\begin{verbatim} -typedef struct _counter { - t_object x_obj; - t_int i_count; - t_float step; - t_int i_down, i_up; - t_outlet *f_out, *b_out; -} t_counter; -\end{verbatim} - -The data space has been extended to hold variables for step width and -upper and lower boundaries. -Furthermore pointers for two outlets have been added. - -\subsection{extension of the class} -The new class objects should have methods for different messages, -like ``set'' and ``reset''. -Therefore the method space has to be extended too. - -\begin{verbatim} - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_GIMME, 0); -\end{verbatim} - -The class generator \verb+class_new+ has been extended by the argument \verb+A_GIMME+. -This enables a dynamic number of arguments to be passed at the instantiation of the object. - -\begin{verbatim} - class_addmethod(counter_class, - (t_method)counter_reset, - gensym("reset"), 0); -\end{verbatim} - -\verb+class_addmethod+ adds a method for an arbitrary selector to an class. - -The first argument is the class the method (second argument) will be added to. - -The third argument is the symbolic selector that should be associated with the method. - -The remaining ``0''-terminated arguments describe the list of atoms that -follows the selector. - -\begin{verbatim} - class_addmethod(counter_class, - (t_method)counter_set, gensym("set"), - A_DEFFLOAT, 0); - class_addmethod(counter_class, - (t_method)counter_bound, gensym("bound"), - A_DEFFLOAT, A_DEFFLOAT, 0); -\end{verbatim} - -A method for ``set'' followed by a numerical value is added, -as well as a method for the selector ``bound'' followed by two numerical values. - -\begin{verbatim} - class_sethelpsymbol(counter_class, gensym("help-counter")); -\end{verbatim} - -If a Pd-object is right-clicked, a help-patch describing the object-class can be opened. -By default, this patch is located in the directory ``{\em doc/5.reference/}'' and -is named like the symbolic class name. - -An alternative help-patch can be defined with the -\verb+class_sethelpsymbol+-command. - -\subsection{construction of in- and outlets} - -When creating the object, several arguments should be passed by the user. - -\begin{verbatim} -void *counter_new(t_symbol *s, int argc, t_atom *argv) -\end{verbatim} -Because of the declaration of arguments in the \verb+class_new+-function -with \verb+A_GIMME+, -the constructor has following arguments: - -\begin{tabular}{c|l} -\verb+t_symbol *s+ & the symbolic name,\\ -& that was used for object creation \\ -\verb+int argc+ & the number of arguments passed to the object\\ -\verb+t_atom *argv+ & a pointer to a list of {\tt argc} atoms -\end{tabular} - -\begin{verbatim} - t_float f1=0, f2=0; - - x->step=1; - switch(argc){ - default: - case 3: - x->step=atom_getfloat(argv+2); - case 2: - f2=atom_getfloat(argv+1); - case 1: - f1=atom_getfloat(argv); - break; - case 0: - break; - } - if (argc<2)f2=f1; - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; - - x->i_count=x->i_down; -\end{verbatim} - -If three arguments are passed, these should be the {\em lower boundary}, -the {\em upper boundary} and the {\em step width}. - -If only two arguments are passed, the step-width defaults to ``1''. -If only one argument is passed, this should be the {\em initial value} of the counter with -step-width of ``1''. - -\begin{verbatim} - inlet_new(&x->x_obj, &x->x_obj.ob_pd, - gensym("list"), gensym("bound")); -\end{verbatim} - -The function \verb+inlet_new+ creates a new ``active'' inlet. -``Active'' means, that a class-method is called each time -a message is sent to an ``active'' inlet. - -Due to the software-architecture, the first inlet is always ``active''. - -The first two arguments of the \verb+inlet_new+-function are -pointers to the interna of the object and to the graphical presentation of the object. - -The symbolic selector that is specified by the third argument is to be -substituted by another symbolic selector (fourth argument) for this inlet. - -Because of this substitution of selectors, -a message on a certain right inlet can be treated as a message with -a certain selector on the leftmost inlet. - -This means: -\begin{itemize} -\item The substituting selector has to be declared by \verb+class_addmethod+ -in the setup-routine. -\item It is possible to simulate a certain right inlet, by sending a message with -this inlet's selector to the leftmost inlet. -\item It is not possible to add methods for more than one selector to a right inlet. -Particularly it is not possible to add a universal method for arbitrary selectors to -a right inlet. -\end{itemize} - -\begin{verbatim} - floatinlet_new(&x->x_obj, &x->step); -\end{verbatim} -\verb+floatinlet_new+ generates a new ``passive'' inlet for numerical values. -``Passive'' inlets allow parts of the data space-memory to be written directly -from outside. -Therefore it is not possible to check for illegal inputs. - -The first argument is a pointer to the internal infrastructure of the object. -The second argument is the address in the data space-memory, -where other objects can write too. - -``Passive'' inlets can be created for pointers, symbolic or -numerical (floating point\footnote{ -That's why the {\tt step}-width of the class\/data space is realized as {\tt t\_float}.}) -values. - - -\begin{verbatim} - x->f_out = outlet_new(&x->x_obj, &s_float); - x->b_out = outlet_new(&x->x_obj, &s_bang); -\end{verbatim} - -The pointers returned by \verb+outlet_new+ have to be saved in the class\/data space -to be used later by the outlet-routines. - -The order of the generation of inlets and outlets is important, -since it corresponds to the order of inlets and outlets in the -graphical representation of the object. - -\subsection{extended method space} - -The method for the ``bang''-message has to full fill the more complex tasks. - -\begin{verbatim} -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - t_int step = x->step; - x->i_count+=step; - if (x->i_down-x->i_up) { - if ((step>0) && (x->i_count > x->i_up)) { - x->i_count = x->i_down; - outlet_bang(x->b_out); - } else if (x->i_count < x->i_down) { - x->i_count = x->i_up; - outlet_bang(x->b_out); - } - } - outlet_float(x->f_out, f); -} -\end{verbatim} - -Each outlet is identified by the \verb+outlet_...+-functions via the -pointer to this outlets. - -The remaining methods still have to be implemented: - -\begin{verbatim} -void counter_reset(t_counter *x) -{ - x->i_count = x->i_down; -} - -void counter_set(t_counter *x, t_floatarg f) -{ - x->i_count = f; -} - -void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2) -{ - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; -} -\end{verbatim} - -\subsection{the code: \tt counter} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *counter_class; - -typedef struct _counter { - t_object x_obj; - t_int i_count; - t_float step; - t_int i_down, i_up; - t_outlet *f_out, *b_out; -} t_counter; - -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - t_int step = x->step; - x->i_count+=step; - - if (x->i_down-x->i_up) { - if ((step>0) && (x->i_count > x->i_up)) { - x->i_count = x->i_down; - outlet_bang(x->b_out); - } else if (x->i_count < x->i_down) { - x->i_count = x->i_up; - outlet_bang(x->b_out); - } - } - - outlet_float(x->f_out, f); -} - -void counter_reset(t_counter *x) -{ - x->i_count = x->i_down; -} - -void counter_set(t_counter *x, t_floatarg f) -{ - x->i_count = f; -} - -void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2) -{ - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; -} - -void *counter_new(t_symbol *s, int argc, t_atom *argv) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - t_float f1=0, f2=0; - - x->step=1; - switch(argc){ - default: - case 3: - x->step=atom_getfloat(argv+2); - case 2: - f2=atom_getfloat(argv+1); - case 1: - f1=atom_getfloat(argv); - break; - case 0: - break; - } - if (argc<2)f2=f1; - - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; - - x->i_count=x->i_down; - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, - gensym("list"), gensym("bound")); - floatinlet_new(&x->x_obj, &x->step); - - x->f_out = outlet_new(&x->x_obj, &s_float); - x->b_out = outlet_new(&x->x_obj, &s_bang); - - return (void *)x; -} - -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_GIMME, 0); - - class_addbang (counter_class, counter_bang); - class_addmethod(counter_class, - (t_method)counter_reset, gensym("reset"), 0); - class_addmethod(counter_class, - (t_method)counter_set, gensym("set"), - A_DEFFLOAT, 0); - class_addmethod(counter_class, - (t_method)counter_bound, gensym("bound"), - A_DEFFLOAT, A_DEFFLOAT, 0); - - class_sethelpsymbol(counter_class, gensym("help-counter")); -} -\end{verbatim} - - -\section{a signal-external: {\tt pan\~\/}} -Signal classes are normal Pd-classes, that offer additional methods for signals. - - -All methods and concepts that can be realized with normal object classes can -therefore be realized with signal classes too. - -Per agreement, the symbolic names of signal classes end with a tilde \~\/. - -The class ``pan\~\/'' shall demonstrate, how signal classes are written. - -A signal on the left inlet is mixed with a signal on the second inlet. -The mixing-factor between 0 and 1 is defined via a \verb+t_float+-message -on a third inlet. - -\subsection{variables of a signal class} -Since a signal-class is only an extended normal class, -there are no principal differences between the data spaces. - -\begin{verbatim} -typedef struct _pan_tilde { - t_object x_obj; - - t_sample f_pan; - t_float f; -} t_pan_tilde; -\end{verbatim} - -Only one variable \verb+f_pan+ for the {\em mixing-factor} of the panning-function is needed. - -The other variable \verb+f+ is needed whenever a signal-inlet is needed too. -If no signal but only a float-message is present at a signal-inlet, this -variable is used to automatically convert the float to signal. - -\subsection{signal-classes} - -\begin{verbatim} -void pan_tilde_setup(void) { - pan_tilde_class = class_new(gensym("pan~"), - (t_newmethod)pan_tilde_new, - 0, sizeof(t_pan_tilde), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addmethod(pan_tilde_class, - (t_method)pan_tilde_dsp, gensym("dsp"), 0); - CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f); -} -\end{verbatim} - -A method for signal-processing has to be provided by each signal class. - -Whenever Pd's audio engine is started, a message with the selector ``dsp'' -is sent to each object. -Each class that has a method for the ``dsp''-message is recognised as signal class. - -Signal classes that want to provide signal-inlets have to -declare this via the \verb+CLASS_MAINSIGNALIN+-macro. -This enables signals at the first (default) inlet. -If more than one signal-inlet is needed, they have to be created explicitly -in the constructor-method. - -Inlets that are declared as signal-inlets cannot provide -methods for \verb+t_float+-messages any longer. - -The first argument of the macro is a pointer to the signal class. -The second argument is the type of the class's data space. - -The last argument is a dummy-variable out of the data space that is needed -to replace non-existing signal at the signal-inlet(s) with \verb+t_float+-messages. - -\subsection{construction of signal-inlets and -outlets} - -\begin{verbatim} -void *pan_tilde_new(t_floatarg f) -{ - t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class); - - x->f_pan = f; - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - floatinlet_new (&x->x_obj, &x->f_pan); - - outlet_new(&x->x_obj, &s_signal); - - return (void *)x; -} -\end{verbatim} - -Additional signal-inlets are added like other inlets with the routine \verb+inlet_new+. -The last two arguments are references to the symbolic selector ``signal'' -in the lookup-table. - -Signal-outlets are also created like normal (message-)outlets, -by setting the outlet-selector to ``signal''. - -\subsection{DSP-methods} -Whenever Pd's audio engine is turned on, -all signal-objects declare their perform-routines that are to be added to the DSP-tree. - -The ``dsp''-method has two arguments, the pointer to the class-data space, and -a pointer to an array of signals. - -The signals are arranged in the array in such way, -that they are ordered in a clockwise way in the graphical representation of the -object.\footnote{ -If both left and right in- and out-signals exist, this means: -First is the leftmost in-signal followed by the right in-signals; -after the right out-signals, finally there comes the leftmost out-signal.} - -\begin{verbatim} -void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp) -{ - dsp_add(pan_tilde_perform, 5, x, - sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); -} -\end{verbatim} - -\verb+dsp_add+ adds a {\em perform}-routine (as declared in the first argument) -to the DSP-tree. - -The second argument is the number of the following pointers to diverse variables. -Which pointers to which variables are passed is not limited. - -Here, sp[0] is the first in-signal, sp[1] represents the second in-signal and -sp[3] points to the out-signal. - -The structure \verb+t_signal+ contains a pointer to the -its signal-vector \verb+().s_vec+ (an array of samples of type \verb+t_sample+), -and the length of this signal-vector \verb+().s_n+. - -Since all signal vectors of a patch (not including it's sub-patches) are of the same length, -it is sufficient to get the length of one of these vectors. - -\subsection{perform-routine} -The perform-routine is the DSP-heart of each signal class. - -A pointer to an integer-array is passed to it. -This array contains the pointers, that were passed via \verb+dsp_add+, -which must be casted back to their real type. - -The perform-routine has to return a pointer to integer, -that points to the address behind the stored pointers of the routine. -This means, that the return argument equals the -argument of the perform-routine plus -the number of pointer variables (as declared as the second argument -of \verb+dsp_add+) plus one. - -\begin{verbatim} -t_int *pan_tilde_perform(t_int *w) -{ - t_pan_tilde *x = (t_pan_tilde *)(w[1]); - t_sample *in1 = (t_sample *)(w[2]); - t_sample *in2 = (t_sample *)(w[3]); - t_sample *out = (t_sample *)(w[4]); - int n = (int)(w[5]); - - t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan; - - while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan; - - return (w+6); -} -\end{verbatim} - -Each sample of the signal vectors is read and manipulated in the \verb+while+-loop. - - -Optimisation of the DSP-tree tries to avoid unnecessary copy-operations. -Therefore it is possible, that in- and out-signal are located -at the same address in the memory. -In this case, the programmer has to be careful not to write into the out-signal -before having read the in-signal to avoid overwriting data that is not yet saved. - -\subsection{the code: \tt pan\~\/} - -\begin{verbatim} -#include "m_pd.h" - -static t_class *pan_tilde_class; - -typedef struct _pan_tilde { - t_object x_obj; - t_sample f_pan; - t_sample f; -} t_pan_tilde; - -t_int *pan_tilde_perform(t_int *w) -{ - t_pan_tilde *x = (t_pan_tilde *)(w[1]); - t_sample *in1 = (t_sample *)(w[2]); - t_sample *in2 = (t_sample *)(w[3]); - t_sample *out = (t_sample *)(w[4]); - int n = (int)(w[5]); - t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan; - - while (n--) *out++ = (*in1++)*(1-f_pan)+(*in2++)*f_pan; - - return (w+6); -} - -void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp) -{ - dsp_add(pan_tilde_perform, 5, x, - sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); -} - -void *pan_tilde_new(t_floatarg f) -{ - t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class); - - x->f_pan = f; - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - floatinlet_new (&x->x_obj, &x->f_pan); - outlet_new(&x->x_obj, &s_signal); - - return (void *)x; -} - -void pan_tilde_setup(void) { - pan_tilde_class = class_new(gensym("pan~"), - (t_newmethod)pan_tilde_new, - 0, sizeof(t_pan_tilde), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - class_addmethod(pan_tilde_class, - (t_method)pan_tilde_dsp, gensym("dsp"), 0); - CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f); -} -\end{verbatim} - -\vfill -\newpage -\begin{appendix} - -\section{Pd's message-system} -Non-audio-data are distributed via a message-system. -Each message consists of a ``selector'' and a list of atoms. - -\subsection{atoms} - -There are three kinds of atoms: -\begin{itemize} -\item {\em A\_FLOAT}: a numerical value (floating point) -\item {\em A\_SYMBOL}: a symbolic value (string) -\item {\em A\_POINTER}: a pointer -\end{itemize} - -Numerical values are always floating point-values (\verb+t_float+), -even if they could be displayed as integer values. - -Each symbol is stored in a lookup-table for reasons of performance. -The command \verb+gensym+ looks up a string in the lookup-table and -returns the address of the symbol. -If the string is not yet to be found in the table, -a new symbol is added. - -Atoms of type {\em A\_POINTER} are not very important (for simple externals). - -The type of an atom \verb+a+ is stored in the structure-element \verb+a.a_type+. - -\subsection{selectors} -The selector is a symbol that defines the type of a message. -There are five predefined selectors: -\begin{itemize} -\item ``{\tt bang}'' labels a trigger event. -A ``bang''-message consists only of the selector and contains no lists of atoms. -\item ``{\tt float}'' labels a numerical value. -The list of a ``float''-Message contains one single atom of type {\em A\_FLOAT} -\item ``{\tt symbol}'' labels a symbolic value. -The list of a ``symbol''-Message contains one single atom of type {\em A\_SYMBOL} -\item ``{\tt pointer}'' labels a pointer value. -The list of a ``pointer''-Message contains one single atom of type {\em A\_POINTER} -\item ``{\tt list}'' labels a list of one or more atoms of arbitrary type. -\end{itemize} - -Since the symbols for these selectors are used quite often, -their address in the lookup-table can be queried directly, -without having to use \verb+gensym+: - -\begin{tabular}{l||l|l} -selector&lookup-routine&lookup-address\\ -\hline -\tt bang &\verb+gensym("bang")+ & \verb+&s_bang+ \\ -\tt float &\verb+gensym("float")+ & \verb+&s_float+ \\ -\tt symbol &\verb+gensym("symbol")+ & \verb+&s_symbol+ \\ -\tt pointer &\verb+gensym("pointer")+ & \verb+&s_pointer+ \\ -\tt list &\verb+gensym("list")+ & \verb+&s_list+ \\ ---- (signal) &\verb+gensym("signal")+&\verb+&s_symbol+ -\end{tabular} - -Other selectors can be used as well. -The receiving class has to provide a method for a specifique selector -or for ``anything'', which is any arbitrary selector. - -Messages that have no explicit selector and start with a numerical value, -are recognised automatically either as ``float''-message (only one atom) or as -``list''-message (several atoms). - -For example, messages ``\verb+12.429+'' and ``\verb+float 12.429+'' are identical. -Likewise, the messages ``\verb+list 1 for you+'' is identical to ``\verb+1 for you+''. - -\section{Pd-types} -Since Pd is used on several platforms, -many ordinary types of variables, like \verb|int|, are re-defined. -To write portable code, it is reasonable to use types provided by Pd. - -Apart from this there are many predefined types, -that should make the life of the programmer simpler. - -Generally, Pd-types start with \verb|t_|. - -\begin{tabular}{c|l} -Pd-type & description \\ -\hline\hline -\verb+t_atom+& atom \\ -\verb+t_float+ & floating point value\\ -\verb+t_symbol+ & symbol \\ -\verb+t_gpointer+ & pointer (to graphical objects) \\ -\hline -\verb+t_int+ & integer value \\ -\verb+t_signal+ & structure of a signal \\ -\verb+t_sample+ & audio signal-value (floating point)\\ -\verb+t_outlet+ & outlet of an object \\ -\verb+t_inlet+ & inlet of an object \\ -\verb+t_object+ & object-interna \\ -\hline -\verb+t_class+ & a Pd-class \\ -\verb+t_method+ & class-method \\ -\verb+t_newmethod+ & pointer to a constructor (new-routine) \\ -\end{tabular} - - -\section{important functions in ``m\_pd.h''} - -\subsection{functions: atoms} - -\subsubsection{SETFLOAT} -\begin{verbatim} -SETFLOAT(atom, f) -\end{verbatim} -This macro sets the type of \verb+atom+ to \verb+A_FLOAT+ -and stores the numerical value \verb+f+ in this atom. - -\subsubsection{SETSYMBOL} -\begin{verbatim} -SETSYMBOL(atom, s) -\end{verbatim} -This macro sets the type of \verb+atom+ to \verb+A_SYMBOL+ -and stores the symbolic pointer \verb+s+ in this atom. - -\subsubsection{SETPOINTER} -\begin{verbatim} -SETPOINTER(atom, pt) -\end{verbatim} -This macro sets the type of \verb+atom+ to \verb+A_POINTER+ -and stores the pointer \verb+pt+ in this atom. - -\subsubsection{atom\_getfloat} -\begin{verbatim} -t_float atom_getfloat(t_atom *a); -\end{verbatim} -If the type of the atom \verb+a+ is \verb+A_FLOAT+, -the numerical value of this atom else ``0.0'' is returned. - -\subsubsection{atom\_getfloatarg} -\begin{verbatim} -t_float atom_getfloatarg(int which, int argc, t_atom *argv) -\end{verbatim} -If the type of the atom -- that is found at in the atom-list -\verb+argv+ with the length \verb+argc+ at the place \verb+which+ -- -is \verb+A_FLOAT+, the numerical value of this atom else ``0.0'' is returned. - -\subsubsection{atom\_getint} -\begin{verbatim} -t_int atom_getint(t_atom *a); -\end{verbatim} -If the type of the atom \verb+a+ is \verb+A_FLOAT+, -its numerical value is returned as integer else ``0'' is returned. - -\subsubsection{atom\_getsymbol} -\begin{verbatim} -t_symbol atom_getsymbol(t_atom *a); -\end{verbatim} -If the type of the atom \verb+a+ is \verb+A_SYMBOL+, -a pointer to this symbol is returned, else a null-pointer ``0'' is returned. - -\subsubsection{atom\_gensym} -\begin{verbatim} -t_symbol *atom_gensym(t_atom *a); -\end{verbatim} -If the type of the atom \verb+a+ is \verb+A_SYMBOL+, -a pointer to this symbol is returned. - -Atoms of a different type, are ``reasonably'' converted into a string. -This string is -- on demand -- inserted into the symbol-table. -A pointer to this symbol is returned. - -\subsubsection{atom\_string} -\begin{verbatim} -void atom_string(t_atom *a, char *buf, unsigned int bufsize); -\end{verbatim} -Converts an atom \verb+a+ into a {\tt C}-string \verb+buf+. -The memory to this char-Buffer has to be reserved manually and -its length has to be declared in \verb+bufsize+. - -\subsubsection{gensym} -\begin{verbatim} -t_symbol *gensym(char *s); -\end{verbatim} -Checks, whether the C-string \verb+*s+ has already been inserted into the symbol-table. -If no entry exists, it is created. -A pointer to the symbol is returned. - -\subsection{functions: classes} -\subsubsection{class\_new} -\begin{verbatim} -t_class *class_new(t_symbol *name, - t_newmethod newmethod, t_method freemethod, - size_t size, int flags, - t_atomtype arg1, ...); -\end{verbatim} -Generates a class with the symbolic name \verb+name+. -\verb+newmethod+ is the constructor that creates an instance of the class and -returns a pointer to this instance. - -If memory is reserved dynamically, this memory has to be freed by the -destructor-method \verb+freemethod+ (without any return argument), -when the object is destroyed. - -\verb+size+ is the static size of the class-data space, -that is returned by \verb+sizeof(t_mydata)+. - -\verb+flags+ define the presentation of the graphical object. -A (more or less arbitrary) combination of following objects is possible: - -\begin{tabular}{l|l} -flag&description\\ -\hline -\verb+CLASS_DEFAULT+ & a normal object with one inlet \\ -\verb+CLASS_PD+ & \em object (without graphical presentation) \\ -\verb+CLASS_GOBJ+ & \em pure graphical object (like arrays, graphs,...)\\ -\verb+CLASS_PATCHABLE+ & \em a normal object (with one inlet) \\ -\verb+CLASS_NOINLET+ & the default inlet is suppressed \\ -\end{tabular} - -Flags the description of which is printed in {\em italic} -are of small importance for writing externals. - -The remaining arguments \verb+arg1,...+ define the -types of object-arguments passed at the creation of a class-object. -A maximum of six type checked arguments can be passed to an object. -The list of argument-types are terminated by ``0''. - -Possible types of arguments are: - -\begin{tabular}{l|l} -\verb+A_DEFFLOAT+ & a numerical value \\ -\verb+A_DEFSYMBOL+ & a symbolical value \\ -\verb+A_GIMME+ & a list of atoms of arbitrary length and types \\ -\end{tabular} - -If more than six arguments are to be passed, -\verb+A_GIMME+ has to be used and a manual type-check has to be made. - -\subsubsection{class\_addmethod} -\begin{verbatim} -void class_addmethod(t_class *c, t_method fn, t_symbol *sel, - t_atomtype arg1, ...); -\end{verbatim} -Adds a method \verb+fn+ for a selector \verb+sel+ to a class \verb+c+. - -The remaining arguments \verb+arg1,...+ define the -types of the list of atoms that follow the selector. -A maximum of six type-checked arguments can be passed. -If more than six arguments are to be passed, -\verb+A_GIMME+ has to be used and a manual type-check has to be made. - -The list of arguments is terminated by ``0''. - - -Possible types of arguments are: - -\begin{tabular}{l|l} -\verb+A_DEFFLOAT+ & a numerical value \\ -\verb+A_DEFSYMBOL+ & a symbolical value \\ -\verb+A_POINTER+ & a pointer \\ -\verb+A_GIMME+ & a list of atoms of arbitrary length and types \\ -\end{tabular} - -\subsubsection{class\_addbang} -\begin{verbatim} -void class_addbang(t_class *c, t_method fn); -\end{verbatim} -Adds a method \verb+fn+ for ``bang''-messages to the class \verb+c+. - -The argument of the ``bang''-method is a pointer to the class-data space: - -\verb+void my_bang_method(t_mydata *x);+ - -\subsubsection{class\_addfloat} -\begin{verbatim} -void class_addfloat(t_class *c, t_method fn); -\end{verbatim} -Adds a method \verb+fn+ for ``float''-messages to the class \verb+c+. - -The arguments of the ``float''-method is a pointer to the class-data space and -a floating point-argument: - -\verb+void my_float_method(t_mydata *x, t_floatarg f);+ - -\subsubsection{class\_addsymbol} -\begin{verbatim} -void class_addsymbol(t_class *c, t_method fn); -\end{verbatim} -Adds a method \verb+fn+ for ``symbol''-messages to the class \verb+c+. - -The arguments of the ``symbol''-method is a pointer to the class-data space and -a pointer to the passed symbol: - -\verb+void my_symbol_method(t_mydata *x, t_symbol *s);+ - -\subsubsection{class\_addpointer} -\begin{verbatim} -void class_addpointer(t_class *c, t_method fn); -\end{verbatim} -Adds a method \verb+fn+ for ``pointer''-messages to the class \verb+c+. - -The arguments of the ``pointer''-method is a pointer to the class-data space and -a pointer to a pointer: - -\verb+void my_pointer_method(t_mydata *x, t_gpointer *pt);+ - -\subsubsection{class\_addlist} -\begin{verbatim} -void class_addlist(t_class *c, t_method fn); -\end{verbatim} -Adds a method \verb+fn+ for ``list''-messages to the class \verb+c+. - -The arguments of the ``list''-method are -- apart from a pointer to the class-data space -- -a pointer to the selector-symbol (always \verb+&s_list+), -the number of atoms and a pointer to the list of atoms: - -\verb+void my_list_method(t_mydata *x,+ - -\verb+ t_symbol *s, int argc, t_atom *argv);+ - -\subsubsection{class\_addanything} -\begin{verbatim} -void class_addanything(t_class *c, t_method fn); -\end{verbatim} -Adds a method \verb+fn+ for an arbitrary message to the class \verb+c+. - -The arguments of the anything-method are -- apart from a pointer to the class-data space -- -a pointer to the selector-symbol, -the number of atoms and a pointer to the list of atoms: - -\verb+void my_any_method(t_mydata *x,+ - -\verb+ t_symbol *s, int argc, t_atom *argv);+ - -\subsubsection{class\_addcreator} -\begin{verbatim} - void class_addcreator(t_newmethod newmethod, t_symbol *s, - t_atomtype type1, ...); -\end{verbatim} -Adds a creator-symbol \verb+s+, alternative to the symbolic class name, -to the constructor \verb+newmethod+. -Thus, objects can be created either by their ``real'' class name or -an alias-name (p.e. an abbreviation, like the internal ``float'' resp. ``f''). - -The ``0''-terminated list of types corresponds to that of \verb+class_new+. - -\subsubsection{class\_sethelpsymbol} -\begin{verbatim} -void class_sethelpsymbol(t_class *c, t_symbol *s); -\end{verbatim} - -If a Pd-object is right-clicked, a help-patch for the corresponding object class -can be opened. -By default this is a patch with the symbolic class name in the -directory ``{\em doc/5.reference/}''. - -The name of the help-patch for the class that is pointed to by \verb+c+ -is changed to the symbol \verb+s+. - -Therefore, several similar classes can share a single help-patch. - -Path-information is relative to the default help path {\em doc/5.reference/}. - -\subsubsection{pd\_new} -\begin{verbatim} -t_pd *pd_new(t_class *cls); -\end{verbatim} -Generates a new instance of the class \verb+cls+ and -returns a pointer to this instance. - -\subsection{functions: inlets and outlets} -All routines for inlets and outlets need a reference to the object-interna of -the class-instance. -When instantiating a new object, -the necessary data space-variable of the \verb+t_object+-type is initialised. -This variable has to be passed as the \verb+owner+-object to the -various inlet- and outlet-routines. - -\subsubsection{inlet\_new} -\begin{verbatim} -t_inlet *inlet_new(t_object *owner, t_pd *dest, - t_symbol *s1, t_symbol *s2); -\end{verbatim} -Generates an additional ``active'' inlet for the object -that is pointed at by \verb+owner+. -Generally, \verb+dest+ points at ``\verb+owner.ob_pd+''. - -The selector \verb+s1+ at the new inlet is substituted by the selector \verb+s2+. - -If a message with selector \verb+s1+ appears at the new inlet, -the class-method for the selector \verb+s2+ is called. - -This means -\begin{itemize} -\item The substituting selector has to be declared by \verb+class_addmethod+ -in the setup-routine. -\item It is possible to simulate a certain right inlet, by sending a message with -this inlet's selector to the leftmost inlet. - -Using an empty symbol (\verb+gensym("")+) as selector -makes it impossible to address a right inlet via the leftmost one. - -\item It is not possible to add methods for more than one selector to a right inlet. -Particularly it is not possible to add a universal method for arbitrary selectors to -a right inlet. -\end{itemize} - -\subsubsection{floatinlet\_new} -\begin{verbatim} -t_inlet *floatinlet_new(t_object *owner, t_float *fp); -\end{verbatim} -Generates a new ``passive'' inlet for the object that is pointed at by \verb+owner+. -This inlet enables numerical values to be written directly into the -memory \verb+fp+, without calling a dedicated method. - -\subsubsection{symbolinlet\_new} -\begin{verbatim} -t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp); -\end{verbatim} -Generates a new ``passive'' inlet for the object that is pointed at by \verb+owner+. -This inlet enables symbolic values to be written directly into the -memory \verb+*sp+, without calling a dedicated method. - - -\subsubsection{pointerinlet\_new} -\begin{verbatim} -t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp); -\end{verbatim} -Generates a new ``passive'' inlet for the object that is pointed at by \verb+owner+. -This inlet enables pointer to be written directly into the -memory \verb+gp+, without calling a dedicated method. - -\subsubsection{outlet\_new} -\begin{verbatim} -t_outlet *outlet_new(t_object *owner, t_symbol *s); -\end{verbatim} -Generates a new outlet for the object that is pointed at by \verb+owner+. -The Symbol \verb+s+ indicates the type of the outlet. - -\begin{tabular}{c|l||l} -symbol & symbol-address & outlet-type \\ -\hline\hline -``bang'' & \verb+&s_bang+ & message (bang)\\ -``float'' & \verb+&s_float+ & message (float)\\ -``symbol'' & \verb+&s_symbol+ & message (symbol) \\ -``pointer'' & \verb+&s_gpointer+ & message (pointer)\\ -``list'' & \verb+&s_list+ & message (list) \\ ---- & 0 & message \\ -\hline -``signal'' & \verb+&s_signal+ & signal \\ -\end{tabular} - -There are no real differences between outlets of the various message-types. -At any rate, it makes code more easily readable, -if the use of outlet is shown at creation-time. -For outlets for any messages a null-pointer is used. -Signal-outlet must be declared with \verb+&s_signal+. - -Variables if the type \verb+t_object+ provide pointer to one outlet. -Whenever a new outlet is generated, its address is stored in the -object variable \verb+(*owner).ob_outlet+. - -If more than one message-outlet is needed, -the outlet-pointers that are returned by \verb+outlet_new+ -have to be stored manually in the data space -to address the given outlets. - -\subsubsection{outlet\_bang} -\begin{verbatim} -void outlet_bang(t_outlet *x); -\end{verbatim} -Outputs a ``bang''-message at the outlet specified by \verb+x+. - -\subsubsection{outlet\_float} -\begin{verbatim} -void outlet_float(t_outlet *x, t_float f); -\end{verbatim} -Outputs a ``float''-message with the numeric value \verb+f+ -at the outlet specified by \verb+x+. - -\subsubsection{outlet\_symbol} -\begin{verbatim} -void outlet_symbol(t_outlet *x, t_symbol *s); -\end{verbatim} -Outputs a ``symbol''-message with the symbolic value \verb+s+ -at the outlet specified by \verb+x+. - -\subsubsection{outlet\_pointer} -\begin{verbatim} -void outlet_pointer(t_outlet *x, t_gpointer *gp); -\end{verbatim} -Outputs a ``pointer''-message with the pointer \verb+gp+ -at the outlet specified by \verb+x+. - -\subsubsection{outlet\_list} -\begin{verbatim} -void outlet_list(t_outlet *x, - t_symbol *s, int argc, t_atom *argv); -\end{verbatim} -Outputs a ``list''-message at the outlet specified by \verb+x+. -The list contains \verb+argc+ atoms. -\verb+argv+ points to the first element of the atom-list. - -Independent of the symbol \verb+s+, the selector ``list'' will precede -the list. - -To make the code more readable, -\verb+s+ should point to the symbol list -(either via \verb+gensym("list")+ or via \verb+&s_list+) - -\subsubsection{outlet\_anything} -\begin{verbatim} -void outlet_anything(t_outlet *x, - t_symbol *s, int argc, t_atom *argv); -\end{verbatim} -Outputs a message at the outlet specified by \verb+x+. - -The message-selector is specified with \verb+s+. -It is followed by \verb+argc+ atoms. -\verb+argv+ points to the first element of the atom-list. - -\subsection{functions: DSP} -If a class should provide methods for digital signal-processing, -a method for the selector ``dsp'' (followed by no atoms) -has to be added to this class - -Whenever Pd's audio engine is started, -all objects that provide a ``dsp''-method are identified as instances of signal classes. - -\paragraph{DSP-method} - -\begin{verbatim} -void my_dsp_method(t_mydata *x, t_signal **sp) -\end{verbatim} - -In the ``dsp''-method a class method for signal-processing -is added to the DSP-tree by the function \verb+dsp_add+. - -Apart from the data space \verb+x+ of the object, -an array of signals is passed. -The signals in the array are arranged in such a way, -that they can be read in the graphical representation of the object -clockwisely. - -In case there are both two in- and out-signals, this means: - -\begin{tabular}{c|r} -pointer & to signal \\ -\hline\hline -sp[0] & left in-signal \\ -sp[1] & right in-signal \\ -sp[2] & right out-signal \\ -sp[3] & left out-signal \\ -\end{tabular} - -The signal structure contains apart from other things: - -\begin{tabular}{c|l} -structure-element & description \\ -\hline -\verb+s_n+ & length of the signal vector \\ -\verb+s_vec+ & pointer to the signal vector \\ -\end{tabular} - -The signal vector is an array of samples of type \verb+t_sample+. - -\paragraph{perform-routine} -\begin{verbatim} -t_int *my_perform_routine(t_int *w) -\end{verbatim} - - -A pointer \verb+w+ to an array (of integer) is passed to -the perform-routine that is inserted into the DSP-tree by \verb+class_add+. - -In this array the pointers that are passed via \verb+dsp_add+ are stored. -These pointers have to be casted back to their original type. - -The first pointer is stored at \verb+w[1]+ !!! - -The perform-routine has to return a pointer to integer, -that points directly behind the memory, where the object's pointers are stored. -This means, that the return-argument equals the routine's argument \verb+w+ -plus the number of used pointers -(as defined in the second argument of \verb+dsp_add+) plus one. - -\subsubsection{CLASS\_MAINSIGNALIN} -\begin{verbatim} -CLASS_MAINSIGNALIN(<class_name>, <class_data>, <f>); -\end{verbatim} -The macro \verb+CLASS_MAINSIGNALIN+ declares, -that the class will use signal-inlets. - -The first macro-argument is a pointer to the signal-class. -The second argument is the type of the class-data space. -The third argument is a (dummy-)floating point-variable of the data space, -that is needed to automatically convert ``float''-messages into signals -if no signal is present at the signal-inlet. - -No ``float''-methods can be used for signal-inlets, that are created this way. - -\subsubsection{dsp\_add} -\begin{verbatim} -void dsp_add(t_perfroutine f, int n, ...); -\end{verbatim} -Adds the perform-routine \verb+f+ to the DSP-tree. -The perform-routine is called at each DSP-cycle. - -The second argument\verb+n+ defines the number of following pointer-arguments - -Which pointers to which data are passes is not limited. -Generally, pointers to the data space of the object and to the -signal-vectors are reasonable. -The length of the signal-vectors should also be passed to manipulate signals effectively. - -\subsubsection{sys\_getsr} -\begin{verbatim} -float sys_getsr(void); -\end{verbatim} -Returns the sampler ate of the system. - -\subsection{functions: memory} -\subsubsection{getbytes} -\begin{verbatim} -void *getbytes(size_t nbytes); -\end{verbatim} -Reserves \verb+nbytes+ bytes and returns a pointer to the allocated memory. - -\subsubsection{copybytes} -\begin{verbatim} -void *copybytes(void *src, size_t nbytes); -\end{verbatim} -Copies \verb+nbytes+ bytes from \verb+*src+ into a newly allocated memory. -The address of this memory is returned. - -\subsubsection{freebytes} -\begin{verbatim} -void freebytes(void *x, size_t nbytes); -\end{verbatim} -Frees \verb+nbytes+ bytes at address \verb+*x+. - -\subsection{functions: output} -\subsubsection{post} -\begin{verbatim} -void post(char *fmt, ...); -\end{verbatim} - -Writes a {\tt C}-string to the standard error (shell). - -\subsubsection{error} -\begin{verbatim} -void error(char *fmt, ...); -\end{verbatim} - -Writes a {\tt C}-string as an error-message to the standard error (shell). - -The object that has output the error-message is marked and -can be identified via the Pd-menu {\em Find->Find last error}. - -\end{appendix} - -\end{document} - diff --git a/doc/tutorials/externals-howto/LICENSE.txt b/doc/tutorials/externals-howto/LICENSE.txt deleted file mode 100644 index aa5c03cca299a105865359c3be30c3052323bbc7..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/LICENSE.txt +++ /dev/null @@ -1,179 +0,0 @@ -"HOWTO write Externals for Pure data" by IOhannes m zmölnig - -This work consists of a HOWTO-text (possibly in various translations) and -accompanying material (example source code files, Makefiles,...) -Any source-code examples within the HOWTO-text are regarded as accompanying material. - - -1. License for the HOWTO-text: -============================== - -Copyright (c) 2001-2006 IOhannes m zmölnig. - Permission is granted to copy, distribute and/or modify this document - under the terms of the GNU Free Documentation License, Version 1.2 - or any later version published by the Free Software Foundation; - with no Invariant Sections, no Front-Cover Texts, and no Back-Cover - Texts. A copy of the license is included in the section entitled "GNU - Free Documentation License" of this document. - - - -2. License for the accompanying material (examples,...) -======================================================= - -This software is copyrighted by IOhannes m zmölnig. The following -terms (the "Standard Improved BSD License") apply to all files associated with -the software unless explicitly disclaimed in individual files: - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. -3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR -BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING -IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF -THE POSSIBILITY OF SUCH DAMAGE. - - - -======================================================= -======================================================= -======================================================= - - -GNU Free Documentation License - -Version 1.2, November 2002 - -Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. -51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -Everyone is permitted to copy and distribute verbatim copies -of this license document, but changing it is not allowed. - -0. PREAMBLE - -The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. - -This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. - -We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. - -1. APPLICABILITY AND DEFINITIONS - -This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. - -A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. - -A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. - -The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. - -The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. - -A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". - -Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. - -The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. - -A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. - -The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. - -2. VERBATIM COPYING - -You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. - -You may also lend copies, under the same conditions stated above, and you may publicly display copies. - -3. COPYING IN QUANTITY - -If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. - -If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. - -If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. - -It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. - -4. MODIFICATIONS - -You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: - - * A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. - * B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. - * C. State on the Title page the name of the publisher of the Modified Version, as the publisher. - * D. Preserve all the copyright notices of the Document. - * E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. - * F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. - * G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. - * H. Include an unaltered copy of this License. - * I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. - * J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. - * K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. - * L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. - * M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. - * N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. - * O. Preserve any Warranty Disclaimers. - -If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. - -You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. - -You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. - -The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. - -5. COMBINING DOCUMENTS - -You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. - -The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. - -In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements." - -6. COLLECTIONS OF DOCUMENTS - -You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. - -You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. - -7. AGGREGATION WITH INDEPENDENT WORKS - -A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. - -If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. - -8. TRANSLATION - -Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. - -If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. - -9. TERMINATION - -You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. - -10. FUTURE REVISIONS OF THIS LICENSE - -The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. - -Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. diff --git a/doc/tutorials/externals-howto/Makefile b/doc/tutorials/externals-howto/Makefile deleted file mode 100644 index f9840099455186ae3e8fffda7a40a7be884c6d97..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -HOWTO_EN=HOWTO-externals-en -HOWTO_DE=HOWTO-externals-de - -HOWTO_EXAMPLES=example1 example2 example3 example4 - -HTMLDIR_EN=HOWTO -HTMLDIR_DE=HOWTO-de - -LATEX=latex -DVIPS=dvips -DVIPDF=dvipdf -LATEX2HTML=latex2html - -default: en_pdf - -TARGETS: default \ - en_ps en_pdf en_html de_ps de_pdf de_html ps pdf html \ - clean cleaner distclean \ - examples $(HOWTO_EXAMPLES) - -.PHONY: $(TARGETS) - -en_ps: $(HOWTO_EN).ps - -en_pdf: $(HOWTO_EN).pdf - -en_html: - mkdir -p ${HTMLDIR_EN} - $(LATEX2HTML) -dir $(HTMLDIR_EN) -split 4 $(HOWTO_EN).tex - -de_ps: $(HOWTO_DE).ps - -de_pdf: $(HOWTO_DE).pdf - -de_html: - mkdir -p ${HTMLDIR_DE} - $(LATEX2HTML) -dir $(HTMLDIR_DE) -split 4 $(HOWTO_DE).tex - -ps: en_ps de_ps - -pdf: en_pdf de_pdf - -html: en_html de_html - -clean: - -rm -f *.aux *.log *.toc *.dvi *~ - -cleaner: clean - -rm -f *.ps *.pdf - -rm -rf $(HTMLDIR_EN) $(HTMLDIR_DE) - -distclean: cleaner - @for d in ${HOWTO_EXAMPLES}; do ${MAKE} -C $$d clean; done - -%.dvi: - $(LATEX) $*.tex - $(LATEX) $*.tex - - -%.ps: %.dvi - $(DVIPS) $*.dvi - - -%.pdf: %.dvi - $(DVIPDF) $*.dvi - -examples: $(HOWTO_EXAMPLES) - echo made examples - -$(HOWTO_EXAMPLES): - $(MAKE) -C $@ diff --git a/doc/tutorials/externals-howto/example1/Makefile b/doc/tutorials/externals-howto/example1/Makefile deleted file mode 100644 index 50e00ac2ad0ed037de9301ab13b7872e7f62b6dd..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example1/Makefile +++ /dev/null @@ -1,154 +0,0 @@ -# Makefile -# (c) 2006 IOhannes m zmölnig - -# path to pd -## change this according to your setup! -PDROOT=../../../../pd -#PDROOT=/home/zmoelnig/src/pd/ - -# here we find the sources of pd (and evtl. the pd.lib) -PDSRCDIR=$(PDROOT)/src -PDLIBDIR=$(PDROOT)/bin - -# this is the filename-extension -# people have to specify it at the cmdline: eg "make pd_linux" -EXTENSION=$(MAKECMDGOALS) - -# if no filename-extension is supplied by the user -# try to guess one, based on what "uname" tells us -UNAME := $(shell uname -s) -ifeq ($(UNAME),Linux) - DEFAULTEXTENSION= pd_linux -else - ifeq ($(UNAME),Darwin) - DEFAULTEXTENSION= pd_darwin - else - ifeq (MINGW,$(findstring MINGW,$(UNAME))) - DEFAULTEXTENSION= pd_nt - else - ifeq ($(UNAME),IRIX) - UNAMEV := $(shell uname -R) - ifeq (6.,$(findstring 6.,$(UNAMEV))) - DEFAULTEXTENSION= pd_irix6 - else - DEFAULTEXTENSION= pd_irix5 - endif - else - DEFAULTEXTENSION=help - endif - endif - endif -endif - -# if no extension is given, call "make" again with a guessed extension -auto: - make $(DEFAULTEXTENSION) - -# just a stupid fallback -help: - @echo "choose one command: make pd_linux (linux), make pd_darwin (osX), make pd_irix5 (IRIX5), make pd_irix6 (IRIX6), make dll (MSVC), make pd_nt (MinWG)" - -# delete old build files -clean: - -rm -f *.dll *.pd_* *.o *.obj *~ - -# we want to compile all C-files we find in the current directory -SOURCES=$(sort $(filter %.c, $(wildcard *.c))) -# each C-files maps will become an external with the given filename-extension -TARGETS=$(SOURCES:.c=.$(EXTENSION)) - - -# ----------------------- Linux ----------------------- - -pd_linux: $(TARGETS) - -LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer -fPIC \ - -Wall -W -Wshadow -Wstrict-prototypes -Werror \ - -Wno-unused -Wno-parentheses -Wno-switch - -LINUXLDFLAGS = -export_dynamic -shared -lc -lm - -LINUXINCLUDE = -I$(PDSRCDIR) - -%.pd_linux: %.c - $(CC) $(LINUXLDFLAGS) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.pd_linux $*.c - strip --strip-unneeded $*.pd_linux - - - -# ----------------------- Mac OSX ----------------------- - -pd_darwin: $(TARGETS) - -DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \ - -Wno-unused -Wno-parentheses -Wno-switch - -DARWININCLUDE = -I$(PDSRCDIR) - -DARWINLDFLAGS = -bundle -undefined suppress -flat_namespace - -%.pd_darwin: %.c - $(CC) $(DARWINCFLAGS) $(DARWININCLUDE) $(DARWINLDFLAGS) -o $*.pd_darwin $*.c - - -# ----------------------- IRIX 5.x ----------------------- -pd_irix5: $(TARGETS) - -SGICFLAGS5 = -o32 -DPD -DSGI -O2 - -SGIINCLUDE = -I$(PDSRCDIR) - -SGILDFLAGS = -elf -shared -rdata_shared - -%.pd_irix5: %.c - $(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c - $(LD) $(SGILDFLAGS) -o $*.pd_irix5 $*.o - rm $*.o - - -# ----------------------- IRIX 6.x ----------------------- -pd_irix6: $(TARGETS) - -SGICFLAGS6 = -DPD -DSGI -n32 \ - -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \ - -Ofast=ip32 - -%.pd_irix6: %.c - $(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c - $(LD) $(SGILDFLAGS) -o $*.pd_irix6 $*.o - rm $*.o - - -# ----------------------- NT ----------------------- -dll: $(TARGETS) - -PDNTCFLAGS = /W3 /WX /DPD /DNT /D__WIN32__ /DMSW /nologo - -VC="C:\Programme\Microsoft Visual Studio\Vc98" - -PDNTINCLUDE = /I. /I$(PDROOT)\tcl\include /I$(PDSRCDIR)\src /I$(VC)\include - -PDNTLDIR = $(VC)\lib - -PDNTLIB = $(PDNTLDIR)\libc.lib \ - $(PDNTLDIR)\oldnames.lib \ - $(PDNTLDIR)\kernel32.lib \ - $(PDLIBDIR)\pd.lib - -%.dll: %.c - cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c - link /dll /export:$*_setup $*.obj $(PDNTLIB) - - -pd_nt: $(TARGETS) - -MINGWCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \ - -Wall -W -Wshadow -Wstrict-prototypes -Werror \ - -Wno-unused -Wno-parentheses -Wno-switch -mms-bitfields - -MINGWLDFLAGS = -export_dynamic -shared -lm -lkernel32 -lcoldname -lcrtdll -lpd -L$(PDLIBDIR) - -MINGWINCLUDE = -I$(PDSRCDIR) - -%.pd_nt: %.c - $(CC) $(MINGWLDFLAGS) $(MINGWCFLAGS) $(MINGWINCLUDE) -o $*.dll $*.c diff --git a/doc/tutorials/externals-howto/example1/helloworld.c b/doc/tutorials/externals-howto/example1/helloworld.c deleted file mode 100644 index f3660f45ea9f735752fe467bad6c19e68cf77dd6..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example1/helloworld.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * HOWTO write an External for Pure data - * (c) 2001-2006 IOhannes m zmölnig zmoelnig[AT]iem.at - * - * this is the source-code for the first example in the HOWTO - * it creates an object that prints "Hello world!" whenever it - * gets banged. - * - * for legal issues please see the file LICENSE.txt - */ - - - -/** - * include the interface to Pd - */ -#include "m_pd.h" - -/** - * define a new "class" - */ -static t_class *helloworld_class; - - -/** - * this is the dataspace of our new object - * we don't need to store anything, - * however the first (and only) entry in this struct - * is mandatory and of type "t_object" - */ -typedef struct _helloworld { - t_object x_obj; -} t_helloworld; - - -/** - * this method is called whenever a "bang" is sent to the object - * the name of this function is arbitrary and is registered to Pd in the - * helloworld_setup() routine - */ -void helloworld_bang(t_helloworld *x) -{ - /* - * post() is Pd's version of printf() - * the string (which can be formatted like with printf()) will be - * output to wherever Pd thinks it has too (pd's console, the stderr...) - * it automatically adds a newline at the end of the string - */ - post("Hello world !!"); -} - - -/** - * this is the "constructor" of the class - * this method is called whenever a new object of this class is created - * the name of this function is arbitrary and is registered to Pd in the - * helloworld_setup() routine - */ -void *helloworld_new(void) -{ - /* - * call the "constructor" of the parent-class - * this will reserve enough memory to hold "t_helloworld" - */ - t_helloworld *x = (t_helloworld *)pd_new(helloworld_class); - - /* - * return the pointer to the class - this is mandatory - * if you return "0", then the object-creation will fail - */ - return (void *)x; -} - - -/** - * define the function-space of the class - * within a single-object external the name of this function is special - */ -void helloworld_setup(void) { - /* create a new class */ - helloworld_class = class_new(gensym("helloworld"), /* the object's name is "helloworld" */ - (t_newmethod)helloworld_new, /* the object's constructor is "helloworld_new()" */ - 0, /* no special destructor */ - sizeof(t_helloworld), /* the size of the data-space */ - CLASS_DEFAULT, /* a normal pd object */ - 0); /* no creation arguments */ - - /* attach functions to messages */ - /* here we bind the "helloworld_bang()" function to the class "helloworld_class()" - - * it will be called whenever a bang is received - */ - class_addbang(helloworld_class, helloworld_bang); -} diff --git a/doc/tutorials/externals-howto/example2/Makefile b/doc/tutorials/externals-howto/example2/Makefile deleted file mode 100644 index ec17746ec92025866b63fe88e7603eb1b6221a58..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example2/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# Makefile -# (c) 2006 IOhannes m zmölnig - -# just use the Makefile in ../example1/ -# (so i only have to maintain one Makefile) -include ../example1/Makefile diff --git a/doc/tutorials/externals-howto/example2/counter.c b/doc/tutorials/externals-howto/example2/counter.c deleted file mode 100644 index 6c4787c2fb83c462e73681437ed3baa2daceed20..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example2/counter.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * HOWTO write an External for Pure data - * (c) 2001-2006 IOhannes m zmölnig zmoelnig[AT]iem.at - * - * this is the source-code for the second example in the HOWTO - * it creates an object that increments and outputs a counter - * whenever it gets banged. - * - * for legal issues please see the file LICENSE.txt - */ - - - -/** - * include the interface to Pd - */ -#include "m_pd.h" - -/** - * define a new "class" - */ -static t_class *counter_class; - - - -/** - * this is the dataspace of our new object - * the first (mandatory) "t_object" - * and a variable that holds the current counter value - */ -typedef struct _counter { - t_object x_obj; - t_int i_count; -} t_counter; - - -/** - * this method is called whenever a "bang" is sent to the object - * a reference to the class-dataspace is given as argument - * this enables us to do something with the data (e.g. increment the counter) - */ -void counter_bang(t_counter *x) -{ - /* - * convert the current counter value to floating-point to output it later - */ - t_float f=x->i_count; - /* increment the counter */ - x->i_count++; - /* send the old counter-value to the 1st outlet of the object */ - outlet_float(x->x_obj.ob_outlet, f); -} - - -/** - * this is the "constructor" of the class - * we have one argument of type floating-point (as specified below in the counter_setup() routine) - */ -void *counter_new(t_floatarg f) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - - /* set the counter value to the given argument */ - x->i_count=f; - - /* create a new outlet for floating-point values */ - outlet_new(&x->x_obj, &s_float); - - return (void *)x; -} - - -/** - * define the function-space of the class - */ -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, - sizeof(t_counter), - CLASS_DEFAULT, - A_DEFFLOAT, 0); /* the object takes one argument which is a floating-point and defaults to 0 */ - - /* call a function when object gets banged */ - class_addbang(counter_class, counter_bang); -} diff --git a/doc/tutorials/externals-howto/example3/Makefile b/doc/tutorials/externals-howto/example3/Makefile deleted file mode 100644 index ec17746ec92025866b63fe88e7603eb1b6221a58..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example3/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# Makefile -# (c) 2006 IOhannes m zmölnig - -# just use the Makefile in ../example1/ -# (so i only have to maintain one Makefile) -include ../example1/Makefile diff --git a/doc/tutorials/externals-howto/example3/counter.c b/doc/tutorials/externals-howto/example3/counter.c deleted file mode 100644 index 5fa8caef98e31dd01c7b17e19fbd8f2528ea2b17..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example3/counter.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * HOWTO write an External for Pure data - * (c) 2001-2006 IOhannes m zmölnig zmoelnig[AT]iem.at - * - * this is the source-code for the third example in the HOWTO - * it creates an object that increments and outputs a counter - * whenever it gets banged. - * the counter value can be "set" to a special value, or "reset" to a default - * an upper and lower boundary can be specified: whenever the counter crosses - * such boundary a "bang" is emitted at the 2nd outlet and the counter value wraps - * - * for legal issues please see the file LICENSE.txt - */ - - -/** - * include the interface to Pd - */ -#include "m_pd.h" - - -/** - * define a new "class" - */ -static t_class *counter_class; - - -/** - * this is the dataspace of our new object - * the first element is the mandatory "t_object" - * then we have all sort of variables for the - * actual counter value, the step-size and the counting boundaries - * finally we have 2 "t_outlet" elements so we can send data - * to a "named" outlet. - */ -typedef struct _counter { - t_object x_obj; /* mandatory t_object */ - t_int i_count; /* the current counter value */ - t_float step; /* step size; - * this is "float" because of the passive inlet we are using */ - t_int i_down, i_up; /* lower and upper boundary */ - t_outlet *f_out, *b_out; /* outlets */ -} t_counter; - - -/** - * this method is called whenever a "bang" is sent to the object - */ -void counter_bang(t_counter *x) -{ - t_float f=x->i_count; - t_int step = x->step; - x->i_count+=step; - - if (x->i_down-x->i_up) { - if ((step>0) && (x->i_count > x->i_up)) { - x->i_count = x->i_down; - /* we crossed the upper boundary, so we send a bang out of - * the 2nd outlet (which is x->b_out) - */ - outlet_bang(x->b_out); - } else if (x->i_count < x->i_down) { - x->i_count = x->i_up; - outlet_bang(x->b_out); - } - } - /* output the current counter value at the 1st outlet (which is x->f_out) */ - outlet_float(x->f_out, f); -} - - -/** - * this is called whenever a "reset" message is sent to the inlet of the object - * since the "reset" message has no arguments (as declared in counter_setup()) - * we only get a reference to the class-dataspace - */ -void counter_reset(t_counter *x) -{ - x->i_count = x->i_down; -} - - -/** - * this is called whenever a "set" message is sent to the inlet of the object - * since the "set" message has one floating-point argument (as declared in counter_setup()) - * we get a reference to the class-dataspace and the value - */ -void counter_set(t_counter *x, t_floatarg f) -{ - x->i_count = f; -} - - -/** - * this is called whenever a "bound" message is sent to the inlet of the object - * note that in counter_new(), we rewrite a list to the 2nd inlet - * to a "bound" message to the 1st inlet - */ -void counter_bound(t_counter *x, t_floatarg f1, t_floatarg f2) -{ - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; -} - - -/** - * this is the "constructor" of the class - * we expect a variable number of arguments to this object - * symbol "s" is the name of the object itself - * the arguments are given as a t_atom array of argc elements. - */ -void *counter_new(t_symbol *s, int argc, t_atom *argv) -{ - t_counter *x = (t_counter *)pd_new(counter_class); - t_float f1=0, f2=0; - - /* depending on the number of arguments we interprete them differently */ - x->step=1; - switch(argc){ - default: - case 3: - x->step=atom_getfloat(argv+2); - case 2: - f2=atom_getfloat(argv+1); - case 1: - f1=atom_getfloat(argv); - break; - case 0: - break; - } - if (argc<2)f2=f1; - - x->i_down = (f1<f2)?f1:f2; - x->i_up = (f1>f2)?f1:f2; - - x->i_count=x->i_down; - - /* create a new active inlet for this object - * a message with the selector "list" that is sent - * to this inlet (it is the 2nd inlet from left), - * will be appear to be the same message but with the selector "bound" - * at the 1st inlet. - * the method for "bound" messages is given in counter_setup() - */ - inlet_new(&x->x_obj, &x->x_obj.ob_pd, - gensym("list"), gensym("bound")); - - /* create a passive inlet inlet (it will be the 2rd inlet from left) - * whenever a floating point number is sent to this inlet, - * its value will be immediately stored in "x->step" - * no function will be called - */ - floatinlet_new(&x->x_obj, &x->step); - - /* create a new outlet which will output floats - * we store a reference to this outlet in x->f_out - * so we are able to send data to this very outlet - */ - x->f_out = outlet_new(&x->x_obj, &s_float); - /* create a new outlet which will output bangs */ - x->b_out = outlet_new(&x->x_obj, &s_bang); - - return (void *)x; -} - - -/** - * define the function-space of the class - */ -void counter_setup(void) { - counter_class = class_new(gensym("counter"), - (t_newmethod)counter_new, - 0, sizeof(t_counter), - CLASS_DEFAULT, - A_GIMME, /* an arbitrary number of arguments - * which are of arbitrary type */ - 0); - - /* call a function when a "bang" message appears on the first inlet */ - class_addbang (counter_class, counter_bang); - - /* call a function when a "reset" message (without arguments) appears on the first inlet */ - class_addmethod(counter_class, - (t_method)counter_reset, gensym("reset"), 0); - - /* call a function when a "set" message with one float-argument (defaults to 0) - * appears on the first inlet */ - class_addmethod(counter_class, - (t_method)counter_set, gensym("set"), - A_DEFFLOAT, 0); - - /* call a function when a "bound" message with 2 float-argument (both default to 0) - * appears on the first inlet - * this is used for "list" messages which appear on the 2nd inlet - * the magic is done in counter_new() - */ - class_addmethod(counter_class, - (t_method)counter_bound, gensym("bound"), - A_DEFFLOAT, A_DEFFLOAT, 0); - - /* set the name of the help-patch to "help-counter"(.pd) */ - class_sethelpsymbol(counter_class, gensym("help-counter")); -} diff --git a/doc/tutorials/externals-howto/example4/Makefile b/doc/tutorials/externals-howto/example4/Makefile deleted file mode 100644 index ec17746ec92025866b63fe88e7603eb1b6221a58..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example4/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# Makefile -# (c) 2006 IOhannes m zmölnig - -# just use the Makefile in ../example1/ -# (so i only have to maintain one Makefile) -include ../example1/Makefile diff --git a/doc/tutorials/externals-howto/example4/pan~.c b/doc/tutorials/externals-howto/example4/pan~.c deleted file mode 100644 index 06dccd69533e32f2afb43852da333f70a7f94908..0000000000000000000000000000000000000000 --- a/doc/tutorials/externals-howto/example4/pan~.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * HOWTO write an External for Pure data - * (c) 2001-2006 IOhannes m zmölnig zmoelnig[AT]iem.at - * - * this is the source-code for the fourth example in the HOWTO - * it creates a simple dsp-object: - * 2 input signals are mixed into 1 output signal - * the mixing-factor can be set via the 3rd inlet - * - * for legal issues please see the file LICENSE.txt - */ - - -/** - * include the interface to Pd - */ -#include "m_pd.h" - - -/** - * define a new "class" - */ -static t_class *pan_tilde_class; - - -/** - * this is the dataspace of our new object - * the first element is the mandatory "t_object" - * f_pan denotes the mixing-factor - * "f" is a dummy and is used to be able to send floats AS signals. - */ -typedef struct _pan_tilde { - t_object x_obj; - t_sample f_pan; - t_sample f; -} t_pan_tilde; - - -/** - * this is the core of the object - * this perform-routine is called for each signal block - * the name of this function is arbitrary and is registered to Pd in the - * pan_tilde_dsp() function, each time the DSP is turned on - * - * the argument to this function is just a pointer within an array - * we have to know for ourselves how many elements inthis array are - * reserved for us (hint: we declare the number of used elements in the - * pan_tilde_dsp() at registration - * - * since all elements are of type "t_int" we have to cast them to whatever - * we think is apropriate; "apropriate" is how we registered this function - * in pan_tilde_dsp() - */ -t_int *pan_tilde_perform(t_int *w) -{ - /* the first element is a pointer to the dataspace of this object */ - t_pan_tilde *x = (t_pan_tilde *)(w[1]); - /* here is a pointer to the t_sample arrays that hold the 2 input signals */ - t_sample *in1 = (t_sample *)(w[2]); - t_sample *in2 = (t_sample *)(w[3]); - /* here comes the signalblock that will hold the output signal */ - t_sample *out = (t_sample *)(w[4]); - /* all signalblocks are of the same length */ - int n = (int)(w[5]); - /* get (and clip) the mixing-factor */ - t_sample f_pan = (x->f_pan<0)?0.0:(x->f_pan>1)?1.0:x->f_pan; - /* just a counter */ - int i; - - /* this is the main routine: - * mix the 2 input signals into the output signal - */ - for(i=0; i<n; i++) - { - out[i]=in1[i]*(1-f_pan)+in2[i]*f_pan; - } - - /* return a pointer to the dataspace for the next dsp-object */ - return (w+6); -} - - -/** - * register a special perform-routine at the dsp-engine - * this function gets called whenever the DSP is turned ON - * the name of this function is registered in pan_tilde_setup() - */ -void pan_tilde_dsp(t_pan_tilde *x, t_signal **sp) -{ - /* add pan_tilde_perform() to the DSP-tree; - * the pan_tilde_perform() will expect "5" arguments (packed into an - * t_int-array), which are: - * the objects data-space, 3 signal vectors (which happen to be - * 2 input signals and 1 output signal) and the length of the - * signal vectors (all vectors are of the same length) - */ - dsp_add(pan_tilde_perform, 5, x, - sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); -} - - -/** - * this is the "constructor" of the class - * the argument is the initial mixing-factir - */ -void *pan_tilde_new(t_floatarg f) -{ - t_pan_tilde *x = (t_pan_tilde *)pd_new(pan_tilde_class); - - /* save the mixing factor in our dataspace */ - x->f_pan = f; - - /* create a new signal-inlet */ - inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); - - /* create a new passive inlet for the mixing-factor */ - floatinlet_new (&x->x_obj, &x->f_pan); - - /* create a new signal-outlet */ - outlet_new(&x->x_obj, &s_signal); - - return (void *)x; -} - - -/** - * define the function-space of the class - * within a single-object external the name of this function is very special - */ -void pan_tilde_setup(void) { - pan_tilde_class = class_new(gensym("pan~"), - (t_newmethod)pan_tilde_new, - 0, sizeof(t_pan_tilde), - CLASS_DEFAULT, - A_DEFFLOAT, 0); - - /* whenever the audio-engine is turned on, the "pan_tilde_dsp()" - * function will get called - */ - class_addmethod(pan_tilde_class, - (t_method)pan_tilde_dsp, gensym("dsp"), 0); - /* if no signal is connected to the first inlet, we can as well - * connect a number box to it and use it as "signal" - */ - CLASS_MAINSIGNALIN(pan_tilde_class, t_pan_tilde, f); -} diff --git a/packages/Makefile b/packages/Makefile index 775420ca3f57ca631cffc6e14c1eeb8c749fbcb1..f5c1f8c09b4b722fc579a73de66379500dda3d6d 100644 --- a/packages/Makefile +++ b/packages/Makefile @@ -175,7 +175,7 @@ endif #==============================================================================# # this is used for installing into a pre-build Pd binary -extended_install: abstractions_install doc_install \ +extended_install: abstractions_install \ externals_install readme_install welcome_install \ license_install noncvs_install @@ -195,12 +195,6 @@ devel_install: pd_devel_install abstractions_install: $(MAKE) -C $(abstractions_src) $(DEST_PATHS) install -#------------------------------------------------------------------------------ -# doc_install -doc_install: - $(MAKE) -C $(doc_src) $(DEST_PATHS) install - - #------------------------------------------------------------------------------ # extensions_install extensions_install: @@ -425,7 +419,6 @@ clean: abstractions_clean doc_clean externals_clean pd_clean distclean: cruft_clean $(MAKE) -C $(abstractions_src) distclean - $(MAKE) -C $(doc_src) distclean $(MAKE) -C $(extensions_src) distclean $(MAKE) -C $(externals_src) distclean -$(MAKE) -C $(pd_src) distclean diff --git a/packages/Makefile.buildlayout b/packages/Makefile.buildlayout index 2e782ec568b0a513ff3e713502e54ca5975a28fe..56a6ce15595a776cfae92ee984e73b682aa62218 100644 --- a/packages/Makefile.buildlayout +++ b/packages/Makefile.buildlayout @@ -22,7 +22,6 @@ # extensions # externals # packages -# doc # # it will be going here too: # gem @@ -88,7 +87,6 @@ DEBUG_CFLAGS = -ggdb # sources abstractions_src = $(cvs_root_dir)/abstractions -doc_src = $(cvs_root_dir)/doc extensions_src = $(cvs_root_dir)/extensions externals_src = $(cvs_root_dir)/externals flext_src = $(cvs_root_dir)/externals/grill/flext diff --git a/packages/darwin_app/Makefile b/packages/darwin_app/Makefile index 6aaf0eafb5a478ed30676bf780d73f3a2773ed14..86823d29e1d649ec59b47b812e969206c47b6599 100644 --- a/packages/darwin_app/Makefile +++ b/packages/darwin_app/Makefile @@ -69,7 +69,6 @@ extended_install: # on Mac OS X 10.6/Snow Leopard don't build Gem since it needs Carbon ifeq ($(shell uname -r | sed 's|10\.[0-9][0-9]*\.[0-9][0-9]*|10|'),10) $(MAKE) -C $(packages_src) $(DEST_PATHS) abstractions_install - $(MAKE) -C $(packages_src) $(DEST_PATHS) doc_install $(MAKE) -C $(packages_src) $(DEST_PATHS) externals_install $(MAKE) -C $(packages_src) $(DEST_PATHS) readme_install $(MAKE) -C $(packages_src) $(DEST_PATHS) welcome_install @@ -97,7 +96,6 @@ endif # Pd.app in $(BUILD_BASE)/Pd.app extended_app_install: $(MAKE) -C $(packages_src) $(DEST_PATHS) abstractions_install - $(MAKE) -C $(packages_src) $(DEST_PATHS) doc_install $(MAKE) -C $(packages_src) $(DEST_PATHS) externals_install diff --git a/doc/media/midr-mjpeg.mov b/pd/doc/media/midr-mjpeg.mov similarity index 100% rename from doc/media/midr-mjpeg.mov rename to pd/doc/media/midr-mjpeg.mov