bool Chaser::write(QByteArray* universes) { Q_UNUSED(universes); /* With some changes to scene, chaser could basically act as a proxy for its members by calling the scene's write() functions by itself instead of starting/stopping them. Whether this would do any good is not clear. */ /* TODO: One extra step is required in single shot mode to return false and thus get a chaser removed from MasterTimer. Not a big problem, but removing already after starting the last step would improve performance (very) slightly. */ if (m_elapsed == 0) { /* This is the first step since the last start() call */ /* Get the next step index */ nextStep(); /* Start the current function */ startMemberAt(m_runTimePosition); /* Mark one cycle being elapsed */ m_elapsed = 1; } else if (m_elapsed >= Bus::instance()->value(m_busID) || m_tapped == true) { /* Reset tapped flag even if it wasn't true */ m_tapped = false; /* Stop current function */ stopMemberAt(m_runTimePosition); /* Get the next step index */ nextStep(); /* Check, whether we have gone a full cycle (thru all steps) */ if (roundCheck() == false) return false; else startMemberAt(m_runTimePosition); /* Mark one cycle being elapsed since it tracks only the duration of the current step. */ m_elapsed = 1; } else { /* Just waiting for hold time to pass */ m_elapsed++; } return true; }
void RGBMatrix::tap() { if (stopped() == false) { FixtureGroup* grp = doc()->fixtureGroup(fixtureGroup()); // Filter out taps that are too close to each other if (grp != NULL && uint(m_roundTime->elapsed()) >= (duration() / 4)) roundCheck(grp->size()); } }
void RGBMatrix::write(MasterTimer* timer, QList<Universe *> universes) { Q_UNUSED(timer); Q_UNUSED(universes); FixtureGroup* grp = doc()->fixtureGroup(fixtureGroup()); if (grp == NULL) { // No fixture group to control stop(); return; } // No time to do anything. if (duration() == 0) return; // Invalid/nonexistent script { QMutexLocker algorithmLocker(&m_algorithmMutex); if (m_algorithm == NULL || m_algorithm->apiVersion() == 0) return; // Get new map every time when elapsed is reset to zero if (elapsed() == 0) { qDebug() << "RGBMatrix stepColor:" << QString::number(m_stepColor.rgb(), 16); RGBMap map = m_algorithm->rgbMap(grp->size(), m_stepColor.rgb(), m_step); updateMapChannels(map, grp); } } // Run the generic fader that takes care of fading in/out individual channels m_fader->write(universes); // Increment elapsed time incrementElapsed(); // Check if we need to change direction, stop completely or go to next step if (elapsed() >= duration()) roundCheck(grp->size()); }
bool ChaserRunner::write(MasterTimer* timer, UniverseArray* universes) { // Nothing to do if (m_steps.size() == 0) return false; if (m_newCurrent != -1) { // Manually-set current step m_currentStep = m_newCurrent; m_newCurrent = -1; // No need to do roundcheck here, since manually-set steps are // always within m_steps limits. m_elapsed = 1; handleChannelSwitch(timer, universes); emit currentStepChanged(m_currentStep); } else if (m_elapsed == 0) { // First step m_elapsed = 1; handleChannelSwitch(timer, universes); emit currentStepChanged(m_currentStep); } else if ((isAutoStep() && m_elapsed >= Bus::instance()->value(m_holdBusId)) || m_next == true || m_previous == true) { // Next step if (m_direction == Function::Forward) { // "Previous" for a forwards chaser is -1 if (m_previous == true) m_currentStep--; else m_currentStep++; } else { // "Previous" for a backwards scene is +1 if (m_previous == true) m_currentStep++; else m_currentStep--; } if (roundCheck() == false) return false; m_elapsed = 1; m_next = false; m_previous = false; handleChannelSwitch(timer, universes); emit currentStepChanged(m_currentStep); } else { // Current step. UINT_MAX is the maximum hold time. if (m_elapsed < UINT_MAX) m_elapsed++; } QMutableMapIterator <quint32,FadeChannel> it(m_channelMap); while (it.hasNext() == true) { Scene* scene = qobject_cast<Scene*> (m_steps.at(m_currentStep)); if (scene == NULL) continue; quint32 fadeTime = Bus::instance()->value(scene->busID()); FadeChannel& channel(it.next().value()); if (channel.current() == channel.target() && channel.group() != QLCChannel::Intensity) { /* Write the final value to LTP channels only once */ } else { uchar value = uchar(floor((qreal(channel.calculateCurrent(fadeTime, m_elapsed)) * m_intensity) + 0.5)); universes->write(channel.address(), value, channel.group()); } } return true; }
bool ChaserRunner::write(MasterTimer* timer, UniverseArray* universes) { Q_UNUSED(universes); // Nothing to do if (m_chaser->steps().size() == 0) return false; if (m_newCurrent != -1) { // Manually-set current step m_currentStep = m_newCurrent; m_newCurrent = -1; // No need to do roundcheck here, since manually-set steps are // always within m_chaser->steps() limits. m_elapsed = MasterTimer::tick(); switchFunctions(timer); emit currentStepChanged(m_currentStep); } else if (m_elapsed == 0) { // First step m_elapsed = MasterTimer::tick(); switchFunctions(timer); emit currentStepChanged(m_currentStep); } else if (m_next == true || m_previous == true || (currentDuration() != Function::infiniteSpeed() && m_elapsed >= currentDuration())) { // Next step if (m_direction == Function::Forward) { // "Previous" for a forwards chaser is -1 if (m_previous == true) m_currentStep--; else m_currentStep++; } else { // "Previous" for a backwards scene is +1 if (m_previous == true) m_currentStep++; else m_currentStep--; } if (roundCheck() == false) return false; m_elapsed = MasterTimer::tick(); m_next = false; m_previous = false; switchFunctions(timer); emit currentStepChanged(m_currentStep); } else { // Current step. UINT_MAX is the maximum hold time. if (m_elapsed < UINT_MAX) m_elapsed += MasterTimer::tick(); } // When the speeds of the chaser change, they need to be updated to the lower // level (only current function) as well. Otherwise the new speeds would take // effect only on the next step change. if (m_updateOverrideSpeeds == true) { m_updateOverrideSpeeds = false; if (m_currentFunction != NULL) { m_currentFunction->setOverrideFadeInSpeed(currentFadeIn()); m_currentFunction->setOverrideFadeOutSpeed(currentFadeOut()); } } return true; }
void RGBMatrix::write(MasterTimer* timer, QList<Universe *> universes) { Q_UNUSED(timer); { QMutexLocker algorithmLocker(&m_algorithmMutex); if (m_group == NULL) { // No fixture group to control stop(FunctionParent::master()); return; } // No time to do anything. if (duration() == 0) return; // Invalid/nonexistent script if (m_algorithm == NULL || m_algorithm->apiVersion() == 0) return; if (isPaused() == false) { // Get a new map every time elapsed is reset to zero if (elapsed() < MasterTimer::tick()) { if (tempoType() == Beats) m_stepBeatDuration = beatsToTime(duration(), timer->beatTimeDuration()); //qDebug() << "RGBMatrix step" << m_stepHandler->currentStepIndex() << ", color:" << QString::number(m_stepHandler->stepColor().rgb(), 16); RGBMap map = m_algorithm->rgbMap(m_group->size(), m_stepHandler->stepColor().rgb(), m_stepHandler->currentStepIndex()); updateMapChannels(map, m_group); } } } // Run the generic fader that takes care of fading in/out individual channels m_fader->write(universes, isPaused()); if (isPaused() == false) { // Increment the ms elapsed time incrementElapsed(); /* Check if we need to change direction, stop completely or go to next step * The cases are: * 1- time tempo type: act normally, on ms elapsed time * 2- beat tempo type, beat occurred: check if the elapsed beats is a multiple of * the step beat duration. If so, proceed to the next step * 3- beat tempo type, not beat: if the ms elapsed time reached the step beat * duration in ms, and the ms time to the next beat is not less than 1/16 of * the step beat duration in ms, then proceed to the next step. If the ms time to the * next beat is less than 1/16 of the step beat duration in ms, then defer the step * change to case #2, to resync the matrix to the next beat */ if (tempoType() == Time && elapsed() >= duration()) { roundCheck(); } else if (tempoType() == Beats) { if (timer->isBeat()) { incrementElapsedBeats(); qDebug() << "Elapsed beats:" << elapsedBeats() << ", time elapsed:" << elapsed() << ", step time:" << m_stepBeatDuration; if (elapsedBeats() % duration() == 0) { roundCheck(); resetElapsed(); } } else if (elapsed() >= m_stepBeatDuration && (uint)timer->timeToNextBeat() > m_stepBeatDuration / 16) { qDebug() << "Elapsed exceeded"; roundCheck(); } } } }