Pd Documentation chapter 4: externals

back to table of contents

4. External Objects & Libraries

4.1. What are: Vanilla Objects, Internals & Externals?

Basically, internals are the objects that come as part of the Pd Vanilla (the main binary distribution of Pure Data, provided by Miller Puckette : http://msp.ucsd.edu/software.html ) , whereas external objects are not! Besides internals, the Pd Vanilla distribution also comes with a few "extra" objects that are not part of its binary. Therefore, Vanilla objects (the built-in objects in Pd) include internals and externals.

Nonetheless, "externals" most commonly refer to objects that do not available in the Pd Vanilla distribution, meaning that usually you have to download these objects and install them properly so they can be loaded into Pd patches.

Figure 4.1 - Excerpt from list of Vanilla objects (help-intro.pd file)

To get a full list of all objects in Pd Vanilla, go to the Help menu and then select List of Objects, or alternatively right click on an empty spot of a patch's window and select "help" - this loads the help-intro.pd file.

Figure 4.2 - Extra objects from Pd Vanilla

The extra objects, which reside in a folder named "extra" inside the Pd application, are presented at the very end of the "help-intro.pd". They can also be viewed in the Help Browser menu (Help => Browser). See Figure 4.2 above, which shows how the browser looks in a fresh install of Pd and lists the objects in the extra folder.

4.1.2. What are the Types of External Objects?

An object in Pd can be either a patch - meaning a Pd file (a.k.a abstraction) - or a compiled binary (note that a binary can contain only one or several external objects, as discussed further on). More details about these two possible types below.

4.1.2.1. Compiled objects:

These are Pd objects compiled to binaries from programming code (like in C or C++). They have to be compiled for your operating system, which means the binaries have different extensions according to each platform. For instance:

4.1.2.2. Abstractions:

You can save pd patches and make them behave like objects by loading them into your patches, these are usually called "Abstractions". Note that some of the "extra" objects from Vanilla that you can see in Figure 4.2 are Pd files/patches. Note that abstractions, like any other Pd file, may contain any kind of objects (internals, compiled externals and even other abstractions).

4.1.3. What are External Libraries?

In practical terms, an external library is a collection of external objects of any kind (abstractions or compiled objects). But when it comes to compiled objects, a library can provide several objects as a single binary pack or as a set of separate binaries (where each object has its own binary).

The "classic" library is a single binary pack (with two or more externals), but splitting into separate binaries became very common. A single external binary (not part of any set of objects) is still technically a library with just one object, and a library with separate binaries could be considered as a set of libraries. But again, in practical terms, the more general concept of a library is that it is just a set of objects. What’s important to note is that there are significant differences for loading externals wether if they are a single binary pack or a set of separate binaries (as we’ll see in this tutorial later on).

4.1.4. What are the types of External Libraries?

Libraries can come in all sorts of ways; as only a collection of abstractions (like "list-abs"), only compiled objects, or both. It can even mix compiled externals both as a set of separate binaries and a single binary pack. Basically, any combination is possible for a set of external.

One example that combines all external options is cyclone 0.3, which provides most of its objects as a set of separate binaries, but also includes a small collection of 12 objects as a single binary pack plus a few abstractions.

Wrapping up Part 1)




4.2. Writing Pd objects in C

