/*
 * Copyright 1988, 1989, 1990, 1991 Massachusetts Institute of Technology
 */
#ifndef GLIB_H
#define GLIB_H

#define CLIENT_REVISION 25


/* This is the fundamental unit of the Galatea protocol */
#define G_INT32 int

/* For machine specific declaration of the socket type */
#define G_SOCKTYPE int

#ifndef SYSINCLUDES
#define SYSINCLUDES
#include<stdio.h>
#ifndef __TYPES__
#define __TYPES__
#include<sys/types.h>
#endif /* __TYPES__ */
#ifndef __SOCKET__
#define __SOCKET__
#include<sys/socket.h>
#endif /* __SOCKET__ */
#include<sys/time.h>
#include<sys/ioctl.h>
#ifndef __FILEH__
#ifndef FOPEN
#define __FILEH__
#include<sys/file.h>
#endif /* FOPEN */
#endif /* __FILEH__ */
#include<netinet/in.h>
#ifndef SYSV
#include<strings.h>
#include<netinet/tcp.h>
#else /* SYSV */
#include<string.h>
#endif /* SYSV */

#ifdef UNIXCONN
#ifndef UNIXINCED
#define UNIXINCED
#include<sys/un.h>
#endif /* UNIXINCED */
#endif /* UNIXCONN */

#ifdef inter386
#include <sys/bsdtypes.h>
#include <net/errno.h>
#endif /* inter386 */

#include<netdb.h>
#include<ctype.h>

#endif /* SYSINCLUDES */

#define G_UNIX_PATH "/dev/gal-unix"
/* Eliminate G_OLD_UNIX_PATH to eliminate backward compatibility */
#define G_OLD_UNIX_PATH "/tmp/.G-unix/G"
/* Eliminate G_OLD_UNIX_DIR to inhibit the creation of the old directory */
#define G_OLD_UNIX_DIR "/tmp/.G-unix"

#define MAX_FDS 32

/* standard defined speeds */

#define R_MAX		-300		/* maximum possible velocity */
#define R_VERY_FAST	-150		/* really moving along */
#define R_FAST		-90		/* 3-5 times normal; still visible */
#define R_PLAY		-30		/* reverse normal */
#define R_SLOW		-10		/* 1/2 to 1/5 normal */
#define R_VERY_SLOW	-3		/* just barely moving */
#define STOP		0		/* transport halted */
#define F_VERY_SLOW     3		/* just barely moving */
#define F_SLOW		10		/* 1/2 to 1/5 normal */
#define F_PLAY		30		/* forward normal */
#define F_FAST		90		/* 3-5 times normal; still visible */
#define F_VERY_FAST	150		/* really moving along */
#define F_MAX		300		/* maximum possible velocity */

/* for jogs */

#define FORWARD         1
#define REVERSE         -1

/* standard defined cmds */
#define INDEX_ON		0
#define INDEX_OFF		1
#define A1_ON			2
#define A1_OFF			3
#define A2_ON			4
#define A2_OFF			5
#define LOAD			6
#define UNLOAD			7
#define EJECT                   8
#define INDEX_TOGGLE            9
#define FORKLOAD                10
#define STARTLOAD               11
#define ENDLOAD                 12
#define RECORD_MODE_ON          13
#define RECORD_MODE_OFF         14
#define SQUELCH_ON              15
#define SQUELCH_OFF             16
#define VIDEO_ON                17
#define VIDEO_OFF               18

/* for immediate versus sync'd return for GPlaySeg() */
#define RETURN_NOW              0
#define RETURN_SYNC             1
#define RETURN_NOW_WITH_SPEED   2

/* for GPlaySeg()'s that start at the current frame */
#define CURRENT_FRAME           0


/* selects library sync style */
#define ASYNC_MODE              1
#define SYNC_MODE               0

#define Notify                  1
#define NoNotify                0

#define TURN_ON                 1
#define TURN_OFF                0

#define SPINDOWN                1
#define NOSPINDOWN              0

typedef struct {
  G_INT32 parm[10];
} Galatea_packet;

typedef struct {
  G_INT32 index;
  G_INT32 type;
  char *volume;
} VolumeList;

typedef struct {
  G_INT32 index;
  G_INT32 uid;
  G_INT32 perm;
  char *dbmname;
} DatabaseList;

