/* * Overlay current effects onto raw channel data */ int OverlayEffects(char *channelData) { int i; int dataRead = 0; std::unique_lock<std::mutex> lock(effectsLock); if (effectCount == 0) { return 0; } int skipBackground = 0; if (pauseBackgroundEffects && sequence->IsSequenceRunning()) { skipBackground = 1; } for (i = 0; i < MAX_EFFECTS; i++) { if (effects[i]) { if ((!skipBackground) || (skipBackground && (!effects[i]->background))) { dataRead |= OverlayEffect(i, channelData); } } } lock.unlock(); if ((dataRead == 0) && (!IsEffectRunning()) && (!sequence->IsSequenceRunning())) { sequence->SendBlankingData(); } return 1; }
void Sequence::ProcessSequenceData(int checkControlChannels) { if (IsEffectRunning()) OverlayEffects(m_seqData); if (UsingMemoryMapInput()) OverlayMemoryMap(m_seqData); if (checkControlChannels && getControlMajor() && getControlMinor()) { char thisMajor = NormalizeControlValue(m_seqData[getControlMajor()-1]); char thisMinor = NormalizeControlValue(m_seqData[getControlMinor()-1]); if ((m_seqLastControlMajor != thisMajor) || (m_seqLastControlMinor != thisMinor)) { m_seqLastControlMajor = thisMajor; m_seqLastControlMinor = thisMinor; if (m_seqLastControlMajor && m_seqLastControlMinor) TriggerEvent(m_seqLastControlMajor, m_seqLastControlMinor); } } if (channelTester->Testing()) channelTester->OverlayTestData(m_seqData); }
void Player::ProcessChannelData(void) { if (IsEffectRunning()) OverlayEffects(m_seqData); if (UsingMemoryMapInput()) OverlayMemoryMap(m_seqData); if (getControlMajor() && getControlMinor()) { char thisMajor = NormalizeControlValue(m_seqData[getControlMajor()-1]); char thisMinor = NormalizeControlValue(m_seqData[getControlMinor()-1]); if ((m_seqLastControlMajor != thisMajor) || (m_seqLastControlMinor != thisMinor)) { m_seqLastControlMajor = thisMajor; m_seqLastControlMinor = thisMinor; if (m_seqLastControlMajor && m_seqLastControlMinor) TriggerEvent(m_seqLastControlMajor, m_seqLastControlMinor); } } if (channelTester->Testing()) channelTester->OverlayTestData(m_seqData); if (m_brightness) AdjustBrightness(); }
/* * Stop all effects */ void StopAllEffects(void) { int i; LogDebug(VB_EFFECT, "Stopping all effects\n"); std::unique_lock<std::mutex> lock(effectsLock); for (i = 0; i < MAX_EFFECTS; i++) { if (effects[i]) StopEffectHelper(i); } lock.unlock(); if ((!IsEffectRunning()) && (!sequence->IsSequenceRunning())) sequence->SendBlankingData(); }
/* * Stop all effects named effectName */ int StopEffect(const std::string &effectName) { LogDebug(VB_EFFECT, "StopEffect(%s)\n", effectName.c_str()); std::unique_lock<std::mutex> lock(effectsLock); for (int i = 0; i < MAX_EFFECTS; i++) { if (effects[i] && effects[i]->name == effectName) StopEffectHelper(i); } lock.unlock(); if ((!IsEffectRunning()) && (!sequence->IsSequenceRunning())) sequence->SendBlankingData(); return 1; }
/* * Stop a single effect */ int StopEffect(int effectID) { FPPeffect *e = NULL; LogDebug(VB_EFFECT, "StopEffect(%d)\n", effectID); std::unique_lock<std::mutex> lock(effectsLock); if (!effects[effectID]) { return 0; } StopEffectHelper(effectID); lock.unlock(); if ((!IsEffectRunning()) && (!sequence->IsSequenceRunning())) sequence->SendBlankingData(); return 1; }
void Sequence::CloseSequenceFile(void) { LogDebug(VB_SEQUENCE, "CloseSequenceFile() %s\n", m_seqFilename); if (getFPPmode() == MASTER_MODE) SendSeqSyncStopPacket(m_seqFilename); pthread_mutex_lock(&m_sequenceLock); if (m_seqFile) { fclose(m_seqFile); m_seqFile = NULL; } m_seqFilename[0] = '\0'; m_seqPaused = 0; if ((getFPPmode() != REMOTE_MODE) && (!IsEffectRunning()) && (FPPstatus != FPP_STATUS_PLAYLIST_PLAYING)) SendBlankingData(); pthread_mutex_unlock(&m_sequenceLock); }
/* * Main loop in channel output thread */ void Player::RunChannelOutputThread(void) { static long long lastStatTime = 0; long long startTime; long long sendTime; long long readTime; int onceMore = 0; struct timespec ts; int syncFrameCounter = 0; LogDebug(VB_PLAYER | VB_CHANNELOUT, "RunChannelOutputThread() starting\n"); m_outputThreadIsRunning = 1; if ((getFPPmode() == REMOTE_MODE) && (!IsEffectRunning()) && (!UsingMemoryMapInput()) && (!channelTester->Testing()) && (!getAlwaysTransmit())) { // Sleep about 2 seconds waiting for the master int loops = 0; while ((m_masterFramesPlayed < 0) && (loops < 200)) { usleep(10000); loops++; } // Stop playback if the master hasn't sent any sync packets yet if (m_masterFramesPlayed < 0) m_runOutputThread = 0; } StartOutputThreads(); while (m_runOutputThread) { startTime = GetTime(); pthread_mutex_lock(&m_sequenceLock); int runningSequences = m_sequence.size(); if ((getFPPmode() == MASTER_MODE) && (runningSequences)) { if (syncFrameCounter & 0x10) { // Send sync every 16 frames (use 16 to make the check simpler) syncFrameCounter = 1; for (int i = 0; i < m_sequence.size(); i++) SendSeqSyncPacket( m_sequence[i]->m_seqFilename, channelOutputFrame, mediaElapsedSeconds); } else { syncFrameCounter++; } } if (m_outputFrames) { if (getFPPmode() == BRIDGE_MODE) { memcpy(m_seqData, e131Data, FPPD_MAX_CHANNELS); } else { for (int i = 0; i < m_sequence.size(); i++) m_sequence[i]->OverlayNextFrame(m_seqData); } SendChannelData(m_seqData); } sendTime = GetTime(); if ((getFPPmode() != BRIDGE_MODE) && (runningSequences)) { // Close any sequences that aren't open anymore for (int i = m_sequence.size() - 1; i >= 0; i--) { if (!m_sequence[i]->SequenceFileOpen()) { Sequence *seq = m_sequence[i]; m_sequence.erase(m_sequence.begin() + i); delete seq; } } runningSequences = m_sequence.size(); // Loop through sequences pre-reading next frame of data for (int i = 0; i < m_sequence.size(); i++) { m_sequence[i]->ReadSequenceData(); } } ProcessChannelData(); readTime = GetTime(); pthread_mutex_unlock(&m_sequenceLock); if ((runningSequences) || (IsEffectRunning()) || (UsingMemoryMapInput()) || (channelTester->Testing()) || (getAlwaysTransmit()) || (getFPPmode() == BRIDGE_MODE)) { onceMore = 1; if (startTime > (lastStatTime + 1000000)) { int sleepTime = m_lightDelay - (GetTime() - startTime); if (sleepTime < 0) sleepTime = 0; lastStatTime = startTime; LogDebug(VB_PLAYER | VB_CHANNELOUT, "Output Thread: Loop: %dus, Send: %lldus, Read: %lldus, Sleep: %dus, FrameNum: %ld\n", m_lightDelay, sendTime - startTime, readTime - sendTime, sleepTime, channelOutputFrame); } } else { m_lightDelay = m_defaultLightDelay; if (onceMore) onceMore = 0; else m_runOutputThread = 0; } // Calculate how long we need to nanosleep() ts.tv_sec = 0; ts.tv_nsec = (m_lightDelay - (GetTime() - startTime)) * 1000; nanosleep(&ts, NULL); } StopOutputThreads(); m_outputThreadIsRunning = 0; LogDebug(VB_PLAYER | VB_CHANNELOUT, "RunChannelOutputThread() completed\n"); pthread_exit(NULL); }