Ejemplo n.º 1
0
void MainLoop(void)
{
	int            commandSock = 0;
	int            controlSock = 0;
	int            bridgeSock = 0;
	int            prevFPPstatus = FPPstatus;
	int            sleepms = 50000;
	fd_set         active_fd_set;
	fd_set         read_fd_set;
	struct timeval timeout;
	int            selectResult;

	LogDebug(VB_GENERAL, "MainLoop()\n");

	FD_ZERO (&active_fd_set);

	CheckExistanceOfDirectoriesAndFiles();

	piFaceSetup(200); // PiFace inputs 1-8 == wiringPi 200-207

	if (getFPPmode() == BRIDGE_MODE)
	{
		bridgeSock = Bridge_Initialize();
		if (bridgeSock)
			FD_SET (bridgeSock, &active_fd_set);
	}
	else
	{
		InitMediaOutput();
	}

	pluginCallbackManager.init();

	InitializeChannelOutputs();
	sequence->SendBlankingData();

	InitEffects();
	InitializeChannelDataMemoryMap();

	commandSock = Command_Initialize();
	if (commandSock)
		FD_SET (commandSock, &active_fd_set);

#ifdef USEHTTPAPI
	APIServer apiServer;
	apiServer.Init();
#endif

	controlSock = InitControlSocket();
	FD_SET (controlSock, &active_fd_set);

	SetupGPIOInput();

	if (getFPPmode() & PLAYER_MODE)
	{
		if (getFPPmode() == MASTER_MODE)
			InitSyncMaster();

		scheduler->CheckIfShouldBePlayingNow();

		if (getAlwaysTransmit())
			StartChannelOutputThread();
	}

	LogInfo(VB_GENERAL, "Starting main processing loop\n");

	while (runMainFPPDLoop)
	{
		timeout.tv_sec  = 0;
		timeout.tv_usec = sleepms;

		read_fd_set = active_fd_set;


		selectResult = select(FD_SETSIZE, &read_fd_set, NULL, NULL, &timeout);
		if (selectResult < 0)
		{
			if (errno == EINTR)
			{
				// We get interrupted when media players finish
				continue;
			}
			else
			{
				LogErr(VB_GENERAL, "Main select() failed: %s\n",
					strerror(errno));
				runMainFPPDLoop = 0;
				continue;
			}
		}

		if (commandSock && FD_ISSET(commandSock, &read_fd_set))
			CommandProc();

		if (bridgeSock && FD_ISSET(bridgeSock, &read_fd_set))
			Bridge_ReceiveData();

		if (controlSock && FD_ISSET(controlSock, &read_fd_set))
			ProcessControlPacket();

		// Check to see if we need to start up the output thread.
		// FIXME, possibly trigger this via a fpp command to fppd
		if ((!ChannelOutputThreadIsRunning()) &&
			(getFPPmode() != BRIDGE_MODE) &&
			((UsingMemoryMapInput()) ||
			 (channelTester->Testing()) ||
			 (getAlwaysTransmit()))) {
			int E131BridgingInterval = getSettingInt("E131BridgingInterval");
			if (!E131BridgingInterval)
				E131BridgingInterval = 50;
			SetChannelOutputRefreshRate(1000 / E131BridgingInterval);
			StartChannelOutputThread();
		}

		if (getFPPmode() & PLAYER_MODE)
		{
			if ((FPPstatus == FPP_STATUS_PLAYLIST_PLAYING) ||
				(FPPstatus == FPP_STATUS_STOPPING_GRACEFULLY))
			{
				if (prevFPPstatus == FPP_STATUS_IDLE)
				{
					playlist->PlayListPlayingInit();
					sleepms = 10000;
				}

				// Check again here in case PlayListPlayingInit
				// didn't find anything and put us back to IDLE
				if ((FPPstatus == FPP_STATUS_PLAYLIST_PLAYING) ||
					(FPPstatus == FPP_STATUS_STOPPING_GRACEFULLY))
				{
					playlist->PlayListPlayingProcess();
				}
			}

			int reactivated = 0;
			if (FPPstatus == FPP_STATUS_IDLE)
			{
				if ((prevFPPstatus == FPP_STATUS_PLAYLIST_PLAYING) ||
					(prevFPPstatus == FPP_STATUS_STOPPING_GRACEFULLY))
				{
					playlist->PlayListPlayingCleanup();

					if (FPPstatus != FPP_STATUS_IDLE)
						reactivated = 1;
					else
						sleepms = 50000;
				}
			}

			if (reactivated)
				prevFPPstatus = FPP_STATUS_IDLE;
			else
				prevFPPstatus = FPPstatus;

			scheduler->ScheduleProc();
		}
		else if (getFPPmode() == REMOTE_MODE)
		{
			if(mediaOutputStatus.status == MEDIAOUTPUTSTATUS_PLAYING)
			{
				playlist->PlaylistProcessMediaData();
			}
		}

		CheckGPIOInputs();
	}

	StopChannelOutputThread();
	ShutdownControlSocket();

	if (getFPPmode() == BRIDGE_MODE)
		Bridge_Shutdown();

	LogInfo(VB_GENERAL, "Main Loop complete, shutting down.\n");
}
Ejemplo n.º 2
0
Archivo: Player.cpp Proyecto: dkulp/fpp
/*
 * 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);
}