#include "noatunarts.h" #include #include #include #include using namespace std; using namespace Arts; namespace Noatun { class StereoEffectStack_impl : public StereoEffectStack_skel, public StdSynthModule { public: long nextID; struct EffectEntry { StereoEffect effect; string name; long id; }; list fx; void xconnect(bool connect, Object from, string fromP, Object to, string toP) { if(connect) from._node()->connect(fromP,to._node(),toP); else from._node()->disconnect(fromP,to._node(),toP); } void xvirtualize(bool connect, string myPort, Object impl, string implPort) { if(connect) _node()->virtualize(myPort,impl._node(),implPort); else _node()->devirtualize(myPort,impl._node(),implPort); } void internalconnect(bool c) { if(fx.empty()) { /* no effects - forward input through to output */ xvirtualize(c,"outleft",Object::_from_base(this->_copy()),"inleft"); xvirtualize(c,"outright",Object::_from_base(this->_copy()),"inright"); } else { list::iterator ei; EffectEntry *laste = 0; long count = 0; for(ei = fx.begin(); ei != fx.end(); ei++, count++) { EffectEntry *e = *ei; if(count == 0) /* top of chain? virtualize to effect */ { xvirtualize(c,"inleft",e->effect,"inleft"); xvirtualize(c,"inright",e->effect,"inright"); } else /* not top? connect last effect to current effect */ { xconnect(c,laste->effect,"outleft",e->effect,"inleft"); xconnect(c,laste->effect,"outright",e->effect,"inright"); } laste = e; } /* end: virtualize effect output to our output */ xvirtualize(c,"outleft",laste->effect,"outleft"); xvirtualize(c,"outright",laste->effect,"outright"); } } void disconnect() { internalconnect(false); } void reconnect() { internalconnect(true); } long insertAfter(long after, StereoEffect effect, const string &name) { arts_return_val_if_fail(!effect.isNull(),0); disconnect(); list::iterator i = fx.begin(); bool found=false; // seek through until we find 'after' while(i != fx.end()) if((*i)->id == after) { found = true; break; } else i++; long newId=0; if (found) { i++; EffectEntry *e = new EffectEntry; e->effect=effect; e->name=name; e->id=nextID++; fx.insert(i, e); newId=e->id; } else arts_warning("StereoEffectStack::insertAfter failed. " "id %d not found?", after); reconnect(); return newId; } void move(long after, long item) { arts_return_if_fail(item != 0); disconnect(); list::iterator iAfter=fx.begin(); bool found=false; if (after) while(iAfter != fx.end()) if((*iAfter)->id == after) { found = true; iAfter++; break; } else iAfter++; else found=true; list::iterator iItem=fx.begin(); while (iItem != fx.end()) if((*iItem)->id == item) { found &= true; break; } else iItem++; if (!found) arts_warning("StereoEffectStack::move couldn't find items"); else { fx.insert(iAfter, *iItem); fx.erase(iItem); } reconnect(); } vector *effectList() { vector *items=new vector; for (list::iterator i=fx.begin(); i!=fx.end();i++) items->push_back((*i)->id); return items; } // as stolen from stereoeffectstack_impl.cc StereoEffectStack_impl() : nextID(1) { reconnect(); } ~StereoEffectStack_impl() { // disconnect remaining effects EffectEntry *laste = 0; list::iterator ei; for(ei = fx.begin(); ei != fx.end(); ei++) { EffectEntry *e = *ei; if(laste) { xconnect(false,laste->effect,"outleft",e->effect,"inleft"); xconnect(false,laste->effect,"outright",e->effect,"inright"); } laste = e; } // delete remaining effect entries for(ei = fx.begin(); ei != fx.end(); ei++) delete *ei; fx.clear(); } long insertTop(StereoEffect effect, const string& name) { arts_return_val_if_fail(!effect.isNull(),0); disconnect(); EffectEntry *e = new EffectEntry(); e->effect = effect; e->name = name; e->id = nextID++; fx.push_front(e); reconnect(); return e->id; } long insertBottom(StereoEffect effect, const string& name) { arts_return_val_if_fail(!effect.isNull(),0); disconnect(); EffectEntry *e = new EffectEntry(); e->effect = effect; e->name = name; e->id = nextID++; fx.push_back(e); reconnect(); return e->id; } void remove(long ID) { arts_return_if_fail(ID != 0); bool found = false; disconnect(); list::iterator ei = fx.begin(); while(ei != fx.end()) { if((*ei)->id == ID) { found = true; delete (*ei); fx.erase(ei); ei = fx.begin(); } else ei++; } if(!found) { arts_warning("StereoEffectStack::remove failed. id %d not found?", ID); } reconnect(); } AutoSuspendState autoSuspend() { return asSuspend; } }; REGISTER_IMPLEMENTATION(StereoEffectStack_impl); }