void GenericFader_Test::addRemove() { GenericFader fader(m_doc); FadeChannel fc; fc.setFixture(0); fc.setChannel(0); FadeChannel wrong; fc.setFixture(0); QCOMPARE(fader.m_channels.count(), 0); QVERIFY(fader.m_channels.contains(fc) == false); fader.add(fc); QVERIFY(fader.m_channels.contains(fc) == true); QCOMPARE(fader.m_channels.count(), 1); fader.remove(wrong); QVERIFY(fader.m_channels.contains(fc) == true); QCOMPARE(fader.m_channels.count(), 1); fader.remove(fc); QVERIFY(fader.m_channels.contains(fc) == false); QCOMPARE(fader.m_channels.count(), 0); fc.setChannel(0); fader.add(fc); QVERIFY(fader.m_channels.contains(fc) == true); fc.setChannel(1); fader.add(fc); QVERIFY(fader.m_channels.contains(fc) == true); fc.setChannel(2); fader.add(fc); QVERIFY(fader.m_channels.contains(fc) == true); QCOMPARE(fader.m_channels.count(), 3); fader.removeAll(); QCOMPARE(fader.m_channels.count(), 0); fc.setFixture(0); fc.setChannel(0); fc.setTarget(127); fader.add(fc); QCOMPARE(fader.m_channels.size(), 1); QCOMPARE(fader.m_channels[fc].target(), uchar(127)); fc.setTarget(63); fader.add(fc); QCOMPARE(fader.m_channels.size(), 1); QCOMPARE(fader.m_channels[fc].target(), uchar(63)); fc.setCurrent(63); fader.add(fc); QCOMPARE(fader.m_channels.size(), 1); QCOMPARE(fader.m_channels[fc].target(), uchar(63)); }
void CueStack::switchCue(int from, int to, const QList<Universe *> ua) { qDebug() << Q_FUNC_INFO; Cue newCue; Cue oldCue; m_mutex.lock(); if (to >= 0 && to < m_cues.size()) newCue = m_cues[to]; if (from >= 0 && from < m_cues.size()) oldCue = m_cues[from]; m_mutex.unlock(); // Fade out the HTP channels of the previous cue QHashIterator <uint,uchar> oldit(oldCue.values()); while (oldit.hasNext() == true) { oldit.next(); FadeChannel fc; fc.setFixture(doc(), Fixture::invalidId()); fc.setChannel(oldit.key()); if (fc.group(doc()) == QLCChannel::Intensity) { fc.setElapsed(0); fc.setReady(false); fc.setTarget(0); fc.setFadeTime(oldCue.fadeOutSpeed()); insertStartValue(fc, ua); m_fader->add(fc); } } // Fade in all channels of the new cue QHashIterator <uint,uchar> newit(newCue.values()); while (newit.hasNext() == true) { newit.next(); FadeChannel fc; fc.setFixture(doc(), Fixture::invalidId()); fc.setChannel(newit.key()); fc.setTarget(newit.value()); fc.setElapsed(0); fc.setReady(false); fc.setFadeTime(newCue.fadeInSpeed()); insertStartValue(fc, ua); m_fader->add(fc); } }
void FadeChannel_Test::group() { Doc doc(this); FadeChannel fc; // Only a channel given, no fixture at the address -> intensity fc.setChannel(2); QCOMPARE(fc.group(&doc), QLCChannel::Intensity); Fixture* fxi = new Fixture(&doc); fxi->setAddress(10); fxi->setChannels(5); doc.addFixture(fxi); // Fixture and channel given, fixture is a dimmer -> intensity fc.setFixture(&doc, fxi->id()); QCOMPARE(fc.group(&doc), QLCChannel::Intensity); QDir dir(INTERNAL_FIXTUREDIR); dir.setFilter(QDir::Files); dir.setNameFilters(QStringList() << QString("*%1").arg(KExtFixture)); QVERIFY(doc.fixtureDefCache()->load(dir) == true); QLCFixtureDef* def = doc.fixtureDefCache()->fixtureDef("Futurelight", "DJScan250"); QVERIFY(def != NULL); QLCFixtureMode* mode = def->modes().first(); QVERIFY(mode != NULL); fxi = new Fixture(&doc); fxi->setAddress(0); fxi->setFixtureDefinition(def, mode); doc.addFixture(fxi); // Fixture and channel given, but channel is beyond fixture's channels -> intensity fc.setFixture(&doc, fxi->id()); fc.setChannel(50); QCOMPARE(fc.group(&doc), QLCChannel::Intensity); // Only a channel given, no fixture given but a fixture occupies the address. // Check that reverse address -> fixture lookup works. fc.setFixture(&doc, Fixture::invalidId()); fc.setChannel(2); QCOMPARE(fc.group(&doc), QLCChannel::Colour); // Fixture and channel given, but fixture doesn't exist -> intensity fc.setFixture(&doc, 12345); fc.setChannel(2); QCOMPARE(fc.group(&doc), QLCChannel::Intensity); }
void EFXFixture::stop(MasterTimer* timer, QList<Universe *> universes) { Q_UNUSED(universes); if (fadeIntensity() > 0 && m_started == true) { Fixture* fxi = doc()->fixture(head().fxi); Q_ASSERT(fxi != NULL); if (fxi->masterIntensityChannel(head().head) != QLCChannel::invalid()) { FadeChannel fc; fc.setFixture(doc(), head().fxi); fc.setChannel(fxi->masterIntensityChannel(head().head)); if (m_parent->overrideFadeOutSpeed() != Function::defaultSpeed()) fc.setFadeTime(m_parent->overrideFadeOutSpeed()); else fc.setFadeTime(m_parent->fadeOutSpeed()); fc.setStart(uchar(floor((float(fadeIntensity()) * intensity()) + 0.5))); fc.setCurrent(fc.start()); fc.setTarget(0); // Give zero-fading to MasterTimer because EFX will stop after this call timer->faderAdd(fc); // Remove the previously up-faded channel from EFX's internal fader to allow // MasterTimer's fader take HTP precedence. m_parent->m_fader->remove(fc); } } m_started = false; }
void EFXFixture::start(MasterTimer* timer, QList<Universe *> universes) { Q_UNUSED(universes); Q_UNUSED(timer); if (fadeIntensity() > 0 && m_started == false) { Fixture* fxi = doc()->fixture(head().fxi); Q_ASSERT(fxi != NULL); if (fxi->masterIntensityChannel(head().head) != QLCChannel::invalid()) { FadeChannel fc; fc.setFixture(doc(), head().fxi); fc.setChannel(fxi->masterIntensityChannel(head().head)); if (m_parent->overrideFadeInSpeed() != Function::defaultSpeed()) fc.setFadeTime(m_parent->overrideFadeInSpeed()); else fc.setFadeTime(m_parent->fadeInSpeed()); fc.setStart(0); fc.setCurrent(fc.start()); // Don't use intensity() multiplier because EFX's GenericFader takes care of that fc.setTarget(fadeIntensity()); // Fade channel up with EFX's own GenericFader to allow manual intensity control m_parent->m_fader->add(fc); } } m_started = true; }
void GenericFader_Test::writeLoop() { UniverseArray ua(512); GenericFader fader(m_doc); FadeChannel fc; fc.setFixture(0); fc.setChannel(5); fc.setStart(0); fc.setTarget(250); fc.setFadeTime(1000); fader.add(fc); QCOMPARE(ua.preGMValues()[15], (char) 0); int expected = 0; for (int i = MasterTimer::tick(); i <= 1000; i += MasterTimer::tick()) { ua.zeroIntensityChannels(); fader.write(&ua); int actual = uchar(ua.preGMValues()[15]); expected += 5; QCOMPARE(actual, expected); } }
void GenericDMXSource::writeDMX(MasterTimer* timer, QList<Universe *> ua) { Q_UNUSED(timer); m_mutex.lock(); QMutableMapIterator <QPair<quint32,quint32>,uchar> it(m_values); while (it.hasNext() == true && m_outputEnabled == true) { it.next(); FadeChannel fc; fc.setFixture(m_doc, it.key().first); fc.setChannel(it.key().second); QLCChannel::Group grp = fc.group(m_doc); quint32 address = fc.address(); quint32 universe = fc.universe(); if (address != QLCChannel::invalid()) ua[universe]->write(address, it.value()); if (grp != QLCChannel::Intensity) it.remove(); } m_mutex.unlock(); }
/***************************************************************************** * Helper Function *****************************************************************************/ void EFXFixture::setFadeChannel(quint32 nChannel, uchar val) { FadeChannel fc; fc.setFixture(doc(), head().fxi); fc.setChannel(nChannel); fc.setTarget(val); m_parent->m_fader->forceAdd(fc); }
void FadeChannel_Test::address() { Doc doc(this); Fixture* fxi = new Fixture(&doc); fxi->setAddress(400); fxi->setChannels(5); doc.addFixture(fxi); FadeChannel fc; fc.setChannel(2); QCOMPARE(fc.address(), quint32(2)); fc.setFixture(&doc, fxi->id()); QCOMPARE(fc.address(), quint32(402)); fc.setFixture(&doc, 12345); QCOMPARE(fc.address(), QLCChannel::invalid()); }
void GenericFader_Test::writeZeroFade() { UniverseArray ua(512); GenericFader fader(m_doc); FadeChannel fc; fc.setFixture(0); fc.setChannel(5); fc.setStart(0); fc.setTarget(255); fc.setFadeTime(0); fader.add(fc); QCOMPARE(ua.preGMValues()[15], (char) 0); fader.write(&ua); QCOMPARE(ua.preGMValues()[15], (char) 255); }
void EFXFixture_Test::stop() { QList<Universe*> ua; ua.append(new Universe(0, new GrandMaster())); MasterTimerStub mts(m_doc, ua); EFX e(m_doc); e.setFadeInSpeed(1000); e.setFadeOutSpeed(2000); EFXFixture* ef = new EFXFixture(&e); ef->setHead(GroupHead(0,0)); e.addFixture(ef); Fixture* fxi = m_doc->fixture(0); QVERIFY(fxi != NULL); e.preRun(&mts); // Not started yet ef->stop(&mts, ua); QCOMPARE(e.m_fader->m_channels.size(), 0); QCOMPARE(mts.fader()->m_channels.size(), 0); // Start ef->start(&mts, ua); QCOMPARE(e.m_fader->m_channels.size(), 1); FadeChannel fc; fc.setFixture(m_doc, fxi->id()); fc.setChannel(fxi->masterIntensityChannel()); QVERIFY(e.m_fader->m_channels.contains(fc) == true); // Then stop ef->stop(&mts, ua); QCOMPARE(e.m_fader->m_channels.size(), 0); // FadeChannels are handed over to MasterTimer's GenericFader QCOMPARE(mts.fader()->m_channels.size(), 1); QVERIFY(e.m_fader->m_channels.contains(fc) == false); QVERIFY(mts.m_fader->m_channels.contains(fc) == true); QCOMPARE(mts.m_fader->m_channels[fc].fadeTime(), uint(2000)); e.postRun(&mts, ua); }
void GenericFader_Test::adjustIntensity() { UniverseArray ua(512); GenericFader fader(m_doc); FadeChannel fc; // HTP channel fc.setFixture(0); fc.setChannel(5); fc.setStart(0); fc.setTarget(250); fc.setFadeTime(1000); fader.add(fc); // LTP channel fc.setChannel(0); fader.add(fc); qreal intensity = 0.5; fader.adjustIntensity(intensity); QCOMPARE(fader.intensity(), intensity); int expected = 0; for (int i = MasterTimer::tick(); i <= 1000; i += MasterTimer::tick()) { ua.zeroIntensityChannels(); fader.write(&ua); expected += 5; // GenericFader should apply intensity only to HTP channels int actual = uchar(ua.preGMValues()[15]); int expectedWithIntensity = floor((qreal(expected) * intensity) + 0.5); QVERIFY(actual == expectedWithIntensity); // No intensity adjustment on LTP channels actual = uchar(ua.preGMValues()[10]); QVERIFY(actual == expected); } }
void EFXFixture_Test::start() { QList<Universe*> ua; ua.append(new Universe(0, new GrandMaster())); MasterTimerStub mts(m_doc, ua); EFX e(m_doc); e.setFadeInSpeed(1000); e.setFadeOutSpeed(2000); EFXFixture* ef = new EFXFixture(&e); ef->setHead(GroupHead(0,0)); e.addFixture(ef); Fixture* fxi = m_doc->fixture(0); QVERIFY(fxi != NULL); e.preRun(&mts); // Fade intensity == 0, no need to do fade-in ef->setFadeIntensity(0); ef->start(&mts, ua); QCOMPARE(e.m_fader->m_channels.size(), 0); ef->m_started = false; // Fade intensity > 0, need to do fade-in ef->setFadeIntensity(1); ef->start(&mts, ua); QCOMPARE(e.m_fader->m_channels.size(), 1); FadeChannel fc; fc.setFixture(m_doc, fxi->id()); fc.setChannel(fxi->masterIntensityChannel()); QVERIFY(e.m_fader->m_channels.contains(fc) == true); QCOMPARE(e.m_fader->m_channels[fc].fadeTime(), uint(1000)); e.postRun(&mts, ua); }
void EFXFixture_Test::start() { UniverseArray array(512 * 4); MasterTimerStub mts(m_doc, array); EFX e(m_doc); e.setFadeInSpeed(1000); e.setFadeOutSpeed(2000); EFXFixture* ef = new EFXFixture(&e); ef->setFixture(0); e.addFixture(ef); Fixture* fxi = m_doc->fixture(0); QVERIFY(fxi != NULL); e.preRun(&mts); // Fade intensity == 0, no need to do fade-in ef->setFadeIntensity(0); ef->start(&mts, &array); QCOMPARE(e.m_fader->m_channels.size(), 0); ef->m_started = false; // Fade intensity > 0, need to do fade-in ef->setFadeIntensity(1); ef->start(&mts, &array); QCOMPARE(e.m_fader->m_channels.size(), 1); FadeChannel fc; fc.setFixture(fxi->id()); fc.setChannel(fxi->masterIntensityChannel()); QVERIFY(e.m_fader->m_channels.contains(fc) == true); QCOMPARE(e.m_fader->m_channels[fc].fadeTime(), uint(1000)); e.postRun(&mts, &array); }
void RGBMatrix::updateMapChannels(const RGBMap& map, const FixtureGroup* grp) { quint32 mdAssigned = QLCChannel::invalid(); quint32 mdFxi = Fixture::invalidId(); uint fadeTime = 0; if (overrideFadeInSpeed() == defaultSpeed()) fadeTime = fadeInSpeed(); else fadeTime = overrideFadeInSpeed(); // Create/modify fade channels for ALL pixels in the color map. for (int y = 0; y < map.size(); y++) { for (int x = 0; x < map[y].size(); x++) { QLCPoint pt(x, y); GroupHead grpHead(grp->head(pt)); Fixture* fxi = doc()->fixture(grpHead.fxi); if (fxi == NULL) continue; if (grpHead.fxi != mdFxi) { mdAssigned = QLCChannel::invalid(); mdFxi = grpHead.fxi; } QLCFixtureHead head = fxi->head(grpHead.head); QVector <quint32> rgb = head.rgbChannels(); QVector <quint32> cmy = head.cmyChannels(); if (rgb.size() == 3) { // RGB color mixing FadeChannel fc; fc.setFixture(doc(), grpHead.fxi); fc.setChannel(rgb.at(0)); fc.setTarget(qRed(map[y][x])); insertStartValues(fc, fadeTime); m_fader->add(fc); fc.setChannel(rgb.at(1)); fc.setTarget(qGreen(map[y][x])); insertStartValues(fc, fadeTime); m_fader->add(fc); fc.setChannel(rgb.at(2)); fc.setTarget(qBlue(map[y][x])); insertStartValues(fc, fadeTime); m_fader->add(fc); } else if (cmy.size() == 3) { // CMY color mixing QColor col(map[y][x]); FadeChannel fc; fc.setFixture(doc(), grpHead.fxi); fc.setChannel(cmy.at(0)); fc.setTarget(col.cyan()); insertStartValues(fc, fadeTime); m_fader->add(fc); fc.setChannel(cmy.at(1)); fc.setTarget(col.magenta()); insertStartValues(fc, fadeTime); m_fader->add(fc); fc.setChannel(cmy.at(2)); fc.setTarget(col.yellow()); insertStartValues(fc, fadeTime); m_fader->add(fc); } if (m_dimmerControl && head.masterIntensityChannel() != QLCChannel::invalid()) { //qDebug() << "RGBMatrix: found dimmer at" << head.masterIntensityChannel(); // Simple intensity (dimmer) channel QColor col(map[y][x]); FadeChannel fc; fc.setFixture(doc(), grpHead.fxi); fc.setChannel(head.masterIntensityChannel()); if (col.value() == 0 && mdAssigned != head.masterIntensityChannel()) fc.setTarget(0); else { fc.setTarget(255); if (mdAssigned == QLCChannel::invalid()) mdAssigned = head.masterIntensityChannel(); } insertStartValues(fc, fadeTime); m_fader->add(fc); } } } }
QString Script::handleSetFixture(const QList<QStringList>& tokens, QList<Universe *> universes) { qDebug() << Q_FUNC_INFO; if (tokens.size() > 4) return QString("Too many arguments"); bool ok = false; quint32 id = 0; quint32 ch = 0; uchar value = 0; double time = 0; id = tokens[0][1].toUInt(&ok); if (ok == false) return QString("Invalid fixture (ID: %1)").arg(tokens[0][1]); for (int i = 1; i < tokens.size(); i++) { QStringList list = tokens[i]; list[0] = list[0].toLower().trimmed(); if (list.size() == 2) { ok = false; if (list[0] == "val" || list[0] == "value") value = uchar(list[1].toUInt(&ok)); else if (list[0] == "ch" || list[0] == "channel") ch = list[1].toUInt(&ok); else if (list[0] == "time") time = list[1].toDouble(&ok); else return QString("Unrecognized keyword: %1").arg(list[0]); if (ok == false) return QString("Invalid value (%1) for keyword: %2").arg(list[1]).arg(list[0]); } } Doc* doc = qobject_cast<Doc*> (parent()); Q_ASSERT(doc != NULL); Fixture* fxi = doc->fixture(id); if (fxi != NULL) { if (ch < fxi->channels()) { int address = fxi->address() + ch; if (address < 512) { GenericFader* gf = fader(); Q_ASSERT(gf != NULL); FadeChannel fc; fc.setFixture(doc, fxi->id()); fc.setChannel(ch); fc.setTarget(value); fc.setFadeTime(time); // If the script has used the channel previously, it might still be in // the bowels of GenericFader so get the starting value from there. // Otherwise get it from universes (HTP channels are always 0 then). quint32 uni = fc.universe(); if (gf->channels().contains(fc) == true) fc.setStart(gf->channels()[fc].current()); else fc.setStart(universes[uni]->preGMValue(address)); fc.setCurrent(fc.start()); gf->add(fc); return QString(); } else { return QString("Invalid address: %1").arg(address); } } else { return QString("Fixture (%1) has no channel number %2").arg(fxi->name()).arg(ch); } } else { return QString("No such fixture (ID: %1)").arg(id); } }