void CtrlList::swap(CtrlList& cl) { #ifdef _CTRL_DEBUG_ printf("CtrlList::swap id:%d\n", cl.id()); #endif std::map<int, CtrlVal, std::less<int> >::swap(cl); cl.setGuiUpdatePending(true); _guiUpdatePending = true; }
void AudioTrack::clearControllerEvents(int id) { ciCtrlList icl = _controller.find(id); if (icl == _controller.end()) return; CtrlList* cl = icl->second; cl->clear(); return; }
void AudioTrack::addPlugin(BasePlugin* plugin, int idx)/*{{{*/ { if(debugMsg) qDebug("AudioTrack::addPlugin(%p, %d) \n", plugin, idx); if (!plugin) { BasePlugin* oldPlugin = (*_efxPipe)[idx]; if (oldPlugin) { oldPlugin->setId(-1); oldPlugin->setTrack(0); uint32_t paramCount = oldPlugin->getParameterCount(); for (uint32_t i = 0; i < paramCount; i++) { ParameterPort* paramPort = oldPlugin->getParameterPort(i); if (! paramPort || paramPort->type != PARAMETER_INPUT || (paramPort->hints & PARAMETER_IS_AUTOMABLE) == 0) continue; int id = genACnum(idx, i); removeController(id); } _efxPipe->remove(idx); } } if (plugin) { idx = efxPipe()->addPlugin(plugin, idx); plugin->setId(idx); plugin->setTrack(this); uint32_t paramCount = plugin->getParameterCount(); for (uint32_t i = 0; i < paramCount; i++) { ParameterPort* paramPort = plugin->getParameterPort(i); if (! paramPort || paramPort->type != PARAMETER_INPUT || (paramPort->hints & PARAMETER_IS_AUTOMABLE) == 0) continue; int id = genACnum(idx, i); CtrlValueType t = plugin->valueType(); CtrlList* cl = new CtrlList(id); cl->setRange(paramPort->ranges.min, paramPort->ranges.max); cl->setName(plugin->getParameterName(i)); cl->setPluginName(plugin->name()); cl->setUnit(plugin->getParameterUnit(i)); cl->setValueType(t); if (paramPort->hints & PARAMETER_IS_TOGGLED) cl->setMode(CtrlList::DISCRETE); else cl->setMode(CtrlList::INTERPOLATE); cl->setCurVal(plugin->getParameterValue(i)); addController(cl); } } }/*}}}*/
void AudioTrack::addACEvent(int id, int frame, double val) { ciCtrlList icl = _controller.find(id); if (icl == _controller.end()) return; CtrlList* cl = icl->second; // Add will replace if found. cl->add(frame, val); return; }
void AudioTrack::eraseRangeACEvents(int id, int frame1, int frame2) { ciCtrlList icl = _controller.find(id); if (icl == _controller.end()) return; CtrlList* cl = icl->second; if (cl->empty()) return; iCtrl s = cl->lower_bound(frame1); iCtrl e = cl->lower_bound(frame2); cl->erase(s, e); return; }
void AudioTrack::eraseACEvent(int id, int frame) { ciCtrlList icl = _controller.find(id); if (icl == _controller.end()) return; CtrlList* cl = icl->second; if (cl->empty()) return; iCtrl s = cl->find(frame); if (s != cl->end()) cl->erase(s); return; }
void AudioTrack::seekPrevACEvent(int id) { ciCtrlList icl = _controller.find(id); if (icl == _controller.end()) return; CtrlList* cl = icl->second; if (cl->empty()) return; iCtrl s = cl->lower_bound(song->cPos().frame()); if (s != cl->begin()) --s; song->setPos(Song::CPOS, Pos(s->second.getFrame(), false), true, false, true); return; }
bool AudioTrack::readProperties(Xml& xml, const QString& tag) { if (tag == "LadspaPlugin" || tag == "plugin") { BasePlugin* pi = new LadspaPlugin(); pi->setTrack(this); pi->setId((int)_efxPipe->size()); if (pi->readConfiguration(xml, false)) delete pi; else _efxPipe->addPlugin(pi, -1); } else if (tag == "Lv2Plugin") { Lv2Plugin* pi = new Lv2Plugin(); pi->setTrack(this); pi->setId((int)_efxPipe->size()); if (pi->readConfiguration(xml, false)) delete pi; else _efxPipe->addPlugin(pi, -1); } else if (tag == "VstPlugin") { VstPlugin* pi = new VstPlugin(); pi->setTrack(this); pi->setId((int)_efxPipe->size()); if (pi->readConfiguration(xml, false)) delete pi; else _efxPipe->addPlugin(pi, -1); } else if (tag == "auxSend") readAuxSend(xml); else if (tag == "prefader") _prefader = xml.parseInt(); else if (tag == "sendMetronome") _sendMetronome = xml.parseInt(); else if (tag == "automation") setAutomationType(AutomationType(xml.parseInt())); else if (tag == "controller") { CtrlList* l = new CtrlList(); l->read(xml); // Since (until now) oom wrote a 'zero' for plugin controller current value // in the XML file, we can't use that value, now that plugin automation is added. // We must take the value from the plugin control value. // Otherwise we break all existing .oom files with plugins, because the gui // controls would all be set to zero. // But we will allow for the (unintended, useless) possibility of a controller // with no matching plugin control. BasePlugin* p = 0; bool ctlfound = false; int m = l->id() & AC_PLUGIN_CTL_ID_MASK; int n = (l->id() >> AC_PLUGIN_CTL_BASE_POW) - 1; int pdepth = _efxPipe->size(); if (n >= 0 && n < pdepth) { p = (*_efxPipe)[n]; if (p) { ParameterPort* cport = p->getParameterPort(m); if (cport && cport->type == PARAMETER_INPUT && (cport->hints & PARAMETER_IS_AUTOMABLE) > 0) ctlfound = true; } } iCtrlList icl = _controller.find(l->id()); if (icl == _controller.end()) _controller.add(l); else { CtrlList* d = icl->second; for (iCtrl i = l->begin(); i != l->end(); ++i) d->add(i->second.getFrame(), i->second.val); if (!ctlfound) d->setCurVal(l->curVal()); d->setColor(l->color()); d->setVisible(l->isVisible()); d->setDefault(l->getDefault()); delete l; l = d; } if (ctlfound) { l->setCurVal(p->getParameterValue(m)); ParameterPort* cport = p->getParameterPort(m); if (cport && cport->hints & PARAMETER_IS_TOGGLED) l->setMode(CtrlList::DISCRETE); else l->setMode(CtrlList::INTERPOLATE); } }
void AudioTrack::processAutomationEvents()/*{{{*/ { if (_automationType != AUTO_TOUCH && _automationType != AUTO_WRITE) return; for (iCtrlList icl = _controller.begin(); icl != _controller.end(); ++icl) { CtrlList* cl = icl->second; int id = cl->id(); // Remove old events from record region. if (_automationType == AUTO_WRITE) { int start = audio->getStartRecordPos().frame(); int end = audio->getEndRecordPos().frame(); iCtrl s = cl->lower_bound(start); iCtrl e = cl->lower_bound(end); // Erase old events only if there were recorded events. for (iCtrlRec icr = _recEvents.begin(); icr != _recEvents.end(); ++icr) { if (icr->id == id) // && icr->type == ARVT_VAL && icr->frame >= s->frame && icr->frame <= e->frame) { cl->erase(s, e); break; } } } else { // type AUTO_TOUCH for (iCtrlRec icr = _recEvents.begin(); icr != _recEvents.end(); ++icr) { // Don't bother looking for start, it's OK, just take the first one. // Needed for mousewheel and paging etc. //if (icr->id == id && icr->type == ARVT_START) if (icr->id == id) { int start = icr->getFrame(); if (icr == _recEvents.end()) { int end = audio->getEndRecordPos().frame(); iCtrl s = cl->lower_bound(start); iCtrl e = cl->lower_bound(end); cl->erase(s, e); break; } iCtrlRec icrlast = icr; ++icr; for (;; ++icr) { if (icr == _recEvents.end()) { int end = icrlast->getFrame(); iCtrl s = cl->lower_bound(start); iCtrl e = cl->lower_bound(end); cl->erase(s, e); break; } if (icr->id == id && icr->type == ARVT_STOP) { int end = icr->getFrame(); // Erase everything up to, not including, this stop event's frame. // Because an event was already stored directly when slider released. if (end > start) --end; iCtrl s = cl->lower_bound(start); iCtrl e = cl->lower_bound(end); cl->erase(s, e); break; } if (icr->id == id) icrlast = icr; } if (icr == _recEvents.end()) break; } } } // Extract all recorded events for controller "id" // from CtrlRecList and put into cl. for (iCtrlRec icr = _recEvents.begin(); icr != _recEvents.end(); ++icr) { if (icr->id == id && (icr->type == ARVT_VAL || icr->type == ARVT_START)) cl->add(icr->getFrame(), icr->val); } } // Done with the recorded automation event list. Clear it. _recEvents.clear(); // Try oom without this, so that the user can remain in automation write mode // after a stop. /* if (automationType() == AUTO_WRITE) { setAutomationType(AUTO_READ); song->update(SC_AUTOMATION); } */ }/*}}}*/
void AudioTrack::swapControllerIDX(int idx1, int idx2) { // FIXME This code is ugly. // At best we would like to modify the keys (IDXs) in-place and // do some kind of deferred re-sort, but it can't be done... int pdepth = _efxPipe->size(); if (idx1 == idx2) return; if (idx1 < 0 || idx2 < 0 || idx1 >= pdepth || idx2 >= pdepth) return; CtrlList *cl; CtrlList *newcl; int id1 = (idx1 + 1) * AC_PLUGIN_CTL_BASE; int id2 = (idx2 + 1) * AC_PLUGIN_CTL_BASE; int i, j; CtrlListList tmpcll; CtrlVal cv(0, 0.0); for (ciCtrlList icl = _controller.begin(); icl != _controller.end(); ++icl) { cl = icl->second; i = cl->id() & AC_PLUGIN_CTL_ID_MASK; j = cl->id() & ~((unsigned long) AC_PLUGIN_CTL_ID_MASK); if (j == id1 || j == id2) { newcl = new CtrlList(i | (j == id1 ? id2 : id1)); newcl->setMode(cl->mode()); newcl->setValueType(cl->valueType()); newcl->setName(cl->name()); double min, max; cl->range(&min, &max); newcl->setRange(min, max); newcl->setCurVal(cl->curVal()); newcl->setDefault(cl->getDefault()); for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { cv = ic->second; newcl->add(cv.getFrame(), cv.val); } tmpcll.insert(std::pair<const int, CtrlList*>(newcl->id(), newcl)); } else { newcl = new CtrlList(); *newcl = *cl; tmpcll.insert(std::pair<const int, CtrlList*>(newcl->id(), newcl)); } } for (iCtrlList ci = _controller.begin(); ci != _controller.end(); ++ci) delete (*ci).second; _controller.clear(); for (ciCtrlList icl = tmpcll.begin(); icl != tmpcll.end(); ++icl) { newcl = icl->second; _controller.insert(std::pair<const int, CtrlList*>(newcl->id(), newcl)); } }