From c50ce0e0217ea07e2d450add2ab29cecea66fa96 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 28 Nov 2005 01:07:25 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r4059, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/pdp/; revision=4060 --- puredata/pdp_base.c | 415 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 415 insertions(+) create mode 100644 puredata/pdp_base.c (limited to 'puredata/pdp_base.c') diff --git a/puredata/pdp_base.c b/puredata/pdp_base.c new file mode 100644 index 0000000..194134e --- /dev/null +++ b/puredata/pdp_base.c @@ -0,0 +1,415 @@ +/* + * Pure Data Packet base class implementation. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +/* + + This file contains the pdp base class object. + This is really nothing more than an attempt to stay away from c++ + as far as possible, while having some kind of base class functionality + for pdp (tucking away the communication & thread protocol). + +*/ + +#include "pdp_base.h" +#include + + +static void pdp_base_debug(t_pdp_base *b, t_floatarg f) +{ + int i; + post("debug"); + post("inlets: %d", b->b_inlets); + post("\tpacket\tnext_packet"); + for (i=0; ib_inlets; i++) + post("\t%d\t%d", b->b_packet[i], b->b_packet_next[i]); + //post("outlets: %d", b->b_inlets); +} + +static void pdp_base_thread(t_pdp_base *b, t_floatarg f) +{ + int i = (int)f; + if ((i == 0) || (i == 1)) b->b_thread_enabled = i; +} + +static void pdp_base_process(t_pdp_base *b) +{ + + if (b->b_process_method) + (*b->b_process_method)(b); +} + +/* this method is called after the thread has finished processing */ +static void pdp_base_postprocess(t_pdp_base *b) +{ + /* call the derived class postproc callback if there is any */ + if (b->b_postproc_method) + (*b->b_postproc_method)(b); + + /* unregister (mark unused) packet and propagate if packet is valid */ + if (b->b_outlet[0]) + pdp_pass_if_valid(b->b_outlet[0], &b->b_packet[0]); +} + + +/* move the passive packets in place */ +void pdp_base_movepassive(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + int i; + + /* if a cold packet was received in the meantime + swap it in, else keep the old one */ + for (i=1; ib_inlets; i++){ + pdp_replace_if_valid(&b->b_packet[i], &b->b_packet_next[i]); + } + + +} + +/* the standard bang method */ +void pdp_base_bang(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + int i; + + /* if pdp thread is still processing, do nothing */ + if (-1 != b->b_queue_id) return; + + /* move packets in place */ + pdp_base_movepassive(x); + + + /* if there is a preproc method defined, call it inside + the pd thread. (mainly for allocations) */ + if (b->b_preproc_method) + (*b->b_preproc_method)(b); + + /* check if we need to use pdp queue */ + if (b->b_thread_enabled){ + + /* add the process method and callback to the process queue */ + pdp_procqueue_add(b->b_q, b, pdp_base_process, pdp_base_postprocess, &b->b_queue_id); + } + else{ + /* call both methods directly */ + pdp_base_process(b); + pdp_base_postprocess(b); + } +} + +/* hot packet input handler */ +void pdp_base_input_hot(t_pdp_base *b, t_symbol *s, t_floatarg f) +{ + + int p = (int)f; + + /* dont register if active inlet is disabled */ + if (!b->b_active_inlet_enabled) return; + + /* register the packet (readonly or read/write) + or drop it if we have an active packet + if type template is not null, packet will be converted */ + + + if (b->b_active_inlet_readonly){ + if (s == S_REGISTER_RO){ + if (b->b_type_template[0]){ + pdp_packet_convert_ro_or_drop(&b->b_packet[0], p, b->b_type_template[0]); + } + else{ + pdp_packet_copy_ro_or_drop(&b->b_packet[0], p); + } + } + } + else{ + if (s == S_REGISTER_RW) { + if (b->b_type_template[0]){ + pdp_packet_convert_rw_or_drop(&b->b_packet[0], p, b->b_type_template[0]); + } + else{ + pdp_packet_copy_rw_or_drop(&b->b_packet[0], p); + } + } + } + + /* start processing if there is an active packet to process + and the processing method is not active */ + + if ((s == S_PROCESS) && (-1 != b->b_packet[0]) && (-1 == b->b_queue_id)){ + pdp_base_bang(b); + } + //if ((pdp_sym_prc() == s) && (-1 != b->b_packet[0]) && (!b->b_dropped)) pdp_base_bang(b); + +} + +/* cold packet input handlers */ +void pdp_base_input_cold(t_pdp_base *b, t_symbol *s, int ac, t_atom *av) +{ + + int p; + int i; + char msg[] = "pdp1"; + char *c; + + int inlet; + + //post("pdp_base_input_cold: got packet"); + + /* do cheap tests first */ + if (ac != 2) return; + if (av[0].a_type != A_SYMBOL) return; + if (av[0].a_w.w_symbol != S_REGISTER_RO) return; + if (av[1].a_type != A_FLOAT) return; + p = (int)av[1].a_w.w_float; + + + /* check if it's a pdp message + and determine inlet */ + for (i=1; ib_packet_next[inlet], p); +} + + +void pdp_base_set_process_method(void *x, t_pdp_method m) +{ + t_pdp_base *b = (t_pdp_base *)x; + b->b_process_method = m; +} + +void pdp_base_set_preproc_method(void *x, t_pdp_method m) +{ + t_pdp_base *b = (t_pdp_base *)x; + b->b_preproc_method = m; +} + + +void pdp_base_set_postproc_method(void *x, t_pdp_method m) +{ + t_pdp_base *b = (t_pdp_base *)x; + b->b_postproc_method = m; +} + + +void pdp_base_queue_wait(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + pdp_procqueue_wait(b->b_q); +} + +void pdp_base_set_queue(void *x, t_pdp_procqueue *q) +{ + t_pdp_base *b = (t_pdp_base *)x; + pdp_base_queue_wait(x); + b->b_q = q; +} + +t_pdp_procqueue *pdp_base_get_queue(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + return b->b_q; +} + +void pdp_base_setup(t_class *c) +{ + + /* add pdp base class methods */ + class_addmethod(c, (t_method)pdp_base_thread, gensym("thread"), A_FLOAT, A_NULL); + class_addmethod(c, (t_method)pdp_base_debug, gensym("debug"), A_NULL); + + /* hot packet handler */ + class_addmethod(c, (t_method)pdp_base_input_hot, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); + + /* cold packet handler */ + class_addanything(c, (t_method)pdp_base_input_cold); +} + +/* pdp base instance constructor */ +void pdp_base_init(void *x) +{ + int i; + t_pdp_base *b = (t_pdp_base *)x; + + b->b_channel_mask = -1; + + for(i=0; ib_packet[i] = -1; + b->b_packet_next[i] = -1; + b->b_type_template[i] = 0; + } + + b->b_queue_id = -1; + //b->b_dropped = 0; + b->b_process_method = 0; + b->b_preproc_method = 0; + b->b_inlets = 1; + b->b_outlets = 0; + b->b_active_inlet_enabled = 1; + b->b_active_inlet_readonly = 0; + b->b_thread_enabled = 1; + + // default queue is pdp queue + b->b_q = pdp_queue_get_queue(); + +} + +/* base instance destructor */ +void pdp_base_free(void *x) +{ + int i; + t_pdp_base *b = (t_pdp_base *)x; + /* remove process method from queue before deleting data */ + pdp_procqueue_finish(b->b_q, b->b_queue_id); + + /* delete stuff */ + for(i=0; ib_packet[i]); + pdp_packet_mark_unused(b->b_packet_next[i]); + } + +} + +void pdp_base_readonly_active_inlet(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + b->b_active_inlet_readonly = 1; +} + +void pdp_base_disable_active_inlet(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + b->b_active_inlet_enabled = 0; +} + + +/* add an inlet */ +void pdp_base_add_pdp_inlet(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + char s[] = "pdp0"; + s[3] += b->b_inlets; + + if (b->b_inlets < MAX_NB_PDP_BASE_INLETS){ + inlet_new(&b->x_obj, &b->x_obj.ob_pd, gensym("pdp"), gensym(s)); + b->b_inlets++; + } + else { + post("pdp_base_add_pdp_inlet: only %d pdp inlets allowed. ignoring.", MAX_NB_PDP_BASE_INLETS); + } +} + + +/* add an outlet: only one allowed */ +t_outlet *pdp_base_add_pdp_outlet(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + t_outlet *outlet = outlet_new(&b->x_obj, &s_anything); + + + if (b->b_outlets < MAX_NB_PDP_BASE_OUTLETS){ + b->b_outlet[b->b_outlets] = outlet; + b->b_outlets++; + } + + return outlet; + +} + +void pdp_base_set_packet(void *x, int inlet, int packet) +{ + t_pdp_base *b = (t_pdp_base *)x; + + if (inlet < b->b_inlets){ + //post("%d %d", b->b_packet[inlet], b->b_packet_next[inlet]); + pdp_packet_mark_unused(b->b_packet[inlet]); + b->b_packet[inlet] = packet; + } +} + + +int pdp_base_get_packet(void *x, int inlet) +{ + t_pdp_base *b = (t_pdp_base *)x; + + if (inlet < b->b_inlets){ + //post("%d %d", b->b_packet[inlet], b->b_packet_next[inlet]); + return (b->b_packet[inlet]); + } + + return -1; +} + +int pdp_base_move_packet(void *x, int inlet) +{ + t_pdp_base *b = (t_pdp_base *)x; + int p; + + if (inlet < b->b_inlets){ + p = b->b_packet[inlet]; + b->b_packet[inlet] = -1; + return (p); + } + + return -1; +} + + + +t_object *pdp_base_get_object(void *x) +{ + return (t_object *)x; +} + +void pdp_base_add_gen_inlet(void *x, t_symbol *from, t_symbol *to) +{ + t_object *o = (t_object *)x; + inlet_new(o, &o->ob_pd, from, to); +} + +void pdp_base_disable_thread(void *x) +{ + + t_pdp_base *b = (t_pdp_base *)x; + b->b_thread_enabled = 0; +} + +void pdp_base_set_type_template(void *x, int inlet, t_pdp_symbol *type_template) +{ + t_pdp_base *b = (t_pdp_base *)x; + if (inlet < b->b_inlets){ + b->b_type_template[inlet] = type_template; + } +} -- cgit v1.2.1