~pbatch/patchwerk

patchwerk/subpatch.w -rw-r--r-- 4.3 KiB
9c265356 — paul plan9 additions from Sigrid 3 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
@** Subpatch.
\mkref{subpatch}
A subpatch can thought up as an abstraction of a patch.
A subpatch is first populated via |pw_patch|, then exported as a subpatch.
A subpatch contains the necessary state information to compute and destroy
a self-contained audio graph. Subpatches were created to support
on-the-fly hotswapping for live coding.

@<Top@>+=
@<Subpatch Top@>

@* Data.

@ The data contents of a |pw_subpatch| are contained in a |typedef| inside
of the |@<Header@>|. The contents of this patch are the core elements needed
to represent an audio graph created without the need of |pw_patch|:
\smallskip
{
\par
\begingroup
\leftskip=20pt
\item{$\bullet$} The variables |nodes| and |last| refer to the root and
last item of the linked list.
\item{$\bullet$} The number of nodes is contained in the variable |nnodes|.
\item{$\bullet$} The output cable |out| is the output of the audio graph.
\item{$\bullet$} The pointer list |plist|, containing data allocated inside
of the patch.
\par
\endgroup
}

@<Type Declarations@>+=
typedef struct {
    pw_node *nodes;
    pw_node *last;
    int nnodes;
    pw_cable *out;
    pw_pointerlist plist;
} pw_subpatch;

@* Functions.

@ The function |pw_subpatch_init| initializes a subpatch by setting the
number of nodes |nnodes| to 0.
@ @<Header@>+=
void pw_subpatch_init(pw_subpatch *subpatch);

@ @<Subpatch Top@>+=
void pw_subpatch_init(pw_subpatch *subpatch)
{
    subpatch->nnodes = 0;
    pw_pointerlist_init(&subpatch->plist);
}

@ The function |pw_subpatch_save| copies variables from |pw_patch|
to a |pw_subpatch| variable, thus producing a snapshot of the |pw_patch| state.
In practice, it is best to call |pw_patch_clear| or
|pw_patch_reinit| after saving a patch, as
it resets the values in the |pw_patch| instance.

@ @<Header@>+=
void pw_subpatch_save(pw_patch *patch, pw_subpatch *subpatch);
@ @<Subpatch Top@>+=
void pw_subpatch_save(pw_patch *patch, pw_subpatch *subpatch)
{
    subpatch->nodes = patch->nodes;
    subpatch->last = patch->last;
    subpatch->nnodes = patch->nnodes;
    subpatch->out = patch->out;
    subpatch->plist = patch->plist;
}

@ The function |pw_subpatch_restore| copies variables from a |pw_subpatch|
instance to a |pw_patch| instance.

@ @<Header@>+=
void pw_subpatch_restore(pw_patch *patch, pw_subpatch *subpatch);

@ @<Subpatch Top@>+=
void pw_subpatch_restore(pw_patch *patch, pw_subpatch *subpatch)
{
    patch->nodes = subpatch->nodes;
    patch->last = subpatch->last;
    patch->nnodes = subpatch->nnodes;
    patch->out = subpatch->out;
    patch->plist = subpatch->plist;
}

@ The function |pw_subpatch_compute| computes a sample block for a patch
contained inside of a subpatch.
@<Header@>+=
void pw_subpatch_compute(pw_subpatch *subpatch);

@ @<Subpatch Top@> +=
void pw_subpatch_compute(pw_subpatch *subpatch)
{
    int n;
    pw_node *node;
    pw_node *next;
    node = subpatch->nodes;
    for(n = 0; n < subpatch->nnodes; n++) {
        next = pw_node_get_next(node);
        pw_node_compute(node);
        node = next;
    }
}

@ The function |pw_subpatch_destroy| calls the destroy function inside of
each node contained in the |pw_subpatch|.
@<Header@>+=
void pw_subpatch_destroy(pw_subpatch *subpatch);

@ @<Subpatch Top@> +=
void pw_subpatch_destroy(pw_subpatch *subpatch)
{
    int n;
    pw_node *node;
    pw_node *next;
    node = subpatch->nodes;
    for(n = 0; n < subpatch->nnodes; n++) {
        next = pw_node_get_next(node);
        pw_node_destroy(node);
        node = next;
    }
}

@ The function |pw_subpatch_free| frees the nodes inside of a subpatch.
In addition, this function also frees and re-initializes the internal
pointer list.
@<Header@>+=
void pw_subpatch_free(pw_subpatch *subpatch);

@ @<Subpatch Top@> +=
void pw_subpatch_free(pw_subpatch *subpatch)
{
    int n;
    pw_node *node;
    pw_node *next;
    node = subpatch->nodes;
    for(n = 0; n < subpatch->nnodes; n++) {
        next = pw_node_get_next(node);
        free(node);
        node = next;
    }
    subpatch->nnodes = 0;
    pw_pointerlist_free(&subpatch->plist);
    pw_pointerlist_init(&subpatch->plist);
}

@ The function |pw_subpatch_out| returns the output cable in the
|pw_subpatch_out|.
@<Header@>+=
pw_cable *pw_subpatch_out(pw_subpatch *subpatch);

@ @<Subpatch Top@> +=
pw_cable *pw_subpatch_out(pw_subpatch *subpatch)
{
    return subpatch->out;
}