You can write your own objects that you and others can use in their Pd applications. You can write them in C or (if you're smart and brave) in C++ or FORTRAN.

HOW EXTERNS ARE LOADED

Whenever you type the name of an object (into an "object" text box) that Pd doesn't yet know about, Pd looks for a relocatable object file, named, for instance, "profile.pd_irix5". Pd looks first in the directory containing the patch, then in directories in its "path." Pd will then add whatever object is defined there to its "class list," which is the set of all Pd classes you can use. If all this works, Pd then attempts again to create the object you asked for, this time perhaps successfully. There is no difference between an object defined this way and an object built into Pd.

Once you load a new object into Pd, it's there for the duration of your Pd session. If you load another Pd document which supplies a different version of some Pd object, the object won't be updated. IF you're working on a new object and decide to change it, you have to exit and re-enter Pd to get the change to take.

In the "externs" subdirectory of the documentation you can find simple examples of "externs" with their source code and test patches; there are many other on the web (see section 1.2 ).

IOhannes zmölnig has written an excellent guide to writing externs at http://pdstatic.iem.at/externals-HOWTO/ .


4.3. Installing External Objects and Libraries

Installing externals in Pd is quite simple, all you need to do is download your externals from somewhere, such as from Pd Vanilla directly, and include them in a proper folder.

4.3.1. Where to include the externals?

You can have externals basically anywhere in your computer, but Pd must know where to look for them. Since Pd 0.48, Pd can automatically create a documents directory for patches and external libraries. At launching Pd for the first time, it asks you to create this folder, which is the current best practice. This automatically includes the folder in the search paths (under Preferences => Path).

Figure 4.3 - Preferences => Path window

If you accept that Pd creates that folder for you, you should have something like this in a fresh install of Pd under Preferences => Path. This is for macOS, where the "Pd" folder is created under ~/Documents, and inside it we have a folder for externals. Even if you did not create this folder, here is where you can create it by clicking the "Reset" button under "Pd Documents Directory".

Pd can actually search for externals anywhere, they just need to be included in the search paths. Nontheless, Pd also has other places it can search for externals. This can be the same folder that your patch is saved on (the Relative Path) or the Standard Paths, which are:

The Standard Paths are not listed in Preferences => Path, as those only include paths added by the user. And again, the current best practice is to have external folders inside an external folder added to Pd search paths (as ~/Documents/Pd/externals). Earlier practices made use of these standard paths above, but note that the user-specific and global standard paths are not automatically created by Pd.

This structure is still kept as an old heritage of Pd and is documented here because of that. It may also serve some edge cases. The Global folder affects all Pure Data Applications for all users. The User-specific folder affects all Pure Data Applications for that user. And since you can have different versions of Pd installed in your system, the Application-specific folder affects only that particular Pd Application. This can be not only an older and a newer version of Pd, but also both 32-bit and 64-bit versions. For reference, here's the list of the Standard Paths for all operating systems:

A) macOS:

B) Windows:

C) GNU/Linux:

4.3.2. How to Download Externals from Pd Vanilla?

Since version 0.47-0, Pd Vanilla has its own external manager! This is a built in .tcl plug-in named "deken" that has been incorporated into the Pd Vanilla distribution to manage the download of external libraries and externals.

So you can just open Pd, click on the "Help" menu and select Help > Find externals. Then you can just type the library's name you want and hit enter or click "search". You can also look for an external name and the library that contains it might be shown. All available versions of the library specific for your operating system will be shown to you. See figure below.

Figure 4.4 - Searching for External Libraries from Pd Vanilla

When you click on the version you want, by default, Pd asks if you want to download it to the external folder set under Preferences => Path. If you say no, you can specify somewhere else to download it to. If you say yes, there is where it gets downloaded to.


4.4. Loading Externals

The current best practice is to use the [declare] object, but there are alternatives. If the library is a single binary pack, it needs to be loaded so you can create externals. This is done either via the [declare] object or manually via Preferences => Startup.

Now, if the external library only contains abstractions or objects compiled as a set of separate binaries, Pd just needs to know its. Again, this can be done with [declare] or manually (via Preferences => Path).

4.4.1. Using the [declare] object:

The [declare] object from Pd Vanilla behaves quite similarly to adding search paths to the user added paths (under Preferences => Path) or adding libraries (under Preferences => Startup). The difference is that it'll only work for the patch containing the [declare]. This means that when you add manually via preferences, it installs it permanently and for any patch.

4.4.1.1. [declare -path]:

Let's take for an example the ELSE library (http://github.com/porres/pd-else) . This library contains 2 separate binaries and abstractions, so Pd only needs to know its location path. So we can do something like [declare -path else] and Pd will look for a folder named else to add it to the search path.

