From d62e56f4df9594f72ce501f5e19c974fd18e7295 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Tue, 22 Oct 2002 23:07:10 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r186, which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=187 --- externals/grill/flext/source/flbuf.cpp | 255 +++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 externals/grill/flext/source/flbuf.cpp (limited to 'externals/grill/flext/source/flbuf.cpp') diff --git a/externals/grill/flext/source/flbuf.cpp b/externals/grill/flext/source/flbuf.cpp new file mode 100644 index 00000000..dc5704c0 --- /dev/null +++ b/externals/grill/flext/source/flbuf.cpp @@ -0,0 +1,255 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flbuf.cpp + \brief Implementation of the buffer abstraction class. +*/ + +#include "flext.h" + +#ifdef MAXMSP +#include "flmspbuffer.h" // include inofficial buffer.h +#endif + +#ifdef PD +#define DIRTY_INTERVAL 0 // buffer dirty check in msec +#endif + + + +flext::buffer::buffer(const t_symbol *bn,bool delayed): + sym(NULL),data(NULL), + chns(0),frames(0) +{ +#ifdef PD + arr = NULL; + interval = DIRTY_INTERVAL; + isdirty = false; + ticking = false; + tick = clock_new(this,(t_method)cb_tick); +#endif + + if(bn) Set(bn,delayed); +} + +flext::buffer::~buffer() +{ +#ifdef PD + clock_free(tick); +#endif +} + +int flext::buffer::Set(const t_symbol *s,bool nameonly) +{ + int ret = 0; + bool valid = data != NULL; // valid now? (before change) + + if(s && sym != s) { + ret = -1; + data = NULL; + frames = 0; + chns = 0; + } + + if(s && *s->s_name) sym = s; + + if(!sym) { + if(valid) ret = -1; + } + else if(!nameonly) { +#ifdef PD + int frames1; + t_sample *data1; + + arr = (t_garray *)pd_findbyclass(const_cast(sym), garray_class); + if(!arr) + { + if (*sym->s_name) error("buffer: no such array '%s'",sym->s_name); + sym = NULL; + if(valid) ret = -1; + } + else if(!garray_getfloatarray(arr, &frames1, &data1)) + { + error("buffer: bad template '%s'", sym->s_name); + data = NULL; + frames = 0; + if(valid) ret = -1; + } + else { + garray_usedindsp(arr); + if(frames != frames1) { frames = frames1; if(!ret) ret = 1; } + if(data != data1) { data = data1; if(!ret) ret = 1; } + chns = 1; + } +#elif defined(MAXMSP) + if(sym->s_thing) { + const _buffer *p = (const _buffer *)sym->s_thing; + + if(NOGOOD(p)) { + post("buffer: buffer object '%s' no good",sym->s_name); + if(valid) ret = -1; + } + else { +#ifdef DEBUG + post("%s: buffer object '%s' - valid:%i samples:%i channels:%i frames:%i",thisName(),bufname->s_name,p->b_valid,p->b_frames,p->b_nchans,p->b_frames); +#endif + if(data != p->b_samples) { data = p->b_samples; if(!ret) ret = 1; } + if(chns != p->b_nchans) { chns = p->b_nchans; if(!ret) ret = 1; } + if(frames != p->b_frames) { frames = p->b_frames; if(!ret) ret = 1; } + } + } + else { + error("buffer: symbol '%s' not defined", sym->s_name); + if(valid) ret = -1; + } +#endif + } + + return ret; +} + +bool flext::buffer::Update() +{ + if(!Ok()) return false; + +#ifdef PD + int frames1; + t_sample *data1; + if(!garray_getfloatarray(arr, &frames1, &data1)) { + frames = 0; + data = NULL; + chns = 0; + return true; + } + else if(data != data1 || frames != frames1) { + frames = frames1; + data = data1; + return true; + } + else + return false; +#else // MAXMSP + if(!sym->s_thing) + return false; + else { + const _buffer *p = (const _buffer *)sym->s_thing; + if(data != p->b_samples || chns != p->b_nchans || frames != p->b_frames) { + data = p->b_samples; + chns = p->b_nchans; + frames = p->b_frames; + return true; + } + else + return false; + } +#endif +} + +void flext::buffer::Frames(int fr,bool keep) +{ +#ifdef PD + ::garray_resize(arr,(float)fr); + Update(); +#else + t_sample *tmp = NULL; + int sz = frames; + if(fr < sz) sz = fr; + + if(keep) { + // copy buffer data to tmp storage + tmp = new t_sample[sz]; + if(tmp) + BlockMoveData(data,tmp,sizeof(t_sample)*sz); + else + error("flext::buffer - not enough memory for keeping buffer~ contents"); + } + + t_atom msg; + _buffer *buf = (_buffer *)sym->s_thing; + // b_msr reflects buffer sample rate... is this what we want? + // Max bug: adding small value 0.001 to get right sample count + float ms = fr/buf->b_msr+0.001; + + SetFloat(msg,ms); + ::typedmess((object *)buf,gensym("size"),1,&msg); + + Update(); + + if(tmp) { + // copy data back + BlockMoveData(tmp,data,sizeof(t_sample)*sz); + delete[] tmp; + } +#endif +} + + +#ifdef PD +void flext::buffer::SetRefrIntv(float intv) +{ + interval = intv; + if(interval == 0 && ticking) { + clock_unset(tick); + ticking = false; + } +} +#else +void flext::buffer::SetRefrIntv(float) {} +#endif + + +void flext::buffer::Dirty(bool force) +{ + if(sym) { +#ifdef PD + if((!ticking) && (interval || force)) { + ticking = true; + cb_tick(this); // immediately redraw + } + else { + if(force) clock_delay(tick,0); + isdirty = true; + } +#elif defined(MAXMSP) + if(sym->s_thing) { + _buffer *p = (_buffer *)sym->s_thing; + + if(NOGOOD(p)) { + post("buffer: buffer object '%s' no good",sym->s_name); + } + else { + p->b_modtime = gettime(); + } + } + else { + error("buffer: symbol '%s' not defined",sym->s_name); + } +#endif + } +} + +#ifdef PD +void flext::buffer::cb_tick(buffer *b) +{ + if(b->arr) garray_redraw(b->arr); +#ifdef _DEBUG + else error("buffer: array is NULL"); +#endif + + if(b->isdirty && b->interval) { + b->isdirty = false; + b->ticking = true; + clock_delay(b->tick,b->interval); + } + else + b->ticking = false; +} +#endif + -- cgit v1.2.1