LCOV - code coverage report
Current view: top level - apps/streamCircBuff - streamCircBuff.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 0.0 % 87 0
Test Date: 2026-01-03 21:03:39 Functions: 0.0 % 18 0

            Line data    Source code
       1              : /** \file streamCircBuff.hpp
       2              :   * \brief The MagAO-X streamCircBuff app header file
       3              :   *
       4              :   * \ingroup streamCircBuff_files
       5              :   */
       6              : 
       7              : #ifndef streamCircBuff_hpp
       8              : #define streamCircBuff_hpp
       9              : 
      10              : 
      11              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      12              : #include "../../magaox_git_version.h"
      13              : 
      14              : /** \defgroup streamCircBuff
      15              :   * \brief An application to keep a circular buffer of a stream
      16              :   *
      17              :   * <a href="../handbook/operating/software/apps/streamCircBuff.html">Application Documentation</a>
      18              :   *
      19              :   * \ingroup apps
      20              :   *
      21              :   */
      22              : 
      23              : /** \defgroup streamCircBuff_files
      24              :   * \ingroup streamCircBuff
      25              :   */
      26              : 
      27              : namespace MagAOX
      28              : {
      29              : namespace app
      30              : {
      31              : 
      32              : /// Class for application to keep a circular buffer of a stream and publish it to another stream
      33              : /**
      34              :   * \ingroup streamCircBuff
      35              :   */
      36              : class streamCircBuff : public MagAOXApp<true>,
      37              :                        public dev::shmimMonitor<streamCircBuff>,
      38              :                        public dev::frameGrabber<streamCircBuff>,
      39              :                        public dev::telemeter<streamCircBuff>
      40              : {
      41              :    friend class dev::shmimMonitor<streamCircBuff>;
      42              :    friend class dev::frameGrabber<streamCircBuff>;
      43              :    friend class dev::telemeter<streamCircBuff>;
      44              : 
      45              : public:
      46              : 
      47              :    /** \name app::dev Configurations
      48              :      *@{
      49              :      */
      50              : 
      51              :    static constexpr bool c_frameGrabber_flippable = false; ///< app:dev config to tell framegrabber these images can not be flipped
      52              : 
      53              :    ///@}
      54              : 
      55              :    typedef float realT;
      56              : 
      57              :    /// The base shmimMonitor type
      58              :    typedef dev::shmimMonitor<streamCircBuff> shmimMonitorT;
      59              : 
      60              :    /// The base frameGrabber type
      61              :    typedef dev::frameGrabber<streamCircBuff> frameGrabberT;
      62              : 
      63              :    /// The telemeter type
      64              :    typedef dev::telemeter<streamCircBuff> telemeterT;
      65              : 
      66              : 
      67              : protected:
      68              : 
      69              :    /** \name Configurable Parameters
      70              :      *@{
      71              :      */
      72              :    ///@}
      73              : 
      74              :    char * m_currSrc {nullptr};
      75              : 
      76              :    sem_t m_smSemaphore {0}; ///< Semaphore used to synchronize the fg thread and the sm thread.
      77              : 
      78              : public:
      79              :    /// Default c'tor.
      80              :    streamCircBuff();
      81              : 
      82              :    /// D'tor, declared and defined for noexcept.
      83            0 :    ~streamCircBuff() noexcept
      84            0 :    {}
      85              : 
      86              :    virtual void setupConfig();
      87              : 
      88              :    /// Implementation of loadConfig logic, separated for testing.
      89              :    /** This is called by loadConfig().
      90              :      */
      91              :    int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
      92              : 
      93              :    virtual void loadConfig();
      94              : 
      95              :    /// Startup function
      96              :    /**
      97              :      *
      98              :      */
      99              :    virtual int appStartup();
     100              : 
     101              :    /// Implementation of the FSM for streamCircBuff.
     102              :    /**
     103              :      * \returns 0 on no critical error
     104              :      * \returns -1 on an error requiring shutdown
     105              :      */
     106              :    virtual int appLogic();
     107              : 
     108              :    /// Shutdown the app.
     109              :    /**
     110              :      *
     111              :      */
     112              :    virtual int appShutdown();
     113              : 
     114              : 
     115              : protected:
     116              : 
     117              :    float (*pixget)(void *, size_t) {nullptr}; ///< Pointer to a function to extract the image data as float
     118              : 
     119              :    //shmimMonitor Interface
     120              :    int allocate( const dev::shmimT & dummy /**< [in] tag to differentiate shmimMonitor parents.*/);
     121              : 
     122              :    int allocatePSDStreams();
     123              : 
     124              :    int processImage( void * curr_src,          ///< [in] pointer to start of current frame.
     125              :                      const dev::shmimT & dummy ///< [in] tag to differentiate shmimMonitor parents.
     126              :                    );
     127              : 
     128              :    /** \name dev::frameGrabber interface
     129              :      *
     130              :      * @{
     131              :      */
     132              : 
     133              :    /// Implementation of the framegrabber configureAcquisition interface
     134              :    /**
     135              :      * \returns 0 on success
     136              :      * \returns -1 on error
     137              :      */
     138              :    int configureAcquisition();
     139              : 
     140              :    /// Implementation of the framegrabber fps interface
     141              :    /**
     142              :      * \todo this needs to infer the stream fps and return it
     143              :      */
     144            0 :    float fps()
     145              :    {
     146            0 :       return 1.0;
     147              :    }
     148              : 
     149              :    /// Implementation of the framegrabber startAcquisition interface
     150              :    /**
     151              :      * \returns 0 on success
     152              :      * \returns -1 on error
     153              :      */
     154              :    int startAcquisition();
     155              : 
     156              :    /// Implementation of the framegrabber acquireAndCheckValid interface
     157              :    /**
     158              :      * \returns 0 on success
     159              :      * \returns -1 on error
     160              :      */
     161              :    int acquireAndCheckValid();
     162              : 
     163              :    /// Implementation of the framegrabber loadImageIntoStream interface
     164              :    /**
     165              :      * \returns 0 on success
     166              :      * \returns -1 on error
     167              :      */
     168              :    int loadImageIntoStream( void * dest  /**< [in] */);
     169              : 
     170              :    /// Implementation of the framegrabber reconfig interface
     171              :    /**
     172              :      * \returns 0 on success
     173              :      * \returns -1 on error
     174              :      */
     175              :    int reconfig();
     176              : 
     177              :    /** \name Telemeter Interface
     178              :      *
     179              :      * @{
     180              :      */
     181              :    int checkRecordTimes();
     182              : 
     183              :    int recordTelem( const telem_fgtimings * );
     184              : 
     185              :    ///@}
     186              : 
     187              : };
     188              : 
     189            0 : streamCircBuff::streamCircBuff() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     190              : {
     191              : 
     192            0 :    return;
     193            0 : }
     194              : 
     195            0 : void streamCircBuff::setupConfig()
     196              : {
     197            0 :    SHMIMMONITOR_SETUP_CONFIG(config);
     198              : 
     199            0 :    FRAMEGRABBER_SETUP_CONFIG(config);
     200              : 
     201            0 :    TELEMETER_SETUP_CONFIG(config);
     202              : 
     203              : }
     204              : 
     205            0 : int streamCircBuff::loadConfigImpl( mx::app::appConfigurator & _config )
     206              : {
     207            0 :    SHMIMMONITOR_LOAD_CONFIG(_config);
     208              : 
     209            0 :    FRAMEGRABBER_LOAD_CONFIG(_config);
     210              : 
     211            0 :    TELEMETER_LOAD_CONFIG(config);
     212              : 
     213            0 :    return 0;
     214              : }
     215              : 
     216            0 : void streamCircBuff::loadConfig()
     217              : {
     218            0 :    loadConfigImpl(config);
     219            0 : }
     220              : 
     221            0 : int streamCircBuff::appStartup()
     222              : {
     223            0 :    if(sem_init(&m_smSemaphore, 0,0) < 0)
     224              :    {
     225            0 :       log<software_critical>({__FILE__, __LINE__, errno,0, "Initializing S.M. semaphore"});
     226            0 :       return -1;
     227              :    }
     228              : 
     229            0 :    SHMIMMONITOR_APP_STARTUP;
     230              : 
     231            0 :    FRAMEGRABBER_APP_STARTUP;
     232              : 
     233            0 :    TELEMETER_APP_STARTUP;
     234              : 
     235            0 :    state(stateCodes::OPERATING);
     236              : 
     237            0 :    return 0;
     238              : }
     239              : 
     240            0 : int streamCircBuff::appLogic()
     241              : {
     242            0 :    SHMIMMONITOR_APP_LOGIC;
     243              : 
     244            0 :    FRAMEGRABBER_APP_LOGIC;
     245              : 
     246            0 :    TELEMETER_APP_LOGIC;
     247              : 
     248            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     249              : 
     250            0 :    SHMIMMONITOR_UPDATE_INDI;
     251              : 
     252            0 :    FRAMEGRABBER_UPDATE_INDI;
     253              : 
     254            0 :    return 0;
     255            0 : }
     256              : 
     257            0 : int streamCircBuff::appShutdown()
     258              : {
     259            0 :    SHMIMMONITOR_APP_SHUTDOWN;
     260            0 :    FRAMEGRABBER_APP_SHUTDOWN;
     261            0 :    TELEMETER_APP_SHUTDOWN;
     262              : 
     263            0 :    return 0;
     264              : }
     265              : 
     266            0 : int streamCircBuff::allocate( const dev::shmimT & dummy)
     267              : {
     268              :    static_cast<void>(dummy);
     269              : 
     270              :    //we don't actually do anything here -- just a pass through to f.g.
     271              : 
     272            0 :    pixget = getPixPointer<float>(shmimMonitorT::m_dataType);
     273              : 
     274            0 :    m_reconfig = true;
     275              : 
     276            0 :    return 0;
     277              : }
     278              : 
     279            0 : int streamCircBuff::processImage( void * curr_src,
     280              :                                   const dev::shmimT & dummy
     281              :                                 )
     282              : {
     283              :    static_cast<void>(dummy);
     284              : 
     285            0 :    m_currSrc = static_cast<char *>(curr_src);
     286              : 
     287              :    //Now tell the f.g. to get going
     288            0 :    if(sem_post(&m_smSemaphore) < 0)
     289              :    {
     290            0 :       log<software_critical>({__FILE__, __LINE__, errno, 0, "Error posting to semaphore"});
     291            0 :       return -1;
     292              :    }
     293              : 
     294            0 :    return 0;
     295              : }
     296              : 
     297            0 : int streamCircBuff::configureAcquisition()
     298              : {
     299            0 :    std::unique_lock<std::mutex> lock(m_indiMutex);
     300              : 
     301              :    ///\todo potential but verrrrry unlikely bug: shmimMonitorT could change these before allocate sets the lock above.  Should use a local set of w/h instead.
     302            0 :    if(shmimMonitorT::m_width==0 || shmimMonitorT::m_height==0)
     303              :    {
     304              :       //This means we haven't connected to the stream to accumulate. so wait.
     305            0 :       lock.unlock(); //don't hold the lock for a whole second.
     306            0 :       sleep(1);
     307            0 :       return -1;
     308              :    }
     309              : 
     310            0 :    frameGrabberT::m_width = shmimMonitorT::m_width;
     311            0 :    frameGrabberT::m_height = shmimMonitorT::m_height;
     312            0 :    frameGrabberT::m_dataType = IMAGESTRUCT_FLOAT;
     313              : 
     314            0 :    return 0;
     315            0 : }
     316              : 
     317            0 : int streamCircBuff::startAcquisition()
     318              : {
     319            0 :    return 0;
     320              : }
     321              : 
     322            0 : int streamCircBuff::acquireAndCheckValid()
     323              : {
     324              :    timespec ts;
     325              : 
     326            0 :    if(clock_gettime(CLOCK_REALTIME, &ts) < 0)
     327              :    {
     328            0 :       log<software_critical>({__FILE__,__LINE__,errno,0,"clock_gettime"});
     329            0 :       return -1;
     330              :    }
     331              : 
     332            0 :    ts.tv_sec += 1;
     333              : 
     334            0 :    if(sem_timedwait(&m_smSemaphore, &ts) == 0)
     335              :    {
     336            0 :       clock_gettime(CLOCK_REALTIME, &m_currImageTimestamp);
     337            0 :       return 0;
     338              :    }
     339              :    else
     340              :    {
     341            0 :       return 1;
     342              :    }
     343              : 
     344              :    if(m_currSrc == nullptr)
     345              :    {
     346              :       return 1;
     347              :    }
     348              : }
     349              : 
     350            0 : int streamCircBuff::loadImageIntoStream(void * dest)
     351              : {
     352            0 :    if(m_currSrc == nullptr)
     353              :    {
     354            0 :       return -1;
     355              :    }
     356              : 
     357            0 :    float * fdest = reinterpret_cast<float *>(dest);
     358              : 
     359            0 :    for(size_t n = 0; n < shmimMonitorT::m_width*shmimMonitorT::m_height; ++n)
     360              :    {
     361            0 :       fdest[n] = pixget(m_currSrc,n);
     362              :    }
     363              : 
     364              :    //memcpy(dest, m_currSrc, shmimMonitorT::m_width*shmimMonitorT::m_height*frameGrabberT::m_typeSize  );
     365            0 :    return 0;
     366              : }
     367              : 
     368            0 : int streamCircBuff::reconfig()
     369              : {
     370            0 :    return 0;
     371              : }
     372              : 
     373            0 : int streamCircBuff::checkRecordTimes()
     374              : {
     375            0 :    return telemeterT::checkRecordTimes(telem_fgtimings());
     376              : }
     377              : 
     378            0 : int streamCircBuff::recordTelem( const telem_fgtimings * )
     379              : {
     380            0 :    return recordFGTimings(true);
     381              : }
     382              : 
     383              : 
     384              : } //namespace app
     385              : } //namespace MagAOX
     386              : 
     387              : #endif //streamCircBuff_hpp
        

Generated by: LCOV version 2.0-1