/*
 * merge.h
 * 
 * Author: Marc Unangst
 */
/*
 * Copyright (c) of Carnegie Mellon University, 1996,1997,1998,1999.
 *
 * Permission to reproduce, use, and prepare derivative works of
 * this software for internal use is granted provided the copyright
 * and "No Warranty" statements are included with all reproductions
 * and derivative works. This software may also be redistributed
 * without charge provided that the copyright and "No Warranty"
 * statements are included in all redistributions.
 *
 * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS.
 * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER
 * EXPRESSED OR IMPLIED AS TO THE MATTER INCLUDING, BUT NOT LIMITED
 * TO: WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY
 * OF RESULTS OR RESULTS OBTAINED FROM USE OF THIS SOFTWARE. CARNEGIE
 * MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT
 * TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
 */


#ifndef _MERGE_H_INCLUDED
#define _MERGE_H_INCLUDED

#include <nasd/nasd_options.h>
#include <nasd/nasd_common.h>
#include <nasd/nasd_pdrive.h>
#include <nasd/nasd_pdrive_client.h>
#include <nasd/nasd_edrfs_client.h>
#include <nasd/video/rtsp.h>
#include <nasd/video/merge_options.h>

typedef struct nasd_merge_fs_ent_s	nasd_merge_fs_ent_t;
typedef struct nasd_merge_buffer_s	nasd_merge_buffer_t;
typedef struct nasd_merge_txq_s		nasd_merge_txq_t;
typedef struct nasd_merge_clientlist_s	nasd_merge_clientlist_t;

struct nasd_merge_fs_ent_s {
  char *fmhost;			    /* EDRFS file manager hostname        */
  char *fsname;			    /* filesystem name                    */
  int binding_type;		    /* NASD binding type                  */
  nasd_edrfs_handle_t nh;	    /* handle to EDRFS file manager       */
  nasd_drive_handle_t h;	    /* handle to associated drive         */
  nasd_edrfs_credential_t cred;	    /* credential to use for all accesses */
  nasd_cookie_t root_cookie;	    /* security cookie for root object    */
  nasd_edrfs_identifier_t root_nid; /* NASD-EDRFS ID for root object      */
};

enum movie_state {
  S_SETUP,
  S_PLAYING,
  S_PAUSED,
  S_DONE,
  S_CLOSED
};

struct nasd_merge_txq_s {
  nasd_merge_buffer_t *head;
  int num;
  NASD_DECLARE_MUTEX(tx_mutex)
  NASD_DECLARE_COND(tx_cv)
};

#define NASD_MERGE_MAX_DRIVES	8

struct driveinfo {
  int movie_id;
  nasd_edrfs_identifier_t         index_nid;
  nasd_edrfs_identifier_t         data_nid;
  nasd_cookie_t                   index_cookie;
  nasd_cookie_t                   data_cookie;
  nasd_index_stream_identifier_t  stream_id;
  /* XXXmju perhaps this should be a nasd_offset_t? */
  long byte_offset;
};

struct streaminfo {
  char objname[80];		/* base object name i.e. "foo.mpg" */
  struct driveinfo di[NASD_MERGE_MAX_DRIVES];
  int num_drives;
  int tx_thresh;
  int tx_fd;			/* transmit fd */
  nasd_merge_txq_t *tx_q;	/* buffers to transmit */
  int resume_drive;             /* Drive to start unpause with */
  long cur_tx_seq;		/* sequence number of next packet to tx */
  NASD_DECLARE_MUTEX(stream_lock)
  int rx_done;			/* count of drives that have sent last dgram */
  enum movie_state state;
  long cur_rx_seq;		/* sequence number of next packet to rx */
  long cur_rx_frame;		/* frame of next packet */
};

#define NASD_MERGE_BUF_SIZE	1500

struct nasd_merge_buffer_s {
  nasd_byte_t buf[NASD_MERGE_BUF_SIZE];	/* buffer space */
  nasd_byte_t *data;		/* pointer to start of data in buffer */
  size_t datalen;		/* length of data region */
  int flags;
  nasd_uint32 seqnum;
  nasd_merge_buffer_t *next;
};

struct nasd_merge_clientlist_s {
  NASD_DECLARE_MUTEX(lock)
  NASD_DECLARE_COND(cond)
  struct clientinfo *head;
  struct clientinfo *tail;
  int num;
};

extern nasd_merge_fs_ent_t *DrivePool;
extern int nasd_merge_num_drives;

/* values for the buf->flags word */
/* this is last buffer in stream */
#define BUFFL_LAST_BUF		1<<0
/* this buffer has start of new frame */
#define BUFFL_NEW_FRAME		1<<1

extern int nasd_merge_drive_socket;
extern struct sockaddr_in nasd_merge_drive_sockaddr;
extern nasd_freelist_t *nasd_merge_bufq;
NASD_DECLARE_EXTERN_MUTEX(nasd_merge_flowtable_lock)
extern int TargetBPMS;
extern nasd_merge_clientlist_t nasd_merge_clients;
extern int nasd_merge_verboseflag;
extern int nasd_merge_pipe[];

extern nasd_threadgroup_t nasd_merge_rx_threadgroup;
extern nasd_threadgroup_t nasd_merge_tx_threadgroup;
extern nasd_threadgroup_t nasd_merge_ctrl_threadgroup;

/* merge.c */
extern void rxThread(nasd_threadarg_t ignored);
extern void requestMovie(struct clientinfo *cinf, nasd_status_t *status,
			 nasd_rpc_status_t *op_status);
extern void abortMovie(struct clientinfo *cinf, nasd_status_t *status,
		      nasd_rpc_status_t *op_status);
extern void txThread(nasd_threadarg_t arg);
extern void nasd_merge_close_stream(struct clientinfo *cinf);
extern void nasd_merge_free_txq(nasd_merge_txq_t *q);
extern void nasd_merge_close_and_abort(struct clientinfo *cinf);
extern void nasd_merge_txq_insert(nasd_merge_txq_t *q, nasd_merge_buffer_t *buf);

/* server.c */
extern void rtspServer(nasd_threadarg_t ignored);
extern void nasd_merge_abort_client(struct clientinfo *cinf);

#endif /* _MERGE_H_INCLUDED */