But where does Pd look the else folder? In the locations it knows where to look (the Relative Path, the Standard Paths or the User Added Paths). So let's say you downloaded the else library folder into "~/Documents/Pd/ externals", which is the current best practice. Pd will know to look for it there and will find it!

4.4.1.2. [declare -lib]:

This is needed for the classic Pd library format, which is a single binary pack with many externals. One such example is the "zexy" library. So once you have downloaded it, you can use [declare -lib zexy]. In the same way, Pd will search for the zexy binary in locations it knows where to look (as in "~/ Documents/Pd/externals").

Does this mean you need to also include the zexy folder path, so Pd knows to search for the zexy binary inside? Not really, because there's a trick here. If Pd finda a 'zexy' location, it knows it can look inside it for the 'zexy' binary, so it will succeed in finding it just with that!

4.4.2. Using Path and Startup:

This is basically the same as using [declare] but it will permanently work every time Pd starts and for any patch.

4.4.2.1. User added Path:

You can add User Added Paths in Preferences => Path. We've seen that even if you have a folder into "~/Documents/Pd/externals" you still need to tell Pd to look for it. You can do this manually added to Pd's search paths so it can be automatically by clicking "New".

Another possibility is that "Deken"offers a preference tabs where you can click once on "Should newly installed libraries be added to Pd's search Path?" to prompt you if you want to add a downloaded library to the user added search paths after you download it. By default, it never asks you to do it. You can also click twice so it always add anything you download from deken to the search path, which is not quite recomended as sometimes you'll download a single binary pack, where adding it to the search path doesn't really help.

4.4.2.2. Startup:

In "Preferences => Startup", you load a window that says "Pd libraries to load on startup". This is where you can manually and permanently load single binary pack libraries. As we've seen with 'zexy', it's common that the name of the binary is the same as the library's, so you don't need to worry about setting the path. Another example is the 'cyclone' library,

Figure 4.5 - Loading the cyclone and zexy binaries/libraries in "Startup"

As previously mentioned, cyclone 0.3 is a special case that includes objects as abstractions, as a set of separate binaries but also has a set a single binary pack that loads objects with non alphanumeric names, which need to be loaded as a single binary pack to avoid issues. One particularity of cylone is that loading its binary will also force Pd to add its path to the search paths, so you don't need to bother adding it to the path as well so you can load its abstractions or separate binaries.

It depends on the developer, but it is common and a good practice that when you load a library, Pd's terminal window will print something to tell us that the libraries were loaded successfully. Here's a screenshot of the result of loading cyclone and zexy via the startup (same happens if you load them via [declare], clearly).

Figure 4.6 - Pd's terminal window after loading cyclone and zexy

4.4.3. Slash declarations:

You can also use slash declarations to search for libraries in paths that are relative to these. For instance, let's say you downloaded the ELSE library into ~/Documents/Pd/externals, or any other folder Pd will eventually search for. Instead of using [declare -path] or adding the ELSE folder to the user added paths, you can just prepend "else/" before an object name that Pd will try to find this object in a folder called else in one of its search paths! Here's an example:

Note that if you do that, you can still add the 'else' folder to Pd's search path or use [declare -path else], but it will just be redundanct. Now, what are the diffences of this method over using [declare] or adding the path to the user added paths? The only use case is if you have two externals with the same name from two different libraries in the same patch. With this method you can specify which one is which!

A library name prefix may also be pertinent in the context of single binary packs. The cyclone library has a set of 12 objects with non alphanumeric names, such as [>~]. But it uses an internal trick of adding a class creator, so creating the object as [cyclone/>~] also works. But note that the library still needs to be loaded anyway (via startup or [declare]).

There's also the case where you can find a single binary pack that has a different name than that of the library. One example is timbreID, which has a timbreIDLib as the binary file. In this case you need to specify the timbreID folder with a slash declaration as in "timbreID/timbreiIDLib" in Startup. This also works in declare as in [declare -lib timbreID/timbreiIDLib].