/* ===========================================================================

  loopFunc.h    Global variables and functions for  LoopFunc 

=============================================================================*/
#ifdef LOOP_FUNC_ALLOCATE
#define EXTERN
#else
#define EXTERN extern
#endif

typedef SINT4 INDEX1;
typedef SINT4 INDEX2;

struct Loop_List
{
  struct ymds_time Time;
  UINT2 iSite;
  UINT2 lFilled;        /* Slot is filled with an image */
};
void ymds_cpy
( volatile struct ymds_time *pTargetTime_a,
  volatile const struct serv_ymds_time *pSourceTime_a );
void ymds_cpy
( volatile struct serv_ymds_time *pTargetTime_a,
  volatile const struct ymds_time *pSourceTime_a );

#ifdef SIGMET_PROJECTION_H
class LoopFunc 
{
public:
  
  LoopFunc(void);           /* Constructor */
  UINT4 iCurrentVtvMapServer[256];
  void  init(void);         /* Initialize after shared memory is mapped */
  void  notifyPeerEntered( void );         /* Another mode entered */

  void  newImage(void);     /* Call when a new image has arrived */

  /* Callbacks for various button presses */
  void  FlushBuffer(void);

  void  loopLeft(void);
  void  loopRight(void);
  void  loopZigZag(void);
  void  loopStop(void);
  void  back(void);
  void  forward(void);
  void  toggle(void);
  
  void  setSkip( SINT4 iSeconds_a );
  void  setMaxTime( SINT4 iSeconds_a );
  void  setSpeed( FLT4 fFramesPerSecond_a );
  void  setPause( SINT4 iMilliSeconds_a );

  void  setMostRecent( void );
  UINT2 getMostRecent( void );
  void  setCurrentFrame( void );
  void  grabEndTime( void);

  void processServerReply            /* LOOP reply from server */
    ( char *stoks_a[8],
      const char *pdata,
      SINT4 isize );
  UINT2 lLoopIsRunning(void);

  void loopSwitchFrame(void );       /* Do not call from outside file */

private:
  /* Note that the private storage must be placed after the public, and
   * ifdef'ed off altogether.  This is to prevent mis allignments if
   * we ifdef off individual elements.
   */
#ifdef LOOP_FUNC_ALLOCATE
  /* Information about the previous image on the screen */
  UINT2   lPreviousValid_c;
  UINT2   iPreviousSiteNum_c;
  UINT2   iPreviousPType_c;
  char    sPreviousPName_c[12];
  struct ymds_time  PreviousTime_c;

  /* State of verious loop control attributes */
  UINT4 iSkipTime_c;      /* Skip time in seconds for loop */
  UINT4 iMaxTime_c;       /* Max time in seconds for loop */
  FLT4  fSpeed_c;         /* Speed in frames per second */
  UINT4 iPauseTime_c;     /* Pause time in ms */
  UINT2 lMostRecent_c;    /* Indicates if we are in most recent mode */
  UINT2 lCurrentFrame_c;  /* Indicates if we are in current frame mode */
  struct ymds_time EndTime_c;  /* End time for the loop, if not most recent or current */

  /* Array of onscreen structures */
  struct on_screen_picture8 OnScreenArray_c[MAX_LOOP_COUNT];
  /* Array of info about products we may use in the loop. */
  struct Loop_List LoopList_c[MAX_LOOP_COUNT];
  INDEX1  iLoopIndex_c;               /* Index of where we are in the loop */
  struct  linear_list_header LHead_c; /* List header for the loop */
  INDEX2  iLList_c[MAX_LOOP_COUNT];   /* List of indicies into loop */
    
  INDEX1  iFilledLoopTop_c;           /* 1+Index of last frame filled in the loop */
  INDEX1  iFilledLoopBase_c;          /* Index of first frame filled in the loop */

  UINT2   lDiscardNextFrame_c;        // Discard the next frame (might be loop loading frame)

  SFLT    LoopFilter_c;               /* Filter used to make the loop */
  SINT4   iLoopFrameSize_c;           /* Size of one frame in the loop in bytes */

  /* These are used to detect whether the loop buffer needs to be erased.  Note
   * that any frame arriving with a size which does not match the iLoopFrameSize_c
   * above must force clearing these variables.
   */
  UINT4   iPreviousLoopPType_c;
  char    sPreviousLoopPName_c[16];
  char    sPreviousLoopTName_c[16];

  UINT1   *pImageArray_c;             /* Array of images */
  SINT4   iImageArraySize_c;          /* Size of array in bytes, not pixels */

  /*Either or both bits can be on.  If zero, then the loop is off */
#define LOOP_OFF     (0)
#define LOOP_LOADING (0x01)
#define LOOP_RUNNING (0x02)
  UINT4   iSubMode_c;

  UINT4   lLoopForwards_c;   /* Current direction of loop playing/loading */
  UINT4   lLoopZigZag_c;     /* Loop should play in zig/zag order */

  /* Functions: */
  void   LoadAnotherFrame(void);
  INDEX2 iLookupNewFrame(void);
  INDEX2 iLookupNextFrame(void);

  void  loopEither(void);
  void  processProductLoopListReply
    (SPHD_SUM *pData_a,
     SINT4 iSize_a );
  void  processTaskLoopListReply
    (SIHD_SUM *pData_a,
     SINT4 iSize_a );

  void  UpdateMovieInfo(void);
  void  CheckLoopPlaying(void);
  void  StepEither
    (UINT2 lforward_a);
  void  RequestProductLoopList(void);
  void  RequestTaskLoopList(void);

  void  MergeTwoLists
    (const struct Loop_List NewList_a[],
     SINT4 iNewCount_a );

#endif  /* #ifdef LOOP_FUNC_ALLOCATE */
  
};
EXTERN LoopFunc loopFunc;
#endif  /* #ifdef SIGMET_PROJECTION_H */

#undef EXTERN
