diff options
Diffstat (limited to 'system/pdbase')
-rw-r--r-- | system/pdbase/Makefile | 11 | ||||
-rw-r--r-- | system/pdbase/pdp_base.c | 415 | ||||
-rw-r--r-- | system/pdbase/pdp_dpd_base.c | 270 | ||||
-rw-r--r-- | system/pdbase/pdp_imagebase.c | 79 |
4 files changed, 775 insertions, 0 deletions
diff --git a/system/pdbase/Makefile b/system/pdbase/Makefile new file mode 100644 index 0000000..58efa41 --- /dev/null +++ b/system/pdbase/Makefile @@ -0,0 +1,11 @@ + +OBJECTS = pdp_base.o pdp_imagebase.o pdp_dpd_base.o + + +include ../../Makefile.config + +all: $(OBJECTS) + +clean: + rm -f *~ + rm -f *.o diff --git a/system/pdbase/pdp_base.c b/system/pdbase/pdp_base.c new file mode 100644 index 0000000..4d5593f --- /dev/null +++ b/system/pdbase/pdp_base.c @@ -0,0 +1,415 @@ +/* + * Pure Data Packet base class implementation. + * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> + * + * 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 <stdarg.h> + + +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; i<b->b_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; i<b->b_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 (pdp_sym_rro() == s){ + 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 (pdp_sym_rrw() == s) { + 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 ((pdp_sym_prc() == s) && (-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 != pdp_sym_rro()) 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; i<MAX_NB_PDP_BASE_INLETS; i++){ + if (s == gensym(msg)){ + inlet = i; + goto found; + } + else{ + msg[3]++; + } + } + return; + + + found: + + /* store the packet and trow away + the old one, if there is any */ + + pdp_packet_copy_ro_or_drop(&b->b_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; i<MAX_NB_PDP_BASE_INLETS; i++){ + b->b_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; i<MAX_NB_PDP_BASE_INLETS; i++){ + pdp_packet_mark_unused(b->b_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; + } +} diff --git a/system/pdbase/pdp_dpd_base.c b/system/pdbase/pdp_dpd_base.c new file mode 100644 index 0000000..162368d --- /dev/null +++ b/system/pdbase/pdp_dpd_base.c @@ -0,0 +1,270 @@ +/* + * Pure Data Packet module. DPD base class implementation. + * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> + * + * 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. + * + */ + + +#include "pdp_dpd_base.h" +#include "pdp_internals.h" + + +#define THIS(b) t_pdp_dpd_base *b = (t_pdp_dpd_base *)x + + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +/* PRIVATE METHODS */ + + + + +/* dpd packet context input handler */ +static void _pdp_dpd_base_context_input(t_pdp_dpd_base *b, t_symbol *s, t_floatarg f) +{ + + int p = (int)f; + int i; + + //post ("pdp_dpd_base_context_input: got %s %d", s->s_name, p); + + /* sources/sinks have active inlet disabled */ + if (b->b_dpd_active_inlet_disabled) return; + + /* handle inspect message */ + if (pdp_sym_ins() == s){ + + /* store packet for inspector */ + b->b_context_packet = p; + + /* add inspector to pdp queue + this is special: it doesn't use a command object */ + pdp_dpd_base_queue_command(b, b, b->b_inspector_method, b->b_inspector_callback, 0); + } + + /* handle accumulate message */ + if (pdp_sym_acc() == s){ + + /* store context for accumulator methods */ + b->b_context_packet = p; + + /* call bang */ + pdp_dpd_base_bang(b); + + + } + +} + +/* default command object (returns self) */ +void *_pdp_dpd_base_get_command_object(void *x){return x;} + +/* PUBLIC METHODS */ + + +void pdp_dpd_base_queue_command(void *x, void *c, t_pdp_method process, + t_pdp_method callback, int *id) +{ + THIS(b); + t_pdp_procqueue *q = pdp_base_get_queue(x); + pdp_procqueue_add(q, c, process, callback, id); + +} + +/* bang method (propagate context to outlet) : it is not registered as a pd message by default ! */ +void pdp_dpd_base_bang(void *x) +{ + THIS(b); + int i, id; + void *cobj; + + /* move passive pdp packets in place */ + pdp_base_movepassive(x); + + /* get command object (or use self) */ + cobj = b->b_command_factory_method ? (b->b_command_factory_method)(b) : b; + //post(" command object is %x. object is %x", cobj, b); + + + /* queue acc method & propagate for all outlets */ + for (i=b->b_nb_context_outlets; i--;){ + + + /* propagate the context packet to the outlet */ + if (b->b_outlet_enable[i]){ + pdp_dpd_base_queue_command(x, cobj, b->b_accum_method[i], b->b_accum_callback[i], 0); + outlet_dpd(b->b_context_outlet[i], b->b_context_packet); + } + else{ + //post("outlet %d disabled", i); + } + } + + /* queue cleanup method */ + if (b->b_cleanup_method) + //pdp_procqueue_add(b->b_q, b, b->b_cleanup_method, 0, &b->b_cleanup_queue_id); + pdp_dpd_base_queue_command(x, cobj, b->b_cleanup_method, b->b_cleanup_callback, 0); + + /* send communication complete notify */ + if (b->b_complete_notify) + (b->b_complete_notify)(x); + +} + +/* get/set context packet */ +int pdp_dpd_base_get_context_packet(void *x){ + THIS(b); + return b->b_context_packet; +} +int pdp_dpd_base_move_context_packet(void *x){ + THIS(b); + int p = b->b_context_packet; + b->b_context_packet = -1; + return p; +} + +void pdp_dpd_base_set_context_packet(void *x, int p){ + THIS(b); + pdp_packet_mark_unused(b->b_context_packet); + b->b_context_packet = p; +} + +/* add a cleanup callback (called after all propagation is finished) for sources/sinks */ +void pdp_dpd_base_add_cleanup(void *x, t_pdp_method cleanup_method, t_pdp_method cleanup_callback) +{ + THIS(b); + b->b_cleanup_method = cleanup_method; + b->b_cleanup_callback = cleanup_callback; + //b->b_cleanup_queue_id = -1; +} + +/* add a inspector callback */ +void pdp_dpd_base_add_inspector(void *x, t_pdp_method inspector_method) +{ + THIS(b); + b->b_inspector_method = inspector_method; + //b->b_inspector_queue_id = -1; +} + +/* add a context outlet */ +t_outlet *pdp_dpd_base_add_outlet(void *x, t_pdp_method accum_method, t_pdp_method accum_callback) +{ + THIS(b); + int i = b->b_nb_context_outlets; + if (i < PDP_DPD_MAX_CONTEXT_OUTLETS){ + b->b_context_outlet[i] = outlet_new((t_object *)b, &s_anything); + b->b_outlet_enable[i] = 1; + b->b_accum_method[i] = accum_method; + b->b_accum_callback[i] = accum_callback; + //b->b_accum_queue_id[i] = -1; + b->b_nb_context_outlets++; + return b->b_context_outlet[i]; + } + else{ + post("pdp_dpd_base_add_outlet: no more free outlet slots"); + return 0; + } + +} + + +/* destructor */ +void pdp_dpd_base_free(void *x) +{ + THIS(b); + + /* free base */ + pdp_base_free(b); +} + + +void pdp_dpd_base_disable_active_inlet(void *x) +{ + THIS(b); + b->b_dpd_active_inlet_disabled = 1; +} + + + +void pdp_dpd_base_enable_outlet(void *x, int outlet, int toggle) +{ + THIS(b); + if (outlet >=0 && outlet < PDP_DPD_MAX_CONTEXT_OUTLETS){ + b->b_outlet_enable[outlet] = toggle; + } + +} + + +void pdp_dpd_base_register_complete_notify(void *x, t_pdp_method method) +{ + THIS(b); + b->b_complete_notify = method; +} + +void pdp_dpd_base_register_command_factory_method(void *x, t_pdp_newmethod command_factory_method) +{ + THIS(b); + b->b_command_factory_method = command_factory_method; +} + + +/* init method */ +void pdp_dpd_base_init(void *x) +{ + THIS(b); + + /* super init */ + pdp_base_init(b); + + /* disable pdp messages on active inlet (dpd messages are used as sync) */ + pdp_base_disable_active_inlet(b); + + /* init data */ + b->b_nb_context_outlets = 0; + b->b_context_packet = -1; + b->b_cleanup_method = 0; + //b->b_cleanup_queue_id = -1; + b->b_inspector_method = 0; + //b->b_inspector_queue_id = -1; + b->b_dpd_active_inlet_disabled = 0; + + // default notify == none + b->b_complete_notify = 0; + + // default command object getter + b->b_command_factory_method = 0; + +} + + +void pdp_dpd_base_setup(t_class *class) +{ + + pdp_base_setup(class); + class_addmethod(class, (t_method)_pdp_dpd_base_context_input, gensym("dpd"), A_SYMBOL, A_FLOAT, A_NULL); + +} + +#ifdef __cplusplus +} +#endif diff --git a/system/pdbase/pdp_imagebase.c b/system/pdbase/pdp_imagebase.c new file mode 100644 index 0000000..f9634e1 --- /dev/null +++ b/system/pdbase/pdp_imagebase.c @@ -0,0 +1,79 @@ +/* + * Pure Data Packet image processor base class implementation. + * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> + * + * 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 image base class object. +*/ + +#include "pdp_imagebase.h" +#include <stdarg.h> + + +static void pdp_imagebase_chanmask(t_pdp_base *b, t_floatarg f) +{ + int i = (int)f; + if (i < 0) i = -1; + b->b_channel_mask = i; +} + +void pdp_imagebase_setup(t_class *c) +{ + /* parent class setup */ + pdp_base_setup(c); + + /* add pdp base class methods */ + class_addmethod(c, (t_method)pdp_imagebase_chanmask, gensym("chanmask"), A_FLOAT, A_NULL); + +} + +/* pdp base instance constructor */ +void pdp_imagebase_init(void *x) +{ + int i; + t_pdp_imagebase *b = (t_pdp_imagebase *)x; + + /* init super */ + pdp_base_init(x); + + /* convert all active incoming packet types to image */ + pdp_base_set_type_template(x, 0, pdp_gensym("image/*/*")); + + /* default chanmask == all */ + b->b_channel_mask = -1; + +} + +/* base instance destructor */ +void pdp_imagebase_free(void *x) +{ + /* free super */ + pdp_base_free(x); + +} + +/* chanmask getter */ +u32 pdp_imagebase_get_chanmask(void *x) +{ + t_pdp_base *b = (t_pdp_base *)x; + return b->b_channel_mask; +} + |