diff --git a/include/input/InputFPPRemote.h b/include/input/InputFPPRemote.h index 5a7df9f0f..e10c8f361 100644 --- a/include/input/InputFPPRemote.h +++ b/include/input/InputFPPRemote.h @@ -42,14 +42,14 @@ class c_InputFPPRemote : public c_InputCommon void GetDriverName (String& sDriverName) { sDriverName = "FPP Remote"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize); void ProcessButtonActions(c_ExternalInput::InputValue_t value); + void SetOperationalState (bool ActiveFlag); protected: # define No_LocalFileToPlay "..." -# define FPP_REMOTE_TASK_PRIORITY 6 c_InputFPPRemotePlayItem * pInputFPPRemotePlayItem = nullptr; int32_t GetSyncOffsetMS () { return SyncOffsetMS; } - bool GetSendFppSync () { return SendFppSync; } + bool GetSendFppSync () { return SendFppSync; } String StatusType; diff --git a/include/input/InputFPPRemotePlayFile.hpp b/include/input/InputFPPRemotePlayFile.hpp index c637d5e61..f878bd778 100644 --- a/include/input/InputFPPRemotePlayFile.hpp +++ b/include/input/InputFPPRemotePlayFile.hpp @@ -23,13 +23,11 @@ #include "InputFPPRemotePlayItem.hpp" #include "InputFPPRemotePlayFileFsm.hpp" #include "service/fseq.h" -#include #ifdef ARDUINO_ARCH_ESP32 #include #endif // def ARDUINO_ARCH_ESP32 - class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem { public: @@ -43,7 +41,6 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem virtual void GetStatus (JsonObject & jsonStatus); virtual bool IsIdle () { return (pCurrentFsmState == &fsm_PlayFile_state_Idle_imp); } - void TimerPoll (); #ifdef ARDUINO_ARCH_ESP32 TaskHandle_t GetTaskHandle () { return TimerPollTaskHandle; } volatile bool TimerPollInProgress = false; @@ -52,7 +49,7 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem private: #define ELAPSED_PLAY_TIMER_INTERVAL_MS 10 - void ClearFileInfo (); + void ClearFileInfo (); friend class fsm_PlayFile_state_Idle; friend class fsm_PlayFile_state_Starting; @@ -69,18 +66,6 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem fsm_PlayFile_state * pCurrentFsmState = &fsm_PlayFile_state_Idle_imp; - c_FileMgr::FileId FileHandleForFileBeingPlayed = c_FileMgr::INVALID_FILE_HANDLE; - - struct FrameControl_t - { - uint32_t DataOffset = 0; - uint32_t ChannelsPerFrame = 0; - uint32_t FrameStepTimeMS = 1; - uint32_t TotalNumberOfFramesInSequence = 0; - uint32_t ElapsedPlayTimeMS = 0; - - } FrameControl; - struct SyncControl_t { uint32_t SyncCount = 0; @@ -88,17 +73,8 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem float LastRcvdElapsedSeconds = 0.0; } SyncControl; -# define FPP_TICKER_PERIOD_MS 25 -// # define FPP_TICKER_PERIOD_MS 1000 - Ticker MsTicker; - uint32_t LastIsrTimeStampMS = 0; uint32_t PlayedFileCount = 0; - // Logic to detect if polls have stopped coming in. - // This is part of the blanking logic. - int PollDetectionCounter = 0; - static const int PollDetectionCounterLimit = 5; - #define MAX_NUM_SPARSE_RANGES 5 FSEQParsedRangeEntry SparseRanges[MAX_NUM_SPARSE_RANGES]; diff --git a/include/input/InputFPPRemotePlayFileFsm.hpp b/include/input/InputFPPRemotePlayFileFsm.hpp index 28bc0a13b..e95cbf9a6 100644 --- a/include/input/InputFPPRemotePlayFileFsm.hpp +++ b/include/input/InputFPPRemotePlayFileFsm.hpp @@ -36,14 +36,13 @@ class fsm_PlayFile_state fsm_PlayFile_state() {} virtual ~fsm_PlayFile_state() {} - virtual bool Poll () = 0; + virtual IRAM_ATTR bool Poll () = 0; virtual void Init (c_InputFPPRemotePlayFile * Parent) = 0; virtual void GetStateName (String & sName) = 0; virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount) = 0; virtual void Stop (void) = 0; virtual bool Sync (String& FileName, float SecondsElapsed) = 0; void GetDriverName (String& Name) { Name = "InputMgr"; } - virtual IRAM_ATTR void TimerPoll () = 0; protected: c_InputFPPRemotePlayFile * p_Parent = nullptr; @@ -57,13 +56,12 @@ class fsm_PlayFile_state_Idle : public fsm_PlayFile_state fsm_PlayFile_state_Idle() {} virtual ~fsm_PlayFile_state_Idle() {} - virtual bool Poll (); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String & sName) { sName = CN_Idle; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); }; // fsm_PlayFile_state_Idle @@ -74,13 +72,12 @@ class fsm_PlayFile_state_Starting : public fsm_PlayFile_state fsm_PlayFile_state_Starting() {} virtual ~fsm_PlayFile_state_Starting() {} - virtual bool Poll (); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String& sName) { sName = F ("Starting"); } virtual void Start (String& FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); }; // fsm_PlayFile_state_Starting @@ -91,13 +88,12 @@ class fsm_PlayFile_state_PlayingFile : public fsm_PlayFile_state fsm_PlayFile_state_PlayingFile() {} virtual ~fsm_PlayFile_state_PlayingFile() {} - virtual bool Poll (); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String & sName) { sName = CN_File; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String & FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); private: struct SparseRange @@ -105,7 +101,7 @@ class fsm_PlayFile_state_PlayingFile : public fsm_PlayFile_state uint32_t DataOffset; uint32_t ChannelCount; }; - uint32_t LastPlayedFrameId = 0; + // uint32_t LastPlayedFrameId = 0; }; // fsm_PlayFile_state_PlayingFile @@ -116,18 +112,14 @@ class fsm_PlayFile_state_Stopping : public fsm_PlayFile_state fsm_PlayFile_state_Stopping() {} virtual ~fsm_PlayFile_state_Stopping() {} - virtual bool Poll (); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String& sName) { sName = F("Stopping"); } virtual void Start (String& FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); private: - String FileName = ""; - uint32_t StartingElapsedTime = 0.0; - uint32_t PlayCount = 0; }; // fsm_PlayFile_state_Stopping @@ -138,13 +130,12 @@ class fsm_PlayFile_state_Error : public fsm_PlayFile_state fsm_PlayFile_state_Error() {} virtual ~fsm_PlayFile_state_Error() {} - virtual bool Poll (); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String& sName) { sName = F ("Error"); } virtual void Start (String& FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); private: diff --git a/include/input/InputFPPRemotePlayItem.hpp b/include/input/InputFPPRemotePlayItem.hpp index 6ce4c4c63..5be34eb74 100644 --- a/include/input/InputFPPRemotePlayItem.hpp +++ b/include/input/InputFPPRemotePlayItem.hpp @@ -24,32 +24,52 @@ class c_InputFPPRemotePlayItem { +protected: + time_t PlayDurationSec = 0; + bool SendFppSync = false; + +private: + bool InputPaused = false; + int32_t SyncOffsetMS = 0; + c_InputMgr::e_InputChannelIds InputChannelId = c_InputMgr::e_InputChannelIds::InputChannelId_ALL; + public: c_InputFPPRemotePlayItem (c_InputMgr::e_InputChannelIds InputChannelId); virtual ~c_InputFPPRemotePlayItem (); + struct FileControl_t + { + String FileName; + c_FileMgr::FileId FileHandleForFileBeingPlayed = c_FileMgr::INVALID_FILE_HANDLE; + uint32_t RemainingPlayCount = 0; + uint32_t DataOffset = 0; + uint32_t ChannelsPerFrame = 0; + uint32_t FrameStepTimeMS = 25; + uint32_t TotalNumberOfFramesInSequence = 0; + uint32_t ElapsedPlayTimeMS = 0; + uint32_t StartingTimeMS = 0; + uint32_t LastPollTimeMS = 0; + uint32_t LastPlayedFrameId = 0; + } FileControl[2]; + #define CurrentFile 0 + #define NextFile 1 + virtual bool Poll () = 0; virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount) = 0; virtual void Stop () = 0; + virtual void SetPauseState (bool _PauseInput) {InputPaused = _PauseInput;} virtual void Sync (String & FileName, float SecondsElapsed) = 0; virtual void GetStatus (JsonObject & jsonStatus) = 0; virtual bool IsIdle () = 0; - String GetFileName () { return PlayItemName; } - uint32_t GetRepeatCount () { return RemainingPlayCount; } + String GetFileName () { return FileControl[CurrentFile].FileName; } + uint32_t GetRepeatCount () { return FileControl[CurrentFile].RemainingPlayCount; } void SetDuration (time_t value) { PlayDurationSec = value; } void GetDriverName (String& Name) { Name = "InputMgr"; } int32_t GetSyncOffsetMS () { return SyncOffsetMS; } void SetSyncOffsetMS (int32_t value) { SyncOffsetMS = value; } void SetSendFppSync (bool value) { SendFppSync = value; } c_InputMgr::e_InputChannelIds GetInputChannelId () { return InputChannelId; } -protected: - String PlayItemName; - uint32_t RemainingPlayCount = 0; - time_t PlayDurationSec = 0; - bool SendFppSync = false; - -private: - int32_t SyncOffsetMS = 0; - c_InputMgr::e_InputChannelIds InputChannelId = c_InputMgr::e_InputChannelIds::InputChannelId_ALL; + bool InputIsPaused () { return InputPaused; } + void SetOperationalState (bool ActiveFlag) {InputPaused = !ActiveFlag;} }; // c_InputFPPRemotePlayItem diff --git a/include/input/InputMgr.hpp b/include/input/InputMgr.hpp index 820776937..8942d1549 100644 --- a/include/input/InputMgr.hpp +++ b/include/input/InputMgr.hpp @@ -27,6 +27,7 @@ #include "output/OutputMgr.hpp" #include "externalInput.h" #include +#include class c_InputCommon; ///< forward declaration to the pure virtual Input class that will be defined later. @@ -94,7 +95,7 @@ class c_InputMgr }; #define NO_CONFIG_NEEDED time_t(-1) - #define INPUTMGR_TASK_PRIORITY 6 + #define INPUTMGR_TASK_PRIORITY 5 DriverInfo_t InputChannelDrivers[InputChannelId_End]; ///< pointer(s) to the current active Input driver uint32_t InputDataBufferSize = 0; @@ -120,6 +121,10 @@ class c_InputMgr FastTimer BlankEndTime[InputChannelId_End]; +# define FPP_TICKER_PERIOD_MS 25 + Ticker MsTicker; + uint32_t LastTickerTimeStampMS = 0; + }; // c_InputMgr extern c_InputMgr InputMgr; diff --git a/include/service/FPPDiscovery.h b/include/service/FPPDiscovery.h index 07307e664..926125311 100644 --- a/include/service/FPPDiscovery.h +++ b/include/service/FPPDiscovery.h @@ -116,24 +116,25 @@ SystemDebugStats_t SystemDebugStats; void begin (); - void ProcessFPPJson (AsyncWebServerRequest* request); - void ProcessFPPDJson (AsyncWebServerRequest* request); - void ProcessGET (AsyncWebServerRequest* request); - void ProcessPOST (AsyncWebServerRequest* request); - void ProcessFile (AsyncWebServerRequest* request, String filename, uint32_t index, uint8_t* data, uint32_t len, bool final, uint32_t contentLength = 0); - void ProcessBody (AsyncWebServerRequest* request, uint8_t* data, uint32_t len, uint32_t index, uint32_t total); - void sendPingPacket (IPAddress destination = IPAddress(255, 255, 255, 255)); - void PlayFile (String & FileToPlay); - void Enable (void); - void Disable (void); - void GetStatus (JsonObject& jsonStatus); + void ProcessFPPJson (AsyncWebServerRequest* request); + void ProcessFPPDJson (AsyncWebServerRequest* request); + void ProcessGET (AsyncWebServerRequest* request); + void ProcessPOST (AsyncWebServerRequest* request); + void ProcessFile (AsyncWebServerRequest* request, String filename, uint32_t index, uint8_t* data, uint32_t len, bool final, uint32_t contentLength = 0); + void ProcessBody (AsyncWebServerRequest* request, uint8_t* data, uint32_t len, uint32_t index, uint32_t total); + void sendPingPacket (IPAddress destination = IPAddress(255, 255, 255, 255)); + void PlayFile (String & FileToPlay); + void Enable (void); + void Disable (void); + void GetStatus (JsonObject& jsonStatus); void NetworkStateChanged (bool NewNetworkState); + void SetOperationalState (bool ActiveFlag); - void SetBlankOnStop (bool value) {BlankOnStop = value;} - bool GetBlankOnStop (void) {return BlankOnStop;} - void SetInputFPPRemotePlayFile (c_InputFPPRemotePlayFile * value); + void SetBlankOnStop (bool value) {BlankOnStop = value;} + bool GetBlankOnStop (void) {return BlankOnStop;} + void SetInputFPPRemotePlayFile (c_InputFPPRemotePlayFile * value); void ForgetInputFPPRemotePlayFile (); - void GenerateFppSyncMsg (uint8_t Action, const String & FileName, uint32_t CurrentFrame, const float & ElpsedTime); + void GenerateFppSyncMsg (uint8_t Action, const String & FileName, uint32_t CurrentFrame, const float & ElpsedTime); # define SYNC_PKT_START 0 # define SYNC_PKT_STOP 1 diff --git a/src/input/InputFPPRemote.cpp b/src/input/InputFPPRemote.cpp index c2ddccd8e..6cdb789a5 100644 --- a/src/input/InputFPPRemote.cpp +++ b/src/input/InputFPPRemote.cpp @@ -287,6 +287,21 @@ bool c_InputFPPRemote::SetConfig (JsonObject& jsonConfig) return true; } // SetConfig +//----------------------------------------------------------------------------- +void c_InputFPPRemote::SetOperationalState (bool ActiveFlag) +{ + // DEBUG_START; + + if(pInputFPPRemotePlayItem) + { + pInputFPPRemotePlayItem->SetOperationalState (ActiveFlag); + } + + FPPDiscovery.SetOperationalState(ActiveFlag); + + // DEBUG_END; +} // SetOperationalState + //----------------------------------------------------------------------------- void c_InputFPPRemote::StopPlaying () { @@ -309,7 +324,7 @@ void c_InputFPPRemote::StopPlaying () Stopping = true; // DEBUG_V ("Disable FPP Discovery"); - FPPDiscovery.Disable (); + // FPPDiscovery.Disable (); FPPDiscovery.ForgetInputFPPRemotePlayFile (); if(PlayingFile()) @@ -347,6 +362,11 @@ void c_InputFPPRemote::StartPlaying (String& FileName) do // once { + if(!IsInputChannelActive) + { + break; + } + // DEBUG_V (String ("FileName: '") + FileName + "'"); if ((FileName.isEmpty ()) || (FileName.equals("null"))) diff --git a/src/input/InputFPPRemotePlayEffect.cpp b/src/input/InputFPPRemotePlayEffect.cpp index f5a5b8465..44cd67cb7 100644 --- a/src/input/InputFPPRemotePlayEffect.cpp +++ b/src/input/InputFPPRemotePlayEffect.cpp @@ -27,13 +27,10 @@ c_InputFPPRemotePlayEffect::c_InputFPPRemotePlayEffect (c_InputMgr::e_InputChann { // DEBUG_START; - // Tell input manager to not put any data into the input buffer - InputMgr.SetOperationalState (false); - fsm_PlayEffect_state_Idle_imp.Init (this); EffectsEngine.Begin (); - EffectsEngine.SetOperationalState (false); + EffectsEngine.SetOperationalState (!InputIsPaused()); // DEBUG_END; } // c_InputFPPRemotePlayEffect @@ -55,7 +52,10 @@ void c_InputFPPRemotePlayEffect::Start (String & FileName, float duration, uint3 { // DEBUG_START; - pCurrentFsmState->Start (FileName, duration); + if(!InputIsPaused()) + { + pCurrentFsmState->Start (FileName, duration); + } // DEBUG_END; } // Start @@ -65,7 +65,10 @@ void c_InputFPPRemotePlayEffect::Stop () { // DEBUG_START; - pCurrentFsmState->Stop (); + if(!InputIsPaused()) + { + pCurrentFsmState->Stop (); + } // DEBUG_END; } // Stop @@ -75,7 +78,10 @@ void c_InputFPPRemotePlayEffect::Sync (String& FileName, float SecondsElapsed) { // DEBUG_START; - pCurrentFsmState->Sync (SecondsElapsed); + if(!InputIsPaused()) + { + pCurrentFsmState->Sync (SecondsElapsed); + } // DEBUG_END; } // Sync @@ -83,11 +89,18 @@ void c_InputFPPRemotePlayEffect::Sync (String& FileName, float SecondsElapsed) //----------------------------------------------------------------------------- bool c_InputFPPRemotePlayEffect::Poll () { - // DEBUG_START; + /// DEBUG_START; - return pCurrentFsmState->Poll (); + bool Response = false; - // DEBUG_END; + if(!InputIsPaused()) + { + // Show that we have received a poll + Response = pCurrentFsmState->Poll (); + } + + /// DEBUG_END; + return Response; } // Poll diff --git a/src/input/InputFPPRemotePlayFile.cpp b/src/input/InputFPPRemotePlayFile.cpp index 8cf0b6b89..3c4b32118 100644 --- a/src/input/InputFPPRemotePlayFile.cpp +++ b/src/input/InputFPPRemotePlayFile.cpp @@ -23,42 +23,6 @@ #include "service/fseq.h" #include "utility/SaferStringConversion.hpp" -//----------------------------------------------------------------------------- -static void TimerPollHandler (void * p) -{ -#ifdef ARDUINO_ARCH_ESP32 - TaskHandle_t Handle = reinterpret_cast (p)->GetTaskHandle (); - if (Handle) - { - vTaskResume (Handle); - } -#else - reinterpret_cast(p)->TimerPoll (); -#endif // def ARDUINO_ARCH_ESP32 - -} // TimerPollHandler - -#ifdef ARDUINO_ARCH_ESP32 -//---------------------------------------------------------------------------- -static void TimerPollHandlerTask (void* pvParameters) -{ - // DEBUG_START; // Need extra stack space to run this - c_InputFPPRemotePlayFile* InputFpp = reinterpret_cast (pvParameters); - - do - { - // we start suspended - vTaskSuspend (NULL); //Suspend Own Task - InputFpp->TimerPollInProgress = true; - // DEBUG_V (""); - InputFpp->TimerPoll (); - InputFpp->TimerPollInProgress = false; - } while (true); - // DEBUG_END; - -} // TimerPollHandlerTask -#endif // def ARDUINO_ARCH_ESP32 - //----------------------------------------------------------------------------- c_InputFPPRemotePlayFile::c_InputFPPRemotePlayFile (c_InputMgr::e_InputChannelIds InputChannelId) : c_InputFPPRemotePlayItem (InputChannelId) @@ -67,13 +31,6 @@ c_InputFPPRemotePlayFile::c_InputFPPRemotePlayFile (c_InputMgr::e_InputChannelId fsm_PlayFile_state_Idle_imp.Init (this); - LastIsrTimeStampMS = millis (); - MsTicker.attach_ms (uint32_t (FPP_TICKER_PERIOD_MS), &TimerPollHandler, (void*)this); // Add ISR Function - -#ifdef ARDUINO_ARCH_ESP32 - xTaskCreate (TimerPollHandlerTask, "FPPTask", TimerPollHandlerTaskStack, this, ESP_TASK_PRIO_MIN + 8, &TimerPollTaskHandle); -#endif // def ARDUINO_ARCH_ESP32 - // DEBUG_END; } // c_InputFPPRemotePlayFile @@ -81,25 +38,13 @@ c_InputFPPRemotePlayFile::c_InputFPPRemotePlayFile (c_InputMgr::e_InputChannelId c_InputFPPRemotePlayFile::~c_InputFPPRemotePlayFile () { // DEBUG_START; - MsTicker.detach (); - -#ifdef ARDUINO_ARCH_ESP32 - if (NULL != TimerPollTaskHandle) - { - // DEBUG_V("wait for the timer task to finish"); - while(TimerPollInProgress == true) {yield();} - - // DEBUG_V("Delete the task"); - vTaskDelete (TimerPollTaskHandle); - TimerPollTaskHandle = NULL; - } -#endif // def ARDUINO_ARCH_ESP32 for (uint32_t LoopCount = 10000; (LoopCount != 0) && (!IsIdle ()); LoopCount--) { Stop (); Poll (); } + // DEBUG_END; } // ~c_InputFPPRemotePlayFile @@ -108,13 +53,15 @@ c_InputFPPRemotePlayFile::~c_InputFPPRemotePlayFile () void c_InputFPPRemotePlayFile::Start (String & FileName, float SecondsElapsed, uint32_t PlayCount) { // DEBUG_START; - if (FileMgr.SdCardIsInstalled ()) + + if (!InputIsPaused() && FileMgr.SdCardIsInstalled ()) { + // DEBUG_V("Ask FSM to start the sequence."); pCurrentFsmState->Start (FileName, SecondsElapsed, PlayCount); } else { - // DEBUG_V ("No SD Card installed. Ignore Start request"); + // DEBUG_V ("Paused or No SD Card installed. Ignore Start request"); fsm_PlayFile_state_Idle_imp.Init (this); } @@ -126,7 +73,10 @@ void c_InputFPPRemotePlayFile::Stop () { // DEBUG_START; - pCurrentFsmState->Stop (); + if(!InputIsPaused()) + { + pCurrentFsmState->Stop (); + } // DEBUG_END; } // Stop @@ -136,11 +86,14 @@ void c_InputFPPRemotePlayFile::Sync (String & FileName, float SecondsElapsed) { // DEBUG_START; - SyncControl.SyncCount++; - UpdateElapsedPlayTimeMS (); - if (pCurrentFsmState->Sync (FileName, SecondsElapsed)) + if(!InputIsPaused()) { - SyncControl.SyncAdjustmentCount++; + SyncControl.SyncCount++; + UpdateElapsedPlayTimeMS (); + if (pCurrentFsmState->Sync (FileName, SecondsElapsed)) + { + SyncControl.SyncAdjustmentCount++; + } } // DEBUG_END; @@ -151,32 +104,18 @@ void c_InputFPPRemotePlayFile::Sync (String & FileName, float SecondsElapsed) bool c_InputFPPRemotePlayFile::Poll () { // xDEBUG_START; + bool Response = false; - // Show that we have received a poll - PollDetectionCounter = 0; - - // TimerPoll (); - return pCurrentFsmState->Poll (); - - // xDEBUG_END; - -} // Poll - -//----------------------------------------------------------------------------- -void c_InputFPPRemotePlayFile::TimerPoll () -{ - // xDEBUG_START; - - // Are polls still coming in? - if (PollDetectionCounter < PollDetectionCounterLimit) + if(!InputIsPaused()) { - PollDetectionCounter++; - UpdateElapsedPlayTimeMS (); - pCurrentFsmState->TimerPoll (); + // xDEBUG_V("Poll the FSM"); + Response = pCurrentFsmState->Poll (); } + // xDEBUG_END; + return Response; -} // TimerPoll +} // Poll //----------------------------------------------------------------------------- void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) @@ -188,9 +127,9 @@ void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) // variables ending in "Rem" reflect remaining play time // File uses milliseconds to store elapsed and total play time - uint32_t mseconds = FrameControl.ElapsedPlayTimeMS; + uint32_t mseconds = FileControl[CurrentFile].ElapsedPlayTimeMS; uint32_t msecondsTotal; - if (__builtin_mul_overflow(FrameControl.FrameStepTimeMS, FrameControl.TotalNumberOfFramesInSequence, &msecondsTotal)) { + if (__builtin_mul_overflow(FileControl[CurrentFile].FrameStepTimeMS, FileControl[CurrentFile].TotalNumberOfFramesInSequence, &msecondsTotal)) { // returned non-zero: there has been an overflow msecondsTotal = MilliSecondsInASecond; // set to one second total when overflow occurs } @@ -219,7 +158,7 @@ void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) // After inserting the total seconds and total seconds remaining, // JsonStatus also includes formatted "minutes + seconds" for both - // timeElapsed and timeRemaining + // time Elapsed and time Remaining char buf[12]; ESP_ERROR_CHECK(saferSecondsToFormattedMinutesAndSecondsString(buf, secs)); JsonStatus[CN_time_elapsed] = buf; @@ -235,20 +174,20 @@ void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) //----------------------------------------------------------------------------- void c_InputFPPRemotePlayFile::UpdateElapsedPlayTimeMS () { - noInterrupts (); + // noInterrupts (); uint32_t now = millis (); - uint32_t elapsedMS = now - LastIsrTimeStampMS; - if (now < LastIsrTimeStampMS) + uint32_t elapsedMS = now - FileControl[CurrentFile].LastPollTimeMS; + if (now < FileControl[CurrentFile].LastPollTimeMS) { // handle wrap - elapsedMS = (0 - LastIsrTimeStampMS) + now; + elapsedMS = (0 - FileControl[CurrentFile].LastPollTimeMS) + now; } - LastIsrTimeStampMS = now; - FrameControl.ElapsedPlayTimeMS += elapsedMS; + FileControl[CurrentFile].LastPollTimeMS = now; + FileControl[CurrentFile].ElapsedPlayTimeMS += elapsedMS; - interrupts (); + // interrupts (); } // UpdateElapsedPlayTimeMS //----------------------------------------------------------------------------- @@ -267,7 +206,7 @@ uint32_t c_InputFPPRemotePlayFile::CalculateFrameId (uint32_t ElapsedMS, int32_t break; } - CurrentFrameId = (AdjustedPlayTime / FrameControl.FrameStepTimeMS); + CurrentFrameId = (AdjustedPlayTime / FileControl[CurrentFile].FrameStepTimeMS); // DEBUG_V (String (" CurrentFrameId: ") + String (CurrentFrameId)); } while (false); @@ -289,23 +228,23 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () FSEQRawHeader fsqRawHeader; FSEQParsedHeader fsqParsedHeader; - if(c_FileMgr::INVALID_FILE_HANDLE != FileHandleForFileBeingPlayed) + if(c_FileMgr::INVALID_FILE_HANDLE != FileControl[CurrentFile].FileHandleForFileBeingPlayed) { // DEBUG_V("Unexpected File Handle at fseq Parse."); - Stop(); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); } - if (false == FileMgr.OpenSdFile (PlayItemName, + if (false == FileMgr.OpenSdFile (FileControl[CurrentFile].FileName, c_FileMgr::FileMode::FileRead, - FileHandleForFileBeingPlayed, -1)) + FileControl[CurrentFile].FileHandleForFileBeingPlayed, -1)) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not open file: filename: '")) + PlayItemName + "'"); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not open file: filename: '")) + FileControl[CurrentFile].FileName + "'"); logcon (LastFailedPlayStatusMsg); break; } - // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (FileHandleForFileBeingPlayed)); - uint32_t BytesRead = FileMgr.ReadSdFile (FileHandleForFileBeingPlayed, + // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (FileControl[CurrentFile].FileHandleForFileBeingPlayed)); + uint32_t BytesRead = FileMgr.ReadSdFile (FileControl[CurrentFile].FileHandleForFileBeingPlayed, (uint8_t*)&fsqRawHeader, sizeof (fsqRawHeader), size_t(0)); // DEBUG_V (String (" BytesRead: ") + String (BytesRead)); @@ -313,9 +252,9 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () if (BytesRead != sizeof (fsqRawHeader)) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not read FSEQ header: filename: '")) + PlayItemName + "'"); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not read FSEQ header: filename: '")) + FileControl[CurrentFile].FileName + "'"); logcon (LastFailedPlayStatusMsg); - FileMgr.CloseSdFile(FileHandleForFileBeingPlayed); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } @@ -337,62 +276,63 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () // #define DUMP_FSEQ_HEADER #ifdef DUMP_FSEQ_HEADER - DEBUG_V (String (" dataOffset: ") + String (fsqParsedHeader.dataOffset)); - DEBUG_V (String (" minorVersion: ") + String (fsqParsedHeader.minorVersion)); - DEBUG_V (String (" majorVersion: ") + String (fsqParsedHeader.majorVersion)); - DEBUG_V (String (" VariableHdrOffset: ") + String (fsqParsedHeader.VariableHdrOffset)); - DEBUG_V (String (" channelCount: ") + String (fsqParsedHeader.channelCount)); - DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (fsqParsedHeader.TotalNumberOfFramesInSequence)); - DEBUG_V (String (" stepTime: ") + String (fsqParsedHeader.stepTime)); - DEBUG_V (String (" flags: ") + String (fsqParsedHeader.flags)); - DEBUG_V (String (" compressionType: 0x") + String (fsqParsedHeader.compressionType, HEX)); - DEBUG_V (String (" numCompressedBlocks: ") + String (fsqParsedHeader.numCompressedBlocks)); - DEBUG_V (String (" numSparseRanges: ") + String (fsqParsedHeader.numSparseRanges)); - DEBUG_V (String (" flags2: ") + String (fsqParsedHeader.flags2)); - DEBUG_V (String (" id: 0x") + String ((unsigned long)fsqParsedHeader.id, HEX)); + // DEBUG_V (String (" dataOffset: ") + String (fsqParsedHeader.dataOffset)); + // DEBUG_V (String (" minorVersion: ") + String (fsqParsedHeader.minorVersion)); + // DEBUG_V (String (" majorVersion: ") + String (fsqParsedHeader.majorVersion)); + // DEBUG_V (String (" VariableHdrOffset: ") + String (fsqParsedHeader.VariableHdrOffset)); + // DEBUG_V (String (" channelCount: ") + String (fsqParsedHeader.channelCount)); + // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (fsqParsedHeader.TotalNumberOfFramesInSequence)); + // DEBUG_V (String (" stepTime: ") + String (fsqParsedHeader.stepTime)); + // DEBUG_V (String (" flags: ") + String (fsqParsedHeader.flags)); + // DEBUG_V (String (" compressionType: 0x") + String (fsqParsedHeader.compressionType, HEX)); + // DEBUG_V (String (" numCompressedBlocks: ") + String (fsqParsedHeader.numCompressedBlocks)); + // DEBUG_V (String (" numSparseRanges: ") + String (fsqParsedHeader.numSparseRanges)); + // DEBUG_V (String (" flags2: ") + String (fsqParsedHeader.flags2)); + // DEBUG_V (String (" id: 0x") + String ((unsigned long)fsqParsedHeader.id, HEX)); #endif // def DUMP_FSEQ_HEADER if (fsqParsedHeader.majorVersion != 2 || fsqParsedHeader.compressionType != 0) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + PlayItemName + F (" is not a v2 uncompressed sequence")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + FileControl[CurrentFile].FileName + F (" is not a v2 uncompressed sequence")); logcon (LastFailedPlayStatusMsg); - FileMgr.CloseSdFile(FileHandleForFileBeingPlayed); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } // DEBUG_V (""); - size_t ActualDataSize = FileMgr.GetSdFileSize (FileHandleForFileBeingPlayed) - sizeof(fsqParsedHeader); + size_t ActualDataSize = FileMgr.GetSdFileSize (FileControl[CurrentFile].FileHandleForFileBeingPlayed) - sizeof(fsqParsedHeader); size_t NeededDataSize = fsqParsedHeader.TotalNumberOfFramesInSequence * fsqParsedHeader.channelCount; // DEBUG_V("NeededDataSize: " + String(NeededDataSize)); // DEBUG_V("ActualDataSize: " + String(ActualDataSize)); if (NeededDataSize > ActualDataSize) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start: ")) + PlayItemName + + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start: ")) + FileControl[CurrentFile].FileName + F (" File does not contain enough data to meet the Stated Channel Count * Number of Frames value. Need: ") + String (NeededDataSize) + F (", SD File Size: ") + String (ActualDataSize)); logcon (LastFailedPlayStatusMsg); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } - FrameControl.FrameStepTimeMS = max ((uint8_t)25, fsqParsedHeader.stepTime); - FrameControl.TotalNumberOfFramesInSequence = fsqParsedHeader.TotalNumberOfFramesInSequence; + FileControl[CurrentFile].FrameStepTimeMS = max ((uint8_t)25, fsqParsedHeader.stepTime); + FileControl[CurrentFile].TotalNumberOfFramesInSequence = fsqParsedHeader.TotalNumberOfFramesInSequence; - FrameControl.DataOffset = fsqParsedHeader.dataOffset; - FrameControl.ChannelsPerFrame = fsqParsedHeader.channelCount; + FileControl[CurrentFile].DataOffset = fsqParsedHeader.dataOffset; + FileControl[CurrentFile].ChannelsPerFrame = fsqParsedHeader.channelCount; memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); if (fsqParsedHeader.numSparseRanges) { if (MAX_NUM_SPARSE_RANGES < fsqParsedHeader.numSparseRanges) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + PlayItemName + F (" Too many sparse ranges defined in file header.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + FileControl[CurrentFile].FileName + F (" Too many sparse ranges defined in file header.")); logcon (LastFailedPlayStatusMsg); - FileMgr.CloseSdFile(FileHandleForFileBeingPlayed); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } FSEQRawRangeEntry FseqRawRanges[MAX_NUM_SPARSE_RANGES]; - FileMgr.ReadSdFile (FileHandleForFileBeingPlayed, + FileMgr.ReadSdFile (FileControl[CurrentFile].FileHandleForFileBeingPlayed, (uint8_t*)&FseqRawRanges[0], sizeof (FseqRawRanges), sizeof (FSEQRawHeader) + fsqParsedHeader.numCompressedBlocks * 8); @@ -430,7 +370,7 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () #endif // def DUMP_FSEQ_HEADER if (0 == TotalChannels) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + PlayItemName + F (" No channels defined in Sparse Ranges.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + FileControl[CurrentFile].FileName + F (" No channels defined in Sparse Ranges.")); logcon (LastFailedPlayStatusMsg); memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); SparseRanges[0].ChannelCount = fsqParsedHeader.channelCount; @@ -438,7 +378,7 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () else if (TotalChannels > fsqParsedHeader.channelCount) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + PlayItemName + F (" Too many channels defined in Sparse Ranges.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + FileControl[CurrentFile].FileName + F (" Too many channels defined in Sparse Ranges.")); logcon (LastFailedPlayStatusMsg); memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); SparseRanges[0].ChannelCount = fsqParsedHeader.channelCount; @@ -446,7 +386,7 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () else if (LargestBlock > fsqParsedHeader.channelCount) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + PlayItemName + F (" Sparse Range Frame offset + Num channels is larger than frame size.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + FileControl[CurrentFile].FileName + F (" Sparse Range Frame offset + Num channels is larger than frame size.")); logcon (LastFailedPlayStatusMsg); memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); SparseRanges[0].ChannelCount = fsqParsedHeader.channelCount; @@ -475,34 +415,34 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () void c_InputFPPRemotePlayFile::ClearFileInfo() { // DEBUG_START; - PlayItemName = emptyString; - RemainingPlayCount = 0; - SyncControl.LastRcvdElapsedSeconds = 0.0; - FrameControl.ElapsedPlayTimeMS = 0; - FrameControl.DataOffset = 0; - FrameControl.ChannelsPerFrame = 0; - FrameControl.FrameStepTimeMS = 25; - FrameControl.TotalNumberOfFramesInSequence = 0; + FileControl[NextFile].FileName = emptyString; + FileControl[NextFile].RemainingPlayCount = 0; + SyncControl.LastRcvdElapsedSeconds = 0.0; + FileControl[NextFile].ElapsedPlayTimeMS = 0; + FileControl[NextFile].DataOffset = 0; + FileControl[NextFile].ChannelsPerFrame = 0; + FileControl[NextFile].FrameStepTimeMS = 25; + FileControl[NextFile].TotalNumberOfFramesInSequence = 0; // DEBUG_END; } // ClearFileInfo +//----------------------------------------------------------------------------- uint32_t c_InputFPPRemotePlayFile::ReadFile(uint32_t DestinationIntensityId, uint32_t NumBytesToRead, uint32_t FileOffset) { // DEBUG_START; -// #define WRITE_DIRECT_TO_OUTPUT_BUFFER -#ifdef WRITE_DIRECT_TO_OUTPUT_BUFFER - uint32_t NumBytesRead = FileMgr.ReadSdFile(FileHandleForFileBeingPlayed, - OutputMgr.GetBufferAddress(), - min((NumBytesToRead), OutputMgr.GetBufferUsedSize()), - FileOffset); -#else + + if(c_FileMgr::INVALID_FILE_HANDLE == FileControl[CurrentFile].FileHandleForFileBeingPlayed) + { + // DEBUG_V(String("FileHandleForFileBeingPlayed: ") + String(FileControl[CurrentFile].FileHandleForFileBeingPlayed)); + } + uint8_t LocalIntensityBuffer[200]; uint32_t NumBytesRead = 0; while (NumBytesRead < NumBytesToRead) { - uint32_t NumBytesReadThisPass = FileMgr.ReadSdFile(FileHandleForFileBeingPlayed, + uint32_t NumBytesReadThisPass = FileMgr.ReadSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed, LocalIntensityBuffer, min((NumBytesToRead - NumBytesRead), sizeof(LocalIntensityBuffer)), FileOffset); @@ -513,7 +453,6 @@ uint32_t c_InputFPPRemotePlayFile::ReadFile(uint32_t DestinationIntensityId, uin NumBytesRead += NumBytesReadThisPass; DestinationIntensityId += NumBytesReadThisPass; } -#endif // !def WRITE_DIRECT_TO_OUTPUT_BUFFER // DEBUG_END; return NumBytesRead; diff --git a/src/input/InputFPPRemotePlayFileFsm.cpp b/src/input/InputFPPRemotePlayFileFsm.cpp index 3ace1b170..aa3bd17b1 100644 --- a/src/input/InputFPPRemotePlayFileFsm.cpp +++ b/src/input/InputFPPRemotePlayFileFsm.cpp @@ -25,35 +25,30 @@ //----------------------------------------------------------------------------- bool fsm_PlayFile_state_Idle::Poll () { - // DEBUG_START; - - // DEBUG_V("fsm_PlayFile_state_Idle::Poll"); + // xDEBUG_START; + // xDEBUG_V("fsm_PlayFile_state_Idle::Poll"); - // do nothing + // is there a new file to play? + if(!p_Parent->FileControl[NextFile].FileName.isEmpty()) + { + p_Parent->fsm_PlayFile_state_Starting_imp.Init (p_Parent); + } - // DEBUG_END; + // xDEBUG_END; return false; } // fsm_PlayFile_state_Idle::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Idle::TimerPoll () -{ - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; - -} // fsm_PlayFile_state_Idle::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Idle::Init (c_InputFPPRemotePlayFile* Parent) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Idle::Init"); - // DEBUG_V (String (" Parent: 0x") + String ((uint32_t)Parent, HEX)); + // DEBUG_V (String ("Parent: 0x") + String ((uint32_t)Parent, HEX)); p_Parent = Parent; - p_Parent->pCurrentFsmState = &(p_Parent->fsm_PlayFile_state_Idle_imp); p_Parent->ClearFileInfo (); + p_Parent->pCurrentFsmState = &(p_Parent->fsm_PlayFile_state_Idle_imp); // DEBUG_END; @@ -64,18 +59,19 @@ void fsm_PlayFile_state_Idle::Start (String& FileName, float ElapsedSeconds, uin { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Idle::Start"); - // DEBUG_V (String ("FileName: ") + FileName); - p_Parent->PlayItemName = FileName; - p_Parent->FrameControl.ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000); - p_Parent->RemainingPlayCount = RemainingPlayCount; + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; - // DEBUG_V (String (" FileName: ") + p_Parent->PlayItemName); - // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FrameControl.ElapsedPlayTimeMS); - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - - p_Parent->fsm_PlayFile_state_Starting_imp.Init (p_Parent); + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); // DEBUG_END; @@ -97,7 +93,7 @@ void fsm_PlayFile_state_Idle::Stop (void) bool fsm_PlayFile_state_Idle::Sync (String& FileName, float ElapsedSeconds) { // DEBUG_START; - // DEBUG_V("State: Idle"); + // DEBUG_V("fsm_PlayFile_state_Idle::Sync"); Start (FileName, ElapsedSeconds, 1); @@ -113,23 +109,41 @@ bool fsm_PlayFile_state_Idle::Sync (String& FileName, float ElapsedSeconds) bool fsm_PlayFile_state_Starting::Poll () { // DEBUG_START; + // DEBUG_V("fsm_PlayFile_state_Starting::Poll"); + + do // once + { + p_Parent->FileControl[CurrentFile] = p_Parent->FileControl[NextFile]; + p_Parent->ClearFileInfo(); - p_Parent->fsm_PlayFile_state_PlayingFile_imp.Init (p_Parent); - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->FrameControl.TotalNumberOfFramesInSequence)); + if (!p_Parent->ParseFseqFile ()) + { + // DEBUG_V("fsm_PlayFile_state_PlayingFile::Poll FSEQ Parse Error"); + break; + } + + p_Parent->FileControl[CurrentFile].RemainingPlayCount --; + p_Parent->FileControl[CurrentFile].LastPollTimeMS = millis(); + p_Parent->FileControl[CurrentFile].StartingTimeMS = p_Parent->FileControl[CurrentFile].LastPollTimeMS - p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS; + p_Parent->FileControl[CurrentFile].LastPlayedFrameId = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[CurrentFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[CurrentFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[CurrentFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + // DEBUG_V (String (" LastPlayedFrameId: ") + p_Parent->FileControl[CurrentFile].LastPlayedFrameId); + // DEBUG_V (String ("NumberOfFramesInSequence: ") + p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence); + + p_Parent->fsm_PlayFile_state_PlayingFile_imp.Init (p_Parent); + + } while (false); // DEBUG_END; return true; } // fsm_PlayFile_state_Starting::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Starting::TimerPoll () -{ - // nothing to do - -} // fsm_PlayFile_state_Starting::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Starting::Init (c_InputFPPRemotePlayFile* Parent) { @@ -154,11 +168,19 @@ void fsm_PlayFile_state_Starting::Start (String& FileName, float ElapsedSeconds, // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Starting::Start"); - // DEBUG_V (String ("FileName: ") + FileName); - p_Parent->PlayItemName = FileName; - p_Parent->FrameControl.ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000); - p_Parent->RemainingPlayCount = RemainingPlayCount; - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); + + p_Parent->fsm_PlayFile_state_Idle_imp.Init(p_Parent); // DEBUG_END; @@ -170,7 +192,7 @@ void fsm_PlayFile_state_Starting::Stop (void) // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Starting::Stop"); - p_Parent->RemainingPlayCount = 0; + p_Parent->FileControl[CurrentFile].RemainingPlayCount = 0; p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); // DEBUG_END; @@ -181,7 +203,7 @@ void fsm_PlayFile_state_Starting::Stop (void) bool fsm_PlayFile_state_Starting::Sync (String& FileName, float ElapsedSeconds) { // DEBUG_START; - // DEBUG_V("State:Starting"); + // DEBUG_V("fsm_PlayFile_state_Starting::Sync"); bool response = false; @@ -203,90 +225,74 @@ bool fsm_PlayFile_state_PlayingFile::Poll () do // once { - if(c_FileMgr::INVALID_FILE_HANDLE == p_Parent->FileHandleForFileBeingPlayed) + if(c_FileMgr::INVALID_FILE_HANDLE == p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed) { // DEBUG_V("Bad FileHandleForFileBeingPlayed"); Stop(); break; } - // DEBUG_V (String ("LastPlayedFrameId: ") + String (LastPlayedFrameId)); + + p_Parent->UpdateElapsedPlayTimeMS(); + uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); + + // xDEBUG_V (String ("LastPlayedFrameId: ") + String (CurrentFrame)); // have we reached the end of the file? - if (p_Parent->FrameControl.TotalNumberOfFramesInSequence <= LastPlayedFrameId) + if (p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence <= CurrentFrame) { - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - if (0 != p_Parent->RemainingPlayCount) + // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + if (0 != p_Parent->FileControl[CurrentFile].RemainingPlayCount) { - // DEBUG_V (String ("RemainingPlayCount: ") + String (p_Parent->RemainingPlayCount)); + // DEBUG_V (String (" Restart Playing:: FileName: '") + p_Parent->GetFileName () + "'"); + // DEBUG_V (String ("RemainingPlayCount: ") + String (p_Parent->FileControl[CurrentFile].RemainingPlayCount)); // DEBUG_V (String ("Replaying:: FileName: '") + p_Parent->GetFileName () + "'"); - --p_Parent->RemainingPlayCount; - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - LastPlayedFrameId = 0; + --p_Parent->FileControl[CurrentFile].RemainingPlayCount; + // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS = 0; + p_Parent->FileControl[CurrentFile].RemainingPlayCount --; + p_Parent->FileControl[CurrentFile].LastPollTimeMS = millis(); + p_Parent->FileControl[CurrentFile].StartingTimeMS = p_Parent->FileControl[CurrentFile].LastPollTimeMS; + p_Parent->FileControl[CurrentFile].LastPlayedFrameId = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[CurrentFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[CurrentFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[CurrentFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + // DEBUG_V (String (" LastPlayedFrameId: ") + p_Parent->FileControl[CurrentFile].LastPlayedFrameId); + // DEBUG_V (String ("NumberOfFramesInSequence: ") + p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence); } else { - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // DEBUG_V (String (" Done Playing:: FileName: '") + p_Parent->GetFileName () + "'"); - p_Parent->Stop (); + // xDEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); + // DEBUG_V (String (" Done Playing:: FileName: '") + p_Parent->FileControl[CurrentFile].FileName + "'"); + Stop (); Response = true; break; } - } - // DEBUG_V(); - InputMgr.RestartBlankTimer (p_Parent->GetInputChannelId ()); - - } while (false); - - // xDEBUG_END; - return Response; - -} // fsm_PlayFile_state_PlayingFile::Poll - -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_PlayingFile::TimerPoll () -{ - // xDEBUG_START; - - do // once - { - if(c_FileMgr::INVALID_FILE_HANDLE == p_Parent->FileHandleForFileBeingPlayed) - { - // DEBUG_V("Bad FileHandleForFileBeingPlayed"); - Stop(); break; } - uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FrameControl.ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); - - // xDEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // xDEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); - - // have we reached the end of the file? - if (p_Parent->FrameControl.TotalNumberOfFramesInSequence <= CurrentFrame) - { - LastPlayedFrameId = CurrentFrame; - break; - } - - if (CurrentFrame == LastPlayedFrameId) + // Do we need to do an update? + if (CurrentFrame == p_Parent->FileControl[CurrentFile].LastPlayedFrameId) { // xDEBUG_V (String ("keep waiting")); break; } + p_Parent->FileControl[CurrentFile].LastPlayedFrameId = CurrentFrame; - uint32_t FilePosition = p_Parent->FrameControl.DataOffset + (p_Parent->FrameControl.ChannelsPerFrame * CurrentFrame); + uint32_t FilePosition = p_Parent->FileControl[CurrentFile].DataOffset + (p_Parent->FileControl[CurrentFile].ChannelsPerFrame * CurrentFrame); uint32_t BufferSize = OutputMgr.GetBufferUsedSize(); - uint32_t MaxBytesToRead = (p_Parent->FrameControl.ChannelsPerFrame > BufferSize) ? BufferSize : p_Parent->FrameControl.ChannelsPerFrame; + uint32_t MaxBytesToRead = (p_Parent->FileControl[CurrentFile].ChannelsPerFrame > BufferSize) ? BufferSize : p_Parent->FileControl[CurrentFile].ChannelsPerFrame; uint32_t CurrentDestination = 0; // xDEBUG_V (String (" MaxBytesToRead: ") + String (MaxBytesToRead)); - LastPlayedFrameId = CurrentFrame; + InputMgr.RestartBlankTimer (p_Parent->GetInputChannelId ()); if(p_Parent->SendFppSync) { - FPPDiscovery.GenerateFppSyncMsg(SYNC_PKT_SYNC, p_Parent->GetFileName(), CurrentFrame, float(p_Parent->FrameControl.ElapsedPlayTimeMS) / 1000.0); + FPPDiscovery.GenerateFppSyncMsg(SYNC_PKT_SYNC, p_Parent->GetFileName(), CurrentFrame, float(p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS) / 1000.0); } for (auto& CurrentSparseRange : p_Parent->SparseRanges) @@ -300,10 +306,10 @@ IRAM_ATTR void fsm_PlayFile_state_PlayingFile::TimerPoll () uint32_t AdjustedFilePosition = FilePosition + CurrentSparseRange.DataOffset; - /// DEBUG_V (String (" FilePosition: ") + String (FilePosition)); - /// DEBUG_V (String (" AdjustedFilePosition: ") + String (uint32_t(AdjustedFilePosition), HEX)); - /// DEBUG_V (String (" CurrentDestination: ") + String (uint32_t(CurrentDestination), HEX)); - /// DEBUG_V (String (" ActualBytesToRead: ") + String (ActualBytesToRead)); + // xDEBUG_V (String (" FilePosition: ") + String (FilePosition)); + // xDEBUG_V (String (" AdjustedFilePosition: ") + String (uint32_t(AdjustedFilePosition), HEX)); + // xDEBUG_V (String (" CurrentDestination: ") + String (uint32_t(CurrentDestination), HEX)); + // xDEBUG_V (String (" ActualBytesToRead: ") + String (ActualBytesToRead)); uint32_t ActualBytesRead = p_Parent->ReadFile(CurrentDestination, ActualBytesToRead, AdjustedFilePosition); MaxBytesToRead -= ActualBytesRead; @@ -311,24 +317,19 @@ IRAM_ATTR void fsm_PlayFile_state_PlayingFile::TimerPoll () if (ActualBytesRead != ActualBytesToRead) { - // xDEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // xDEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); - + // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence)); + // DEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); // DEBUG_V (F ("File Playback Failed to read enough data")); - p_Parent->Stop (); + Stop (); } } - // xDEBUG_V (String (" DataOffset: ") + String (p_Parent->DataOffset)); - // xDEBUG_V (String (" BufferSize: ") + String (p_Parent->BufferSize)); - // xDEBUG_V (String (" ChannelsPerFrame: ") + String (p_Parent->ChannelsPerFrame)); - // xDEBUG_V (String (" FilePosition: ") + String (FilePosition)); - // xDEBUG_V (String (" MaxBytesToRead: ") + String (MaxBytesToRead)); - // xDEBUG_V (String ("GetInputChannelId: ") + String (p_Parent->GetInputChannelId ())); - } while (false); -} // fsm_PlayFile_state_PlayingFile::TimerPoll + // xDEBUG_END; + return Response; + +} // fsm_PlayFile_state_PlayingFile::Poll //----------------------------------------------------------------------------- void fsm_PlayFile_state_PlayingFile::Init (c_InputFPPRemotePlayFile* Parent) @@ -338,59 +339,35 @@ void fsm_PlayFile_state_PlayingFile::Init (c_InputFPPRemotePlayFile* Parent) p_Parent = Parent; - do // once - { - LastPlayedFrameId = 0; - - // DEBUG_V (String ("FileName: '") + p_Parent->PlayItemName + "'"); - // DEBUG_V (String (" FrameId: '") + p_Parent->LastPlayedFrameId + "'"); - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - if (0 == p_Parent->RemainingPlayCount) - { - // DEBUG_V(); - p_Parent->Stop (); - break; - } - - --p_Parent->RemainingPlayCount; - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - - - if (!p_Parent->ParseFseqFile ()) - { - p_Parent->fsm_PlayFile_state_Error_imp.Init (p_Parent); - break; - } - - // DEBUG_V (String (" LastPlayedFrameId: ") + String (p_Parent->LastPlayedFrameId)); - // DEBUG_V (String (" StartTimeMS: ") + String (p_Parent->StartTimeMS)); - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - - // DEBUG_V (String (F ("Start Playing:: FileName: '")) + p_Parent->PlayItemName + "'"); - - Parent->pCurrentFsmState = &(Parent->fsm_PlayFile_state_PlayingFile_imp); - Parent->FrameControl.ElapsedPlayTimeMS = 0; - - } while (false); + // LastPlayedFrameId = 0; + Parent->pCurrentFsmState = &(Parent->fsm_PlayFile_state_PlayingFile_imp); // DEBUG_END; } // fsm_PlayFile_state_PlayingFile::Init //----------------------------------------------------------------------------- -void fsm_PlayFile_state_PlayingFile::Start (String& FileName, float ElapsedSeconds, uint32_t PlayCount) +void fsm_PlayFile_state_PlayingFile::Start (String& FileName, float ElapsedSeconds, uint32_t RemainingPlayCount) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_PlayingFile::Start"); - // DEBUG_V (String (" FileName: ") + FileName); - // DEBUG_V (String (" LastPlayedFrameId: ") + String (p_Parent->LastPlayedFrameId)); - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - // DEBUG_V(); - p_Parent->Stop (); - // DEBUG_V(); - p_Parent->Start (FileName, ElapsedSeconds, PlayCount); + // DEBUG_V("Set up a next file"); + + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); + + // DEBUG_V("Stop old file"); + Stop (); // DEBUG_END; @@ -402,16 +379,11 @@ void fsm_PlayFile_state_PlayingFile::Stop (void) // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_PlayingFile::Stop"); - // DEBUG_V (String (F ("Stop Playing:: FileName: '")) + p_Parent->PlayItemName + "'"); - // DEBUG_V (String (" LastPlayedFrameId: ") + String (p_Parent->LastPlayedFrameId)); - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); + // DEBUG_V (String (F ("Stop Playing:: FileName: '")) + p_Parent->FileControl[CurrentFile].FileName + "'"); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); p_Parent->fsm_PlayFile_state_Stopping_imp.Init (p_Parent); - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - LastPlayedFrameId = 0; - // DEBUG_END; } // fsm_PlayFile_state_PlayingFile::Stop @@ -419,7 +391,9 @@ void fsm_PlayFile_state_PlayingFile::Stop (void) //----------------------------------------------------------------------------- bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSeconds) { - // DEBUG_START; + // xDEBUG_START; + // xDEBUG_V("fsm_PlayFile_state_PlayingFile::Sync"); + bool response = false; do // once @@ -427,9 +401,7 @@ bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSecond // are we on the correct file? if (!FileName.equals(p_Parent->GetFileName ())) { - // DEBUG_V ("Sync: Filename change"); - p_Parent->Stop (); - // DEBUG_V(); + // DEBUG_V ("Sync: Filename change: Start"); p_Parent->Start (FileName, ElapsedSeconds, 1); break; } @@ -440,56 +412,59 @@ bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSecond break; } - // DEBUG_V (String ("old LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); + // xDEBUG_V (String ("old LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); p_Parent->SyncControl.LastRcvdElapsedSeconds = ElapsedSeconds; - // DEBUG_V (String ("new LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); - // DEBUG_V (String (" ElapsedPlayTimeMS: ") + String (p_Parent->FrameControl.ElapsedPlayTimeMS)); + // xDEBUG_V (String ("new LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); + // xDEBUG_V (String (" ElapsedPlayTimeMS: ") + String (p_Parent->FileControl.ElapsedPlayTimeMS)); uint32_t TargetElapsedMS = uint32_t (ElapsedSeconds * 1000); - uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FrameControl.ElapsedPlayTimeMS, 0); + uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, 0); uint32_t TargetFrameId = p_Parent->CalculateFrameId (TargetElapsedMS, 0); int32_t FrameDiff = TargetFrameId - CurrentFrame; if (2 > abs (FrameDiff)) { - // DEBUG_V ("No Need to adjust the time"); + // xDEBUG_V ("No Need to adjust the time"); break; } - // DEBUG_V ("Need to adjust the start time"); - // DEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FrameControl.ElapsedPlayTimeMS)); + // xDEBUG_V ("Need to adjust the start time"); + // xDEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FileControl.ElapsedPlayTimeMS)); - // DEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); - // DEBUG_V (String (" TargetFrameId: ") + String (TargetFrameId)); - // DEBUG_V (String (" FrameDiff: ") + String (FrameDiff)); + // xDEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); + // xDEBUG_V (String (" TargetFrameId: ") + String (TargetFrameId)); + // xDEBUG_V (String (" FrameDiff: ") + String (FrameDiff)); // Adjust the start of the file time to align with the master FPP noInterrupts (); if (20 < abs (FrameDiff)) { - // DEBUG_V ("Large Setp Adjustment"); - p_Parent->FrameControl.ElapsedPlayTimeMS = TargetElapsedMS; + // xDEBUG_V ("Large Setp Adjustment"); + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS = TargetElapsedMS; + p_Parent->FileControl[CurrentFile].StartingTimeMS = millis() - TargetElapsedMS; } else if(CurrentFrame > TargetFrameId) { - // DEBUG_V("go back a frame"); - p_Parent->FrameControl.ElapsedPlayTimeMS -= p_Parent->FrameControl.FrameStepTimeMS; + // xDEBUG_V("go back a frame"); + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS -= p_Parent->FileControl[CurrentFile].FrameStepTimeMS; + p_Parent->FileControl[CurrentFile].StartingTimeMS = millis() - p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS; } else { - // DEBUG_V("go forward a frame"); - p_Parent->FrameControl.ElapsedPlayTimeMS += p_Parent->FrameControl.FrameStepTimeMS; + // xDEBUG_V("go forward a frame"); + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS += p_Parent->FileControl[CurrentFile].FrameStepTimeMS; + p_Parent->FileControl[CurrentFile].StartingTimeMS = millis() - p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS; } interrupts (); response = true; - // DEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FrameControl.ElapsedPlayTimeMS)); + // xDEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS)); } while (false); - // DEBUG_END; + // xDEBUG_END; return response; } // fsm_PlayFile_state_PlayingFile::Sync @@ -500,42 +475,31 @@ bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSecond bool fsm_PlayFile_state_Stopping::Poll () { // DEBUG_START; - // DEBUG_V("fsm_PlayFile_state_Stopping::Poll"); - // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (p_Parent->FileHandleForFileBeingPlayed)); - FileMgr.CloseSdFile (p_Parent->FileHandleForFileBeingPlayed); - p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); + // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed)); - StartingElapsedTime = 0.0; - PlayCount = 0; + if(c_FileMgr::INVALID_FILE_HANDLE != p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed) + { + FileMgr.CloseSdFile (p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed); + } + else + { + // DEBUG_V("Unexpected missing file handle"); + } - p_Parent->SyncControl.LastRcvdElapsedSeconds = 0; - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; + p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); if(p_Parent->SendFppSync) { FPPDiscovery.GenerateFppSyncMsg(SYNC_PKT_STOP, emptyString, 0, float(0.0)); } - if (!FileName.equals(emptyString)) - { - // DEBUG_V ("Restarting File"); - p_Parent->Start (FileName, StartingElapsedTime, PlayCount); - } - // DEBUG_END; return true; } // fsm_PlayFile_state_Stopping::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Stopping::TimerPoll () -{ - // nothing to do - -} // fsm_PlayFile_state_Stopping::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Stopping::Init (c_InputFPPRemotePlayFile* Parent) { @@ -550,14 +514,24 @@ void fsm_PlayFile_state_Stopping::Init (c_InputFPPRemotePlayFile* Parent) } // fsm_PlayFile_state_Stopping::Init //----------------------------------------------------------------------------- -void fsm_PlayFile_state_Stopping::Start (String& _FileName, float ElapsedTime, uint32_t _PlayCount) +void fsm_PlayFile_state_Stopping::Start (String& FileName, float ElapsedSeconds, uint32_t RemainingPlayCount) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Stopping::Start"); - FileName = _FileName; - StartingElapsedTime = ElapsedTime; - PlayCount = _PlayCount; + // DEBUG_V("Set up a next file"); + + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); // DEBUG_END; @@ -577,7 +551,7 @@ void fsm_PlayFile_state_Stopping::Stop (void) bool fsm_PlayFile_state_Stopping::Sync (String&, float) { // DEBUG_START; - // DEBUG_V("State:Stopping"); + // DEBUG_V("fsm_PlayFile_state_Stopping::Sync"); // DEBUG_END; return false; @@ -589,30 +563,22 @@ bool fsm_PlayFile_state_Stopping::Sync (String&, float) //----------------------------------------------------------------------------- bool fsm_PlayFile_state_Error::Poll () { - // xDEBUG_START; + // DEBUG_START; + // DEBUG_V("fsm_PlayFile_state_Error::Poll"); - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.FrameStepTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; + if(c_FileMgr::INVALID_FILE_HANDLE != p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed) + { + // DEBUG_V("Unexpected file handle in Error handler."); + FileMgr.CloseSdFile (p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed); + } - // xDEBUG_END; + p_Parent->FileControl[CurrentFile].FileName.clear(); + + // DEBUG_END; return false; } // fsm_PlayFile_state_Error::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Error::TimerPoll () -{ - // xDEBUG_START; - - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.FrameStepTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; - - // xDEBUG_END; - -} // fsm_PlayFile_state_Error::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Error::Init (c_InputFPPRemotePlayFile* Parent) { @@ -622,30 +588,31 @@ void fsm_PlayFile_state_Error::Init (c_InputFPPRemotePlayFile* Parent) p_Parent = Parent; Parent->pCurrentFsmState = &(Parent->fsm_PlayFile_state_Error_imp); - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.FrameStepTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; - - if(c_FileMgr::INVALID_FILE_HANDLE != p_Parent->FileHandleForFileBeingPlayed) - { - // DEBUG_V("Unexpected File Handle at error init."); - FileMgr.CloseSdFile(p_Parent->FileHandleForFileBeingPlayed); - } - // DEBUG_END; } // fsm_PlayFile_state_Error::Init //----------------------------------------------------------------------------- -void fsm_PlayFile_state_Error::Start (String& FileName, float ElapsedSeconds, uint32_t PlayCount) +void fsm_PlayFile_state_Error::Start (String& FileName, float ElapsedSeconds, uint32_t RemainingPlayCount) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Error::Start"); - if (!FileName.equals(p_Parent->GetFileName ())) - { - p_Parent->fsm_PlayFile_state_Idle_imp.Start (FileName, ElapsedSeconds, PlayCount); - } + // DEBUG_V("Set up a next file"); + + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); + + p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); // DEBUG_END @@ -667,12 +634,9 @@ void fsm_PlayFile_state_Error::Stop (void) bool fsm_PlayFile_state_Error::Sync (String& FileName, float ElapsedSeconds) { // DEBUG_START; - // DEBUG_V("State:Error"); + // DEBUG_V("fsm_PlayFile_state_Error::Sync"); - if (!FileName.equals(p_Parent->GetFileName ())) - { - p_Parent->fsm_PlayFile_state_Idle_imp.Start (FileName, ElapsedSeconds, 1); - } + Start(FileName, ElapsedSeconds, 1); // DEBUG_END; return false; diff --git a/src/input/InputFPPRemotePlayList.cpp b/src/input/InputFPPRemotePlayList.cpp index a05845497..cb8af6264 100644 --- a/src/input/InputFPPRemotePlayList.cpp +++ b/src/input/InputFPPRemotePlayList.cpp @@ -48,7 +48,10 @@ void c_InputFPPRemotePlayList::Start (String & FileName, float ElapsedSeconds, u { // DEBUG_START; - pCurrentFsmState->Start (FileName, ElapsedSeconds, PlayCount); + if(!InputIsPaused()) + { + pCurrentFsmState->Start (FileName, ElapsedSeconds, PlayCount); + } // DEBUG_END; @@ -59,7 +62,10 @@ void c_InputFPPRemotePlayList::Stop () { // DEBUG_START; - pCurrentFsmState->Stop (); + if(!InputIsPaused()) + { + pCurrentFsmState->Stop (); + } // DEBUG_END; @@ -70,7 +76,10 @@ void c_InputFPPRemotePlayList::Sync (String & FileName, float ElapsedSeconds) { // DEBUG_START; - pCurrentFsmState->Sync (FileName, ElapsedSeconds); + if(!InputIsPaused()) + { + pCurrentFsmState->Sync (FileName, ElapsedSeconds); + } // DEBUG_END; @@ -80,10 +89,15 @@ void c_InputFPPRemotePlayList::Sync (String & FileName, float ElapsedSeconds) bool c_InputFPPRemotePlayList::Poll () { // DEBUG_START; + bool Response = false; + if(!InputIsPaused()) + { + // Show that we have received a poll + Response = pCurrentFsmState->Poll (); + } - return pCurrentFsmState->Poll (); - - // DEBUG_END; + // xDEBUG_END; + return Response; } // Poll @@ -119,11 +133,11 @@ bool c_InputFPPRemotePlayList::ProcessPlayListEntry () // Get the playlist file String FileData; - if (0 == FileMgr.ReadSdFile (PlayItemName, FileData)) + if (0 == FileMgr.ReadSdFile (FileControl[CurrentFile].FileName, FileData)) { - logcon (String (F ("Could not read Playlist file: '")) + PlayItemName + "'"); + logcon (String (F ("Could not read Playlist file: '")) + FileControl[CurrentFile].FileName + "'"); fsm_PlayList_state_Paused_imp.Init (this); - pCurrentFsmState->Start (PlayItemName, PauseDelayTimer.GetTimeRemaining() / 1000, 1); + pCurrentFsmState->Start (FileControl[CurrentFile].FileName, PauseDelayTimer.GetTimeRemaining() / 1000, 1); break; } // DEBUG_V (""); @@ -133,12 +147,12 @@ bool c_InputFPPRemotePlayList::ProcessPlayListEntry () // DEBUG_V ("Error Check"); if (error) { - String CfgFileMessagePrefix = String (F ("SD file: '")) + PlayItemName + "' "; + String CfgFileMessagePrefix = String (F ("SD file: '")) + FileControl[CurrentFile].FileName + "' "; logcon (CN_Heap_colon + String (ESP.getFreeHeap ())); logcon (CfgFileMessagePrefix + String (F ("Deserialzation Error. Error code = ")) + error.c_str ()); logcon (String (F ("++++")) + FileData + String (F ("----"))); fsm_PlayList_state_Paused_imp.Init (this); - pCurrentFsmState->Start (PlayItemName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); + pCurrentFsmState->Start (FileControl[CurrentFile].FileName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); break; } @@ -164,7 +178,7 @@ bool c_InputFPPRemotePlayList::ProcessPlayListEntry () PauseDelayTimer.StartTimer(1000, false); fsm_PlayList_state_Paused_imp.Init (this); - pCurrentFsmState->Start (PlayItemName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); + pCurrentFsmState->Start (FileControl[CurrentFile].FileName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); break; } diff --git a/src/input/InputFPPRemotePlayListFsm.cpp b/src/input/InputFPPRemotePlayListFsm.cpp index 3c7eb8cd9..c7fcd11ab 100644 --- a/src/input/InputFPPRemotePlayListFsm.cpp +++ b/src/input/InputFPPRemotePlayListFsm.cpp @@ -55,13 +55,13 @@ void fsm_PlayList_state_WaitForStart::Start (String & FileName, float, uint32_t) do // once { - pInputFPPRemotePlayList->PlayItemName = FileName; + pInputFPPRemotePlayList->FileControl[CurrentFile].FileName = FileName; pInputFPPRemotePlayList->PlayListEntryId = 0; // DEBUG_V (String ("PlayItemName: '") + pInputFPPRemotePlayList->PlayItemName + "'"); pInputFPPRemotePlayList->fsm_PlayList_state_Idle_imp.Init (pInputFPPRemotePlayList); - + } while (false); // DEBUG_END; diff --git a/src/input/InputMgr.cpp b/src/input/InputMgr.cpp index 24ba1b0b3..57a7e380f 100644 --- a/src/input/InputMgr.cpp +++ b/src/input/InputMgr.cpp @@ -36,8 +36,6 @@ // needs to be last #include "input/InputMgr.hpp" -//----------------------------------------------------------------------------- - //----------------------------------------------------------------------------- // Local Data definitions //----------------------------------------------------------------------------- @@ -62,6 +60,7 @@ static const InputTypeXlateMap_t InputTypeXlateMap[c_InputMgr::e_InputType::Inpu {c_InputMgr::e_InputType::InputType_Disabled, "Disabled", c_InputMgr::e_InputChannelIds::InputChannelId_ALL} }; +uint32_t DeltaTime = 0; #if defined ARDUINO_ARCH_ESP32 # include @@ -79,18 +78,17 @@ void InputMgrTask (void *arg) while(1) { - uint32_t DeltaTime = PollEndTime - PollStartTime; + DeltaTime = PollEndTime - PollStartTime; if (DeltaTime < MinPollTimeMs) { PollTime = pdMS_TO_TICKS(MinPollTimeMs - DeltaTime); + vTaskDelay(PollTime); } else { - // handle time wrap and long frames - PollTime = pdMS_TO_TICKS(1); + // DEBUG_V(String("handle time wrap and long frames. DeltaTime:") + String(DeltaTime)); } - vTaskDelay(PollTime); FeedWDT(); PollStartTime = millis(); @@ -102,6 +100,11 @@ void InputMgrTask (void *arg) PollEndTime = millis(); } } // InputMgrTask +#else +void TimerPollHandler() +{ + InputMgr.Process(); +} #endif // def ARDUINO_ARCH_ESP32 //----------------------------------------------------------------------------- @@ -187,7 +190,10 @@ void c_InputMgr::Begin (uint32_t BufferSize) #if defined ARDUINO_ARCH_ESP32 xTaskCreatePinnedToCore(InputMgrTask, "InputMgrTask", 4096, NULL, INPUTMGR_TASK_PRIORITY, &PollTaskHandle, 1); -#endif // defined ARDUINO_ARCH_ESP32 +#else + LastIsrTimeStampMS = millis (); + MsTicker.attach_ms (uint32_t (FPP_TICKER_PERIOD_MS), &TimerPollHandler, (void*)this); // Add ISR Function +#endif // ! defined ARDUINO_ARCH_ESP32 HasBeenInitialized = true; @@ -1010,7 +1016,7 @@ void c_InputMgr::SetOperationalState (bool ActiveFlag) // DEBUG_START; // DEBUG_V(String("ActiveFlag: ") + String(ActiveFlag)); - PauseProcessing = ActiveFlag; + PauseProcessing = !ActiveFlag; // pass through each active interface and set the active state for (auto & InputChannel : InputChannelDrivers) diff --git a/src/main.cpp b/src/main.cpp index 619707f3f..a7f4bbe9d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -513,11 +513,6 @@ void loop() // Keep the Network Open NetworkMgr.Poll (); -#if !defined ARDUINO_ARCH_ESP32 - // Process input data - InputMgr.Process (); -#endif // defined ARDUINO_ARCH_ESP32 - // Poll output OutputMgr.Poll(); diff --git a/src/service/FPPDiscovery.cpp b/src/service/FPPDiscovery.cpp index dce9e9380..878881722 100644 --- a/src/service/FPPDiscovery.cpp +++ b/src/service/FPPDiscovery.cpp @@ -139,6 +139,17 @@ void c_FPPDiscovery::Enable () } // Enable +//----------------------------------------------------------------------------- +void c_FPPDiscovery::SetOperationalState (bool ActiveFlag) +{ + // DEBUG_START; + + // Do NOT call enable / disable since they call other functions. + IsEnabled = ActiveFlag; + + // DEBUG_END; +} + //----------------------------------------------------------------------------- void c_FPPDiscovery::GetStatus (JsonObject & jsonStatus) { @@ -338,7 +349,7 @@ void c_FPPDiscovery::ProcessSyncPacket (uint8_t action, String FileName, float S // DEBUG_START; do // once { - if (!AllowedToRemotePlayFiles ()) + if (!IsEnabled || !AllowedToRemotePlayFiles ()) { // DEBUG_V ("Not allowed to play remote files"); break; @@ -429,9 +440,9 @@ void c_FPPDiscovery::ProcessBlankPacket () { // DEBUG_START; - StopPlaying (false); if (IsEnabled) { + StopPlaying (false); memset (OutputMgr.GetBufferAddress(), 0x0, OutputMgr.GetBufferUsedSize ()); } // DEBUG_END; @@ -531,6 +542,8 @@ void c_FPPDiscovery::BuildFseqResponse (String fname, c_FileMgr::FileId fseq, St JsonDocument JsonDoc; JsonObject JsonData = JsonDoc.to (); + // DEBUG_V(String("FileHandle: ") + String(fseq)); + FSEQRawHeader fsqHeader; FileMgr.ReadSdFile (fseq, (byte*)&fsqHeader, sizeof (fsqHeader), size_t(0)); @@ -832,14 +845,16 @@ void c_FPPDiscovery::ProcessFile ( // DEBUG_V(); if (final) { - // DEBUG_V("Allow file to play"); inFileUpload = false; UploadFileName = ""; writeFailed = false; memset(OutputMgr.GetBufferAddress(), 0x00, OutputMgr.GetBufferSize()); InputMgr.SetOperationalState(true); OutputMgr.PauseOutputs(false); - delay(10); + FeedWDT(); + delay(1000); + FeedWDT(); + // DEBUG_V("Allow file to play"); StartPlaying(UploadFileName, 0.0); } @@ -1149,6 +1164,7 @@ void c_FPPDiscovery::StartPlaying (String & FileName, float SecondsElapsed) { // DEBUG_START; // DEBUG_V (String("Open:: FileName: ") + FileName); + // DEBUG_V (String ("IsEnabled '") + String(IsEnabled)); do // once { @@ -1190,11 +1206,12 @@ void c_FPPDiscovery::StartPlaying (String & FileName, float SecondsElapsed) void c_FPPDiscovery::StopPlaying (bool wait) { // DEBUG_START; - // DEBUG_V(String("Current Task Priority: ") + String(uxTaskPriorityGet(NULL))); - // DEBUG_V (String ("FPPDiscovery::StopPlaying '") + InputFPPRemotePlayFile->GetFileName() + "'"); + // DEBUG_V (String ("Current Task Priority: ") + String(uxTaskPriorityGet(NULL))); + // xDEBUG_V (String ("FPPDiscovery::StopPlaying '") + InputFPPRemotePlayFile->GetFileName() + "'"); + // DEBUG_V (String ("IsEnabled '") + String(IsEnabled)); // prevent reentrant issues - if(!StopInProgress) + if(!StopInProgress && IsEnabled) { StopInProgress = true; // only process if the pointer is valid @@ -1209,6 +1226,7 @@ void c_FPPDiscovery::StopPlaying (bool wait) // DEBUG_V("try to stop"); InputFPPRemotePlayFile->Stop (); + InputFPPRemotePlayFile->Poll (); if(wait) { @@ -1312,5 +1330,4 @@ void c_FPPDiscovery::ForgetInputFPPRemotePlayFile () } // SetInputFPPRemotePlayFile - c_FPPDiscovery FPPDiscovery;