A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/* Copyright (c) 1997-1999 Miller Puckette.
2* For information on usage and redistribution, and for a DISCLAIMER OF ALL
3* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
4
5/* graphical inlets and outlets, both for control and signals. */
6
7/* This code is highly inefficient; messages actually have to be forwarded
8by inlets and outlets. The outlet is in even worse shape than the inlet;
9in order to avoid having a "signal" method in the class, the oulet actually
10sprouts an inlet, which forwards the message to the "outlet" object, which
11sends it on to the outlet proper. Another way to do it would be to have
12separate classes for "signal" and "control" outlets, but this would complicate
13life elsewhere. */
14
15
16/* hacked to run subpatches with different samplerates
17 *
18 * mfg.gfd.uil
19 * IOhannes
20 *
21 * edited lines are marked with "IOhannes"
22 *
23 */
24
25#ifdef ROCKBOX
26#include "plugin.h"
27#include "../../pdbox.h"
28#include "m_pd.h"
29#include "g_canvas.h"
30#else
31#include "m_pd.h"
32#include "g_canvas.h"
33#include <string.h>
34#endif
35
36void signal_setborrowed(t_signal *sig, t_signal *sig2);
37void signal_makereusable(t_signal *sig);
38
39/* ------------------------- vinlet -------------------------- */
40t_class *vinlet_class;
41
42typedef struct _vinlet
43{
44 t_object x_obj;
45 t_canvas *x_canvas;
46 t_inlet *x_inlet;
47 int x_bufsize;
48 t_float *x_buf; /* signal buffer; zero if not a signal */
49 t_float *x_endbuf;
50 t_float *x_fill;
51 t_float *x_read;
52 int x_hop;
53 /* if not reblocking, the next slot communicates the parent's inlet
54 signal from the prolog to the DSP routine: */
55 t_signal *x_directsignal;
56
57 t_resample x_updown; /* IOhannes */
58} t_vinlet;
59
60static void *vinlet_new(t_symbol *s)
61{
62#ifdef ROCKBOX
63 (void) s;
64#endif
65 t_vinlet *x = (t_vinlet *)pd_new(vinlet_class);
66 x->x_canvas = canvas_getcurrent();
67 x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, 0);
68 x->x_bufsize = 0;
69 x->x_buf = 0;
70 outlet_new(&x->x_obj, 0);
71 return (x);
72}
73
74static void vinlet_bang(t_vinlet *x)
75{
76 outlet_bang(x->x_obj.ob_outlet);
77}
78
79static void vinlet_pointer(t_vinlet *x, t_gpointer *gp)
80{
81 outlet_pointer(x->x_obj.ob_outlet, gp);
82}
83
84static void vinlet_float(t_vinlet *x, t_float f)
85{
86 outlet_float(x->x_obj.ob_outlet, f);
87}
88
89static void vinlet_symbol(t_vinlet *x, t_symbol *s)
90{
91 outlet_symbol(x->x_obj.ob_outlet, s);
92}
93
94static void vinlet_list(t_vinlet *x, t_symbol *s, int argc, t_atom *argv)
95{
96 outlet_list(x->x_obj.ob_outlet, s, argc, argv);
97}
98
99static void vinlet_anything(t_vinlet *x, t_symbol *s, int argc, t_atom *argv)
100{
101 outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
102}
103
104static void vinlet_free(t_vinlet *x)
105{
106 canvas_rminlet(x->x_canvas, x->x_inlet);
107 resample_free(&x->x_updown);
108}
109
110t_inlet *vinlet_getit(t_pd *x)
111{
112 if (pd_class(x) != vinlet_class) bug("vinlet_getit");
113 return (((t_vinlet *)x)->x_inlet);
114}
115
116/* ------------------------- signal inlet -------------------------- */
117int vinlet_issignal(t_vinlet *x)
118{
119 return (x->x_buf != 0);
120}
121
122#ifndef ROCKBOX
123static int tot;
124#endif
125
126t_int *vinlet_perform(t_int *w)
127{
128 t_vinlet *x = (t_vinlet *)(w[1]);
129 t_float *out = (t_float *)(w[2]);
130 int n = (int)(w[3]);
131 t_float *in = x->x_read;
132#if 0
133 if (tot < 5) post("-in %x out %x n %d", in, out, n);
134 if (tot < 5) post("-buf %x endbuf %x", x->x_buf, x->x_endbuf);
135 if (tot < 5) post("in[0] %f in[1] %f in[2] %f", in[0], in[1], in[2]);
136#endif
137 while (n--) *out++ = *in++;
138 if (in == x->x_endbuf) in = x->x_buf;
139 x->x_read = in;
140 return (w+4);
141}
142
143static void vinlet_dsp(t_vinlet *x, t_signal **sp)
144{
145 t_signal *outsig;
146 /* no buffer means we're not a signal inlet */
147 if (!x->x_buf)
148 return;
149 outsig = sp[0];
150 if (x->x_directsignal)
151 {
152 signal_setborrowed(sp[0], x->x_directsignal);
153 }
154 else
155 {
156 dsp_add(vinlet_perform, 3, x, outsig->s_vec, outsig->s_n);
157 x->x_read = x->x_buf;
158 }
159}
160
161 /* prolog code: loads buffer from parent patch */
162t_int *vinlet_doprolog(t_int *w)
163{
164 t_vinlet *x = (t_vinlet *)(w[1]);
165 t_float *in = (t_float *)(w[2]);
166 int n = (int)(w[3]);
167 t_float *out = x->x_fill;
168 if (out == x->x_endbuf)
169 {
170 t_float *f1 = x->x_buf, *f2 = x->x_buf + x->x_hop;
171 int nshift = x->x_bufsize - x->x_hop;
172 out -= x->x_hop;
173 while (nshift--) *f1++ = *f2++;
174 }
175#if 0
176 if (tot < 5) post("in %x out %x n %x", in, out, n), tot++;
177 if (tot < 5) post("in[0] %f in[1] %f in[2] %f", in[0], in[1], in[2]);
178#endif
179
180 while (n--) *out++ = *in++;
181 x->x_fill = out;
182 return (w+4);
183}
184
185int inlet_getsignalindex(t_inlet *x);
186
187 /* set up prolog DSP code */
188void vinlet_dspprolog(t_vinlet *x, t_signal **parentsigs,
189 int myvecsize, int phase, int period, int frequency, int downsample, int upsample/* IOhannes */, int reblock,
190 int switched)
191{
192#ifdef ROCKBOX
193 t_signal *insig;
194 (void) frequency;
195 (void) switched;
196#else
197 t_signal *insig, *outsig;
198#endif
199 x->x_updown.downsample = downsample;
200 x->x_updown.upsample = upsample;
201
202 /* if the "reblock" flag is set, arrange to copy data in from the
203 parent. */
204 if (reblock)
205 {
206 int parentvecsize, bufsize, oldbufsize, prologphase;
207 int re_parentvecsize; /* resampled parentvectorsize: IOhannes */
208 /* this should never happen: */
209 if (!x->x_buf) return;
210
211 /* the prolog code counts from 0 to period-1; the
212 phase is backed up by one so that AFTER the prolog code
213 runs, the "x_fill" phase is in sync with the "x_read" phase. */
214 prologphase = (phase - 1) & (period - 1);
215 if (parentsigs)
216 {
217 insig = parentsigs[inlet_getsignalindex(x->x_inlet)];
218 parentvecsize = insig->s_n;
219 re_parentvecsize = parentvecsize * upsample / downsample;
220 }
221 else
222 {
223 insig = 0;
224 parentvecsize = 1;
225 re_parentvecsize = 1;
226 }
227
228 bufsize = re_parentvecsize;
229 if (bufsize < myvecsize) bufsize = myvecsize;
230 if (bufsize != (oldbufsize = x->x_bufsize))
231 {
232 t_float *buf = x->x_buf;
233 t_freebytes(buf, oldbufsize * sizeof(*buf));
234 buf = (t_float *)t_getbytes(bufsize * sizeof(*buf));
235 memset((char *)buf, 0, bufsize * sizeof(*buf));
236 x->x_bufsize = bufsize;
237 x->x_endbuf = buf + bufsize;
238 x->x_buf = buf;
239 }
240 if (parentsigs)
241 {
242 /* IOhannes { */
243 x->x_hop = period * re_parentvecsize;
244
245 x->x_fill = x->x_endbuf -
246 (x->x_hop - prologphase * re_parentvecsize);
247
248 if (upsample * downsample == 1)
249 dsp_add(vinlet_doprolog, 3, x, insig->s_vec, re_parentvecsize);
250 else {
251 resamplefrom_dsp(&x->x_updown, insig->s_vec, parentvecsize, re_parentvecsize, x->x_updown.method);
252 dsp_add(vinlet_doprolog, 3, x, x->x_updown.s_vec, re_parentvecsize);
253 }
254
255 /* } IOhannes */
256 /* if the input signal's reference count is zero, we have
257 to free it here because we didn't in ugen_doit(). */
258 if (!insig->s_refcount)
259 signal_makereusable(insig);
260 }
261 else memset((char *)(x->x_buf), 0, bufsize * sizeof(*x->x_buf));
262 x->x_directsignal = 0;
263 }
264 else
265 {
266 /* no reblocking; in this case our output signal is "borrowed"
267 and merely needs to be pointed to the real one. */
268 x->x_directsignal = parentsigs[inlet_getsignalindex(x->x_inlet)];
269 }
270}
271
272//static void *vinlet_newsig(void)
273static void *vinlet_newsig(t_symbol *s)
274{
275 t_vinlet *x = (t_vinlet *)pd_new(vinlet_class);
276 x->x_canvas = canvas_getcurrent();
277 x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, &s_signal);
278 x->x_endbuf = x->x_buf = (t_float *)getbytes(0);
279 x->x_bufsize = 0;
280 x->x_directsignal = 0;
281 outlet_new(&x->x_obj, &s_signal);
282
283 resample_init(&x->x_updown);
284
285 /* this should be though over:
286 * it might prove hard to provide consistency between labeled up- & downsampling methods
287 * maybe indeces would be better...
288 *
289 * up till now we provide several upsampling methods and 1 single downsampling method (no filtering !)
290 */
291 if (s == gensym("hold"))x->x_updown.method=1; /* up: sample and hold */
292 else if (s == gensym("lin"))x->x_updown.method=2; /* up: linear interpolation */
293 else x->x_updown.method=0; /* up: zero-padding */
294
295 return (x);
296}
297
298static void vinlet_setup(void)
299{
300 vinlet_class = class_new(gensym("inlet"), (t_newmethod)vinlet_new,
301 (t_method)vinlet_free, sizeof(t_vinlet), CLASS_NOINLET, A_DEFSYM, 0);
302 class_addcreator((t_newmethod)vinlet_newsig, gensym("inlet~"), A_DEFSYM, 0);
303 class_addbang(vinlet_class, vinlet_bang);
304 class_addpointer(vinlet_class, vinlet_pointer);
305 class_addfloat(vinlet_class, vinlet_float);
306 class_addsymbol(vinlet_class, vinlet_symbol);
307 class_addlist(vinlet_class, vinlet_list);
308 class_addanything(vinlet_class, vinlet_anything);
309 class_addmethod(vinlet_class, (t_method)vinlet_dsp, gensym("dsp"), 0);
310 class_sethelpsymbol(vinlet_class, gensym("pd"));
311}
312
313/* ------------------------- voutlet -------------------------- */
314
315t_class *voutlet_class;
316
317typedef struct _voutlet
318{
319 t_object x_obj;
320 t_canvas *x_canvas;
321 t_outlet *x_parentoutlet;
322 int x_bufsize;
323 t_sample *x_buf; /* signal buffer; zero if not a signal */
324 t_sample *x_endbuf;
325 t_sample *x_empty; /* next to read out of buffer in epilog code */
326 t_sample *x_write; /* next to write in to buffer */
327 int x_hop; /* hopsize */
328 /* vice versa from the inlet, if we don't block, this holds the
329 parent's outlet signal, valid between the prolog and the dsp setup
330 routines. */
331 t_signal *x_directsignal;
332 /* and here's a flag indicating that we aren't blocked but have to
333 do a copy (because we're switched). */
334 char x_justcopyout;
335 t_resample x_updown; /* IOhannes */
336} t_voutlet;
337
338static void *voutlet_new(t_symbol *s)
339{
340#ifdef ROCKBOX
341 (void) s;
342#endif
343 t_voutlet *x = (t_voutlet *)pd_new(voutlet_class);
344 x->x_canvas = canvas_getcurrent();
345 x->x_parentoutlet = canvas_addoutlet(x->x_canvas, &x->x_obj.ob_pd, 0);
346 inlet_new(&x->x_obj, &x->x_obj.ob_pd, 0, 0);
347 x->x_bufsize = 0;
348 x->x_buf = 0;
349 return (x);
350}
351
352static void voutlet_bang(t_voutlet *x)
353{
354 outlet_bang(x->x_parentoutlet);
355}
356
357static void voutlet_pointer(t_voutlet *x, t_gpointer *gp)
358{
359 outlet_pointer(x->x_parentoutlet, gp);
360}
361
362static void voutlet_float(t_voutlet *x, t_float f)
363{
364 outlet_float(x->x_parentoutlet, f);
365}
366
367static void voutlet_symbol(t_voutlet *x, t_symbol *s)
368{
369 outlet_symbol(x->x_parentoutlet, s);
370}
371
372static void voutlet_list(t_voutlet *x, t_symbol *s, int argc, t_atom *argv)
373{
374 outlet_list(x->x_parentoutlet, s, argc, argv);
375}
376
377static void voutlet_anything(t_voutlet *x, t_symbol *s, int argc, t_atom *argv)
378{
379 outlet_anything(x->x_parentoutlet, s, argc, argv);
380}
381
382static void voutlet_free(t_voutlet *x)
383{
384 canvas_rmoutlet(x->x_canvas, x->x_parentoutlet);
385 resample_free(&x->x_updown);
386}
387
388t_outlet *voutlet_getit(t_pd *x)
389{
390 if (pd_class(x) != voutlet_class) bug("voutlet_getit");
391 return (((t_voutlet *)x)->x_parentoutlet);
392}
393
394/* ------------------------- signal outlet -------------------------- */
395
396int voutlet_issignal(t_voutlet *x)
397{
398 return (x->x_buf != 0);
399}
400
401 /* LATER optimize for non-overlapped case where the "+=" isn't needed */
402t_int *voutlet_perform(t_int *w)
403{
404 t_voutlet *x = (t_voutlet *)(w[1]);
405 t_sample *in = (t_sample *)(w[2]);
406 int n = (int)(w[3]);
407 t_sample *out = x->x_write, *outwas = out;
408#if 0
409 if (tot < 5) post("-in %x out %x n %d", in, out, n);
410 if (tot < 5) post("-buf %x endbuf %x", x->x_buf, x->x_endbuf);
411#endif
412 while (n--)
413 {
414 *out++ += *in++;
415 if (out == x->x_endbuf) out = x->x_buf;
416 }
417 outwas += x->x_hop;
418 if (outwas >= x->x_endbuf) outwas = x->x_buf;
419 x->x_write = outwas;
420 return (w+4);
421}
422
423 /* epilog code for blocking: write buffer to parent patch */
424static t_int *voutlet_doepilog(t_int *w)
425{
426 t_voutlet *x = (t_voutlet *)(w[1]);
427 t_sample *out = (t_sample *)(w[2]); /* IOhannes */
428
429 int n = (int)(w[3]);
430 t_sample *in = x->x_empty;
431 if (x->x_updown.downsample != x->x_updown.upsample) out = x->x_updown.s_vec; /* IOhannes */
432
433#if 0
434 if (tot < 5) post("outlet in %x out %x n %x", in, out, n), tot++;
435#endif
436 for (; n--; in++) *out++ = *in, *in = 0;
437 if (in == x->x_endbuf) in = x->x_buf;
438 x->x_empty = in;
439 return (w+4);
440}
441
442/* IOhannes { */
443static t_int *voutlet_doepilog_resampling(t_int *w)
444{
445 t_voutlet *x = (t_voutlet *)(w[1]);
446 // t_float *dummy = (t_float *)(w[2]);
447 int n = (int)(w[2]);
448 t_sample *in = x->x_empty;
449 t_sample *out = x->x_updown.s_vec; /* IOhannes */
450
451#if 0
452 if (tot < 5) post("outlet in %x out %x n %x", in, out, n), tot++;
453#endif
454 for (; n--; in++) *out++ = *in, *in = 0;
455 if (in == x->x_endbuf) in = x->x_buf;
456 x->x_empty = in;
457 return (w+3);
458}
459/* } IOhannes */
460int outlet_getsignalindex(t_outlet *x);
461
462 /* prolog for outlets -- store pointer to the outlet on the
463 parent, which, if "reblock" is false, will want to refer
464 back to whatever we see on our input during the "dsp" method
465 called later. */
466void voutlet_dspprolog(t_voutlet *x, t_signal **parentsigs,
467 int myvecsize, int phase, int period, int frequency, int downsample, int upsample /* IOhannes */, int reblock,
468 int switched)
469{
470#ifdef ROCKBOX
471 (void) myvecsize;
472 (void) phase;
473 (void) period;
474 (void) frequency;
475#endif
476 x->x_updown.downsample=downsample; x->x_updown.upsample=upsample; /* IOhannes */
477 x->x_justcopyout = (switched && !reblock);
478 if (reblock)
479 {
480 x->x_directsignal = 0;
481 }
482 else
483 {
484 if (!parentsigs) bug("voutlet_dspprolog");
485 x->x_directsignal =
486 parentsigs[outlet_getsignalindex(x->x_parentoutlet)];
487 }
488}
489
490static void voutlet_dsp(t_voutlet *x, t_signal **sp)
491{
492 t_signal *insig;
493 if (!x->x_buf) return;
494 insig = sp[0];
495 if (x->x_justcopyout)
496 dsp_add_copy(insig->s_vec, x->x_directsignal->s_vec, insig->s_n);
497 else if (x->x_directsignal)
498 {
499 /* if we're just going to make the signal available on the
500 parent patch, hand it off to the parent signal. */
501 /* this is done elsewhere--> sp[0]->s_refcount++; */
502 signal_setborrowed(x->x_directsignal, sp[0]);
503 }
504 else
505 dsp_add(voutlet_perform, 3, x, insig->s_vec, insig->s_n);
506}
507
508 /* set up epilog DSP code. If we're reblocking, this is the
509 time to copy the samples out to the containing object's outlets.
510 If we aren't reblocking, there's nothing to do here. */
511void voutlet_dspepilog(t_voutlet *x, t_signal **parentsigs,
512 int myvecsize, int phase, int period, int frequency, int downsample, int upsample /* IOhannes */, int reblock,
513 int switched)
514{
515 if (!x->x_buf) return; /* this shouldn't be necesssary... */
516 x->x_updown.downsample=downsample; x->x_updown.upsample=upsample; /* IOhannes */
517 if (reblock)
518 {
519#ifdef ROCKBOX
520 t_signal *outsig;
521#else
522 t_signal *insig, *outsig;
523#endif
524 int parentvecsize, bufsize, oldbufsize;
525 int re_parentvecsize; /* IOhannes */
526 int bigperiod, epilogphase, blockphase;
527 if (parentsigs)
528 {
529 outsig = parentsigs[outlet_getsignalindex(x->x_parentoutlet)];
530 parentvecsize = outsig->s_n;
531 re_parentvecsize = parentvecsize * upsample / downsample;
532 }
533 else
534 {
535 outsig = 0;
536 parentvecsize = 1;
537 re_parentvecsize = 1;
538 }
539 // bigperiod = (downsample * myvecsize)/(upsample * parentvecsize); /* IOhannes */
540 bigperiod = myvecsize/re_parentvecsize; /* IOhannes */
541 if (!bigperiod) bigperiod = 1;
542 epilogphase = phase & (bigperiod - 1);
543 blockphase = (phase + period - 1) & (bigperiod - 1) & (- period);
544 // bufsize = parentvecsize * upsample; /* IOhannes */
545 bufsize = re_parentvecsize; /* IOhannes */
546 if (bufsize < myvecsize) bufsize = myvecsize;
547 if (bufsize != (oldbufsize = x->x_bufsize))
548 {
549 t_sample *buf = x->x_buf;
550 t_freebytes(buf, oldbufsize * sizeof(*buf));
551 buf = (t_sample *)t_getbytes(bufsize * sizeof(*buf));
552 memset((char *)buf, 0, bufsize * sizeof(*buf));
553 x->x_bufsize = bufsize;
554 x->x_endbuf = buf + bufsize;
555 x->x_buf = buf;
556 }
557 /* IOhannes: { */
558 if (re_parentvecsize * period > bufsize) bug("voutlet_dspepilog");
559 x->x_write = x->x_buf + re_parentvecsize * blockphase;
560 if (x->x_write == x->x_endbuf) x->x_write = x->x_buf;
561 if (period == 1 && frequency > 1)
562 x->x_hop = re_parentvecsize / frequency;
563 else x->x_hop = period * re_parentvecsize;
564 /* } IOhannes */
565 /* post("phase %d, block %d, parent %d", phase & 63,
566 parentvecsize * blockphase, parentvecsize * epilogphase); */
567 if (parentsigs)
568 {
569 /* set epilog pointer and schedule it */
570 /* IOhannes { */
571 x->x_empty = x->x_buf + re_parentvecsize * epilogphase;
572 if (upsample * downsample == 1)
573 dsp_add(voutlet_doepilog, 3, x, outsig->s_vec, re_parentvecsize);
574 else {
575 dsp_add(voutlet_doepilog_resampling, 2, x, re_parentvecsize);
576 resampleto_dsp(&x->x_updown, outsig->s_vec, re_parentvecsize, parentvecsize, x->x_updown.method);
577 }
578 /* } IOhannes */
579 }
580 }
581 /* if we aren't blocked but we are switched, the epilog code just
582 copies zeros to the output. In this case the blocking code actually
583 jumps over the epilog if the block is running. */
584 else if (switched)
585 {
586 if (parentsigs)
587 {
588 t_signal *outsig =
589 parentsigs[outlet_getsignalindex(x->x_parentoutlet)];
590 dsp_add_zero(outsig->s_vec, outsig->s_n);
591 }
592 }
593}
594
595static void *voutlet_newsig(t_symbol *s)
596{
597 t_voutlet *x = (t_voutlet *)pd_new(voutlet_class);
598 x->x_canvas = canvas_getcurrent();
599 x->x_parentoutlet = canvas_addoutlet(x->x_canvas,
600 &x->x_obj.ob_pd, &s_signal);
601 inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
602 x->x_endbuf = x->x_buf = (t_sample *)getbytes(0);
603 x->x_bufsize = 0;
604
605 resample_init(&x->x_updown);
606
607 /* this should be though over:
608 * it might prove hard to provide consistency between labeled up- & downsampling methods
609 * maybe indeces would be better...
610 *
611 * up till now we provide several upsampling methods and 1 single downsampling method (no filtering !)
612 */
613 if (s == gensym("hold"))x->x_updown.method=1; /* up: sample and hold */
614 else if (s == gensym("lin"))x->x_updown.method=2; /* up: linear interpolation */
615 else if (s == gensym("linear"))x->x_updown.method=2; /* up: linear interpolation */
616 else x->x_updown.method=0; /* up: zero-padding; down: ignore samples inbetween */
617
618 return (x);
619}
620
621
622static void voutlet_setup(void)
623{
624 voutlet_class = class_new(gensym("outlet"), (t_newmethod)voutlet_new,
625 (t_method)voutlet_free, sizeof(t_voutlet), CLASS_NOINLET, A_DEFSYM, 0);
626 class_addcreator((t_newmethod)voutlet_newsig, gensym("outlet~"), A_DEFSYM, 0);
627 class_addbang(voutlet_class, voutlet_bang);
628 class_addpointer(voutlet_class, voutlet_pointer);
629 class_addfloat(voutlet_class, (t_method)voutlet_float);
630 class_addsymbol(voutlet_class, voutlet_symbol);
631 class_addlist(voutlet_class, voutlet_list);
632 class_addanything(voutlet_class, voutlet_anything);
633 class_addmethod(voutlet_class, (t_method)voutlet_dsp, gensym("dsp"), 0);
634 class_sethelpsymbol(voutlet_class, gensym("pd"));
635}
636
637
638/* ---------------------------- overall setup ----------------------------- */
639
640void g_io_setup(void)
641{
642 vinlet_setup();
643 voutlet_setup();
644}
645