#ifdef OBSOLETE
typedef struct _script_event {
  G_INT32 target_frame;  /* frame (from 0 since start of list) */
  G_INT32 action;    /* ROLL, SWITCH or RELEASE */
  G_INT32 arg;    /* source frame or VIDEO_CHAN | RIGHT_CHAN | LEFT_CHAN */
  G_INT32 arg2;   /* secondary argument... speed?*/
  struct _script_event *next;    /* next list item */
} script_event;

typedef struct _action {
  script_event *events;
  G_INT32 source_vol;
  char *volume_name;
  struct _action *next;
} action;
#endif /* OBSOLETE */

/* New Server structure */
typedef struct _server {
  G_SOCKTYPE fd;
  char *server;
  G_INT32 output;
  G_INT32 num_volumes;
  VolumeList *volumes;
  G_INT32 switching_mask;
  G_INT32 num_extensions;
  char **extensions;
  G_INT32 max_lock_time;
  G_INT32 ex1;
  G_INT32 ex2;
  G_INT32 ex3;
  G_INT32 ex4;
  G_INT32 ex5;
  G_INT32 ex6;
  G_INT32 ex7;
  G_INT32 ex8;
  G_INT32 num_db;
  DatabaseList *databases;
} Server;

#define G_OpenServer 1
#define G_Switch 2
#define G_Run 3
#define G_Jog 4
#define G_Still 5
#define G_Index 6
#define G_Search 7
#define G_GetFrame 8
#define G_PlaySeg 9
#define G_Reset 10
#define G_Release 11
#define G_Lock 12
#define G_UnLock 13
#define G_Download 14
#define G_PlayList 15
#define G_RequestNotification 16
#define G_ShutOff 17
#define G_Load 18
#define G_CheckRevision 19
#define G_Configure 20
#define G_GetServerTime 21
#define G_RegisterTimeSlice 22
#define G_CancelTimeSlice 23
#define G_GetStatistics 24
#define G_Rebuild 25
#define G_Mount 26
#define G_Umount 27
#define G_GetMounts 28
#define G_FreeList 29
#define G_Alloc 30
#define G_Record 31
#define G_Free 32
#define G_RecordPreview 33
#define G_AllocAtFrame 34
#define G_Dub 35
#define G_GetDatabases 36
#define G_GetSpeed 37
#define G_PlaySequence 38
/* Must update G_MINEXT to be at least 1 greater than the maximum builtin
   protocol request */
#define G_MINEXT 39

#define ROLL    0
#define SEARCH  1
#define SWITCH  2
#define RELEASE 3
#define END_OF_TRANSMISSION   -1000000

#ifndef VIDEO_CHAN
#define VIDEO_CHAN      1
#define LEFT_CHAN       2
#define RIGHT_CHAN      4
#define AUDIO_CHAN      LEFT_CHAN | RIGHT_CHAN
#define ALL_CHAN        AUDIO_CHAN | VIDEO_CHAN
#endif

#define INDEX_CTRL      8

#define SQUELCH_CTRL    16

/* Device types.  Clients should only ever see 
   SWTR_DEV, INPUT_DEV and RPD_DEV */
#define SWTR_DEV	1
#define	RPD_DEV		2
#define INPUT_DEV	3	/* an uncontrolled channel source */
#define OUTPUT_DEV	4	/* a channel sink */
#define NETWORK_DEV     5
#define IGN_DEV         6
#define DATA_DEV        7      /* Database */

#define RECORDABLE      0x0100  /* If an RPD_DEV can record */

/* Permission modes for databases */
#define G_USER_WRITE    1
#define G_USER_READ     2
#define G_WORLD_WRITE   4
#define G_WORLD_READ    8
#define G_STICKY_DB     16

