void Function::setTempoType(const Function::TempoType &type) { if (type == m_tempoType) return; m_tempoType = type; /* Retrieve the current BPM value known by the Master Timer */ float bpmNum = doc()->masterTimer()->bpmNumber(); /* Calculate the duration in ms of a single beat */ float beatTime = 60000.0 / bpmNum; switch (type) { /* Beats -> Time */ case Time: setFadeInSpeed(beatsToTime(fadeInSpeed(), beatTime)); setDuration(beatsToTime(duration(), beatTime)); setFadeOutSpeed(beatsToTime(fadeOutSpeed(), beatTime)); disconnect(doc()->masterTimer(), SIGNAL(bpmNumberChanged(int)), this, SLOT(slotBPMChanged(int))); break; /* Time -> Beats */ case Beats: setFadeInSpeed(timeToBeats(fadeInSpeed(), beatTime)); setDuration(timeToBeats(duration(), beatTime)); setFadeOutSpeed(timeToBeats(fadeOutSpeed(), beatTime)); connect(doc()->masterTimer(), SIGNAL(bpmNumberChanged(int)), this, SLOT(slotBPMChanged(int))); break; default: qDebug() << "Error. Unhandled tempo type" << type; break; } emit changed(m_id); }
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(); } } } }