pddb
is a JSON database that parses the Pure Data source code to get data about
the internal objects. It is useful in the context of the pdpy
project, with
possible other uses like autocomplete, error check when typing, etc. In the
following text there is a brief description of the JSON data structure.
Simply run make start
, start typing your queries.
You should see a message like this on your Terminal:
Starting live database...
Type your queries, eg: osc~, and hit RETURN to get the result.
Type QUIT and hit RETURN to quit.
Starting server...
Starting client...
Listening on 127.0.0.1:9226
Connected by ('127.0.0.1', 61874)
For example, when typing osc~
and hitting return, this is the result:
osc~
Received: [True, namespace(inlets=2, outlets=1), 1]
Which means that osc~
- is an object -->
True
- has 2 inlets and 1 outlet -->
namespace(inlets=2, outlets=1))
- takes 1 optional creation argument -->
1
Simply run wget https://raw.githubusercontent.com/fdch/pddb/main/pddb.json
- Clone or download the Pure Data distribution
- Clone or download this repository.
- Run the following:
cd pddb
make PDDIR=/path/to/pure-data
Where /path/to/pure-data
is the path to your Pure Data distribution.
Mine looks like ~/Development/pure-data
, which is the default.
The purpose of this database is to better understand the internal structure of
the Pure Data
source code, and to enable language checks for the pdpy
project.
PRs are welcome.
You can load pddb.json
as a json object like this:
import json
with open('pddpy.json') as f:
data = json.load(f)
print(data)
NOTE: the data
variable will be used in the python examples that follow.
This database is an Array
of Object
s, meaning that:
- A single
Array
encloses the entire database. - Every element contains exactly one Entry Object.
Each entry Object
has two keys named file
and classes
. The structure
looks like this:
[
{
"file" : '',
"classes" : []
}, ...
]
>>> data[0]['file']
'/path/to/pure-data/extra/pique/pique.c'
This key contains exactly one String
with the path to the Pure Data .c
file
from which the data of that specific entry was obtained.
In python, you can extract all file
keys like this:
>>> [entry['file'] for entry in data]
['/path/to/pure-data/extra/pique/pique.c', ... ****]
>>> data[0]['classes']
[{'className': 'pique', 'attributes': {'patchable': False, 'newmethod': 'pique_new', 'arguments': {'name': 'pique', 'args': ['A_DEFFLOAT']}, 'methods': ['list', {'name': 'errthresh', 'args': ['A_FLOAT']}], 'description': {'kind': 'data', 'subkind': 'array'}, 'iolets': {'outlets': 1}}}]
This key contains an Array
of Class Objects that describe the Pure Data classes found in the file path to which file
points. In this classes
key you will find most of the data.
Each class Object
has two keys: className
and attributes
.
[
{
"file": "",
"classes": [
{
"className": "",
"attributes": {} | []
}, ...
}, ...
]
>>> data[0]['classes'][0]['className']
'pique'
This key has exactly one String
with the name by which this specific class
is refered to internally in the source code.
>>> data[0]['classes'][0]['attributes']
{'patchable': False, 'newmethod': 'pique_new', 'arguments': {'name': 'pique', 'args': ['A_DEFFLOAT']}, 'methods': ['list', {'name': 'errthresh', 'args': ['A_FLOAT']}], 'description': {'kind': 'data', 'subkind': 'array'}, 'iolets': {'outlets': 1}}
This key can hold either one or multiple Attribute Objects.
Therefore, it can be either an Object
or an Array
of Object
s and needs
to be parsed accordingly.
This Object
contains variable keys depending on the Pure Data class it describes. The possible keys are:
Key | Type | Description |
---|---|---|
patchable |
bool |
Describes if object has inlets or not. |
newmethod |
String |
The method by which the class is instantiated as a new object. |
arguments |
`Object | String` |
methods |
`String | Object |
description |
Object |
Describes the object with kind and a subkind keys. See Description Object. |
iolets |
Object |
Describes the objects inlets and outlets . See iolet Object. |
signal |
bool |
Describes if object processes audio or not. |
alias |
String |
This contains an alias string that can be used to create the object when patching. |
help |
String |
This contains the help file identifier when multiple objects are grouped into the same help file. |
>>> data[0]['classes'][0]['attributes']['arguments']
{'name': 'pique', 'args': ['A_DEFFLOAT']}
This key can either be a String
or an argument Object
(See Argument Object)
>>> data[3]['classes'][0]['attributes']['arguments']
'loop~'
If arguments
is a String
, this means that the Pure Data object does not take any arguments except the creation argument. So, the String
represents the argument needed to create the object when patching.
>>> data[23]['classes'][0]['attributes']['arguments']
{'name': 'delay', 'args': ['A_DEFFLOAT', 'A_DEFFLOAT', 'A_DEFSYM']}
If arguments
is an Object
, then the Pure Data object takes arguments besides its creation argument.
The argument Object
contains a name
and an args
keys, for example:
"arguments": {
"name": "moses",
"args": [
"A_DEFFLOAT"
]
}
If the argument Object
is within the arguments
key, then the name
key points to the creation argument (e.g., "moses"
or "array define"
).
>>> data[0]['classes'][0]['attributes']['arguments']['name']
'pique'
However, it it is within the methods
key, then the name
key points to the "message" header.
For example, in the case of the netreceive
object, the message header to set the internal port is "listen", and it takes a list
as argument. This looks like this:
"name": "listen",
"args": [
"A_GIMME"
]
The args
key contains an Array
of argument types as defined in the Pure Data source code (e.g., "A_DEFFLOAT"
). The list of possible argument types is:
Type | Description |
---|---|
A_DEFFLOAT |
A float type argument that can either be present or the Pure Data object falls back to the argument's default value. |
A_GIMME |
A list of arguments. |
A_DEFSYM |
A symbol type argument that can either be present or the Pure Data object falls back to the argument's default value. |
A_DEFSYMBOL |
Same as "A_DEFSYM" |
A_FLOAT |
A float type argument that must be present. |
A_SYMBOL |
A symbol type argument that must be present. |
This key describes the way to interface with the object via Pure Data "messages". The methods
key can be either a String
or an argument Object
or an Array
combining both.
If there is no methods
key present, then the object takes no messages.
This Array
can hold a combination of String
and argument Object
s.
This needs to be taken into account when parsing. Continue reading for each specification.
>>> data[26]['classes'][0]['attributes']['methods']
'list'
If methods
is a String
, this means that the Pure Data object takes only one message. So, the String
represents the message that takes exactly one symbol, for example, the "bang" message. The above
example is from the midiin
object.
>>> data[23]['classes'][0]['attributes']['methods']
['bang', 'stop', {'name': 'float', 'args': ['A_FLOAT']}, {'name': 'tempo', 'args': ['A_FLOAT', 'A_SYMBOL']}]
This Object
describes the way to construct the message to interface with the Pure Data object. It is exactly like the arguments object. See Argument Object.
The above example is from the delay
object.
>>> data[26]['classes'][0]['attributes']['description']
{'kind': 'interface', 'subkind': 'midi'}
The description Object
contains two keys, kind
and subkind
, each holding a String
that attempts to classify the Pure Data object in the following way:
These are the different kinds of Pure Data objects that this description performs:
data, signal, interface, parsing, control, operators
Kind | Description |
---|---|
signal |
The object processes audio in DSP blocks |
interface |
Objects that handle user interface actions |
operators |
Control operators |
data |
Handle various data structures |
parsing |
Parsing functions |
control |
Control flow |
nonobj |
Non public objects |
obsolete |
Objects marked as obsolete |
extra |
None of the above kind |
These are the different sub-kinds of Pure Data objects that this description performs:
array, analysis, midi, generators, block, list, system, time, gui, math, stream, other, text, struct, fourier, filters, canvas, format, network, control_to_sig, flow, delays, comparison, binary, keyboard, route, types
signal |
Description |
---|---|
math |
Performs mathematical functions on the audio block. |
fourier |
Performs the Fast Fourier Transform on the audio block. |
filters |
Filters the audio signal block. |
flow |
Signal object inlets and outlets. |
delays |
Delays a signal block. |
route |
Signal routing. |
generators |
Signal generators. |
system |
Input/Output to disk or to audio interface. |
control_to_sig |
Converts control to signal. |
array |
Interface signals with tables and arrays. |
block |
Interface to change the DSP block. |
analysis |
Analyze the signal block. |
interface |
Description |
---|---|
midi |
Handle MIDI input and output |
keyboard |
Handle Keyboard events |
system |
Handle System events |
gui |
Graphical User Interface objects |
operators |
Description |
---|---|
math |
Mathematical operators |
binary |
Binary operators |
comparison |
Comparison perators |
data |
Description |
---|---|
array |
Tables and Arrays |
struct |
Data Structures |
text |
Text objects |
canvas |
Subpatches |
other |
None of the above |
parsing |
Description |
---|---|
list |
Parse list elements |
stream |
Parse an incoming stream |
forma |
Format parsing |
control |
Description |
---|---|
flow |
Inlets and Outlets |
network |
Network objects |
math |
Mathematical operations |
time |
Delay and time operations |
generators |
Control flow Generators |
types |
Type casting |
>>> data[35]['classes'][0]['attributes']['iolets']
{'inlets': 2, 'outlets': 1}
The iolets Object
contains two keys, inlets
and outlets
, each
holding a Number
that describes how many inlet
and outlet
the Pure Data
object box has. The above example is from the hip~
object.
This is an example of the x_misc.c
entry. The only class that is shown is the
random
class, the rest are omitted:
[
{
"file": "/Users/fd/Development/pure-data/src/x_misc.c",
"classes": [
{
"className": "random",
"attributes": {
"patchable": true,
"newmethod": "random_new",
"arguments": {
"name": "random",
"args": [
"A_DEFFLOAT"
]
},
"methods": "bang",
"description": {
"kind": "control",
"subkind": "generators"
},
"iolets": {
"inlets": 2,
"outlets": 1
}
}
}, ...
}, ...
]
The "random"
className
is located in the x_misc.c
file. The
Pure Data object is created with the "random"
symbol and an
optional float (A_DEFFLOAT
). It has a single method that is
represented by the "bang"
string, and it is described as a
control
object of the generators
subkind. It has 2
inlets and
1
outlet.
While this is true, it is incomplete. From this description alone,
we are missing information about the functionality of the object.
For example, we cannot know what the object does. Other limitations come from the fact that the .c
files are not loaded but parsed,
and some object attributes may depend on creation arguments and other
circumstances during instantiation. Accounting for these is still in the todo list.
You are of course welcome to help in any way. Please file an issue or make a PR!
Fede Camara Halac (fdch)
Pure Data by Miller Puckette.