/* Standard defined errors */
#define NO_ERROR              999999
#define LOWEST_ERROR         1000000  /* use this for < LOWEST_ERROR */
#define VOLUME_LIST_OLD      1000000  /* something has changed */
#define BAD_VOLUME            1000001  /* not a real volume */
#define FUNC_NOT_SUPPORTED    1000002  /* volume doesn't support func */
#define BAD_COMMAND           1000003  /* unknown command */
#define COULDNT_SEARCH        1000004  /* fault in RPD search */
#define COULDNT_STOP          1000005  /* couldn't stop RPD */
#define COULDNT_CHANGE_SPEED  1000006  /* couldn't change RPD speed */
#define COULDNT_DO_FUNC       1000007  /* fault while trying func */
#define BAD_ARGUMENT          1000008  /* an argument was faulty */
#define GIO_ERROR             1000010  /* a write to a server failed */
#define VIOLATE_TIME_SLICE    1000011  /* requests violates time slice */
#define SEGMENT_TOO_LONG      1000014  /*PlaySeg request would block too long*/
#define PERMISSION_DENIED     1000015  /* unpermitted command */
#define COULDNT_ROUTE         1000017  /* a switch operation failed */
#define COULDNT_ALLOC         1000018  /* Not enough free on volume */
#define COULDNT_FREE          1000019  /* Couldn't free block */
#define VIOLATE_ALLOC         1000020  /* Like a segmentation violation */
#define BAD_OUTPUT            1000021  /* Client output beyond server bounds*/
#define DB_LIST_OLD           1000022  /* database list has changed */
#define NO_EXTENSION          1000023  /* Desired extension not on server */
#define EXTENSION_LIST_OLD    1000024  /* An extension has been (un)loaded */
#define HIGHEST_ERROR         1000024  /* This to be changed with new errs */

static char *G_error_strings[] = {
    "No error",
    "Volume list old",
    "Bad volume",
    "Function not supported",
    "Bad command",
    "Couldn't search",
    "Couldn't stop",
    "Couldn't change speed",
    "Couldn't do function",
    "Bad argument",
    "(Unknown error)",
    "Galatea I/O Error",
    "Violated time slice",
    "(Unknown error)",
    "(Unknown error)",
    "Segment too long",
    "Permission denied",
    "(Unknown error)",
    "Couldn't route",
    "Couldn't allocate",
    "Couldn't free",
    "Violate allocation",
    "Bad output",
    "Database list old",
    "No such extension",
    "Extension list old",
};

typedef struct {
  G_INT32 revision;
  G_INT32 num_requests;
  G_INT32 run_time;
  G_INT32 num_collisions;
  G_INT32 num_connections;
  G_INT32 max_connections;
  G_INT32 delayed_requests;
} GStats;

typedef struct {
  G_INT32 volumenum;
  G_INT32 start, end;
  G_INT32 speed;
  G_INT32 mask;
} GSegment;

#ifndef FD_SET
#define NFDBITS    (sizeof(fd_set) * 8)
#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
#endif /* FD_SET */

/* Public function declarations */
Server *GOpenServer(), *GReopenServer(), *GNewOpenServer();

G_INT32 GCloseServer(), GSwitch(), GRun(), GJog(), GStill();
G_INT32 GConfigure(), GLoad(), GSearch(), GGetFrame(), GPlaySeg();
G_INT32 GShutOff(), GAlloc(), GAllocAtFrame(), GFree(), GRecord();
G_INT32 GRecordPreview(), GCheckRevision(), GLock(), GUnLock();
G_INT32 GGetServerTime(), GSetState(), GSetErrorHandler(), GRelease();
G_INT32 GRequestNotification(), GWhichVolumeIndex(), GVolumeIndex();
G_INT32 GMaxLockTime(), GVolumeType(), GNumberVolumes(), GNumberExtensions();
G_INT32 GGetStatistics(), GRebuild(), GMount(), GUmount(), GMounts();
G_INT32 GUmounts(), GGetMounts(), GGetSpeed(), GPlaySequence();
G_INT32 GExtensionMajor();
G_SOCKTYPE GConnection();

char *GWhichVolumeName(), *GVolumeName(), *GExtensionName(), *GOpenedHost();

/* Private function declarations */
G_INT32 _freeserv(), _gopenserv(), _handleerror(), acceptint(); 
G_INT32 SendCommand(), full_read(), full_write(), sendstring();
G_INT32 sendint();
char *acceptstring();
G_SOCKTYPE _gconnserv();
char *strfile();

#ifndef MAC
G_INT32 serv_full_read(), serv_acceptint();
char *serv_acceptstring();
#endif /* MAC */

#ifdef OBSOLETE
G_INT32 IsOKToRead();
#endif /* OBSOLETE */

#endif /* GLIB_H */
