/*
 *  TV headend - structures
 *  Copyright (C) 2007 Andreas Ă–man
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef TV_HEAD_H
#define TV_HEAD_H

#include <pthread.h>
#include <netinet/in.h>
#include <libhts/htsq.h>
#include <libhts/htstv.h>
#include <libhts/htscfg.h>
#include <libhts/avg.h>
#include <libhts/hts_strtab.h>
#include <libavcodec/avcodec.h>
#include <libhts/redblack.h>
#include <linux/dvb/frontend.h>

/*
 * Commercial status
 */
typedef enum {
  COMMERCIAL_UNKNOWN,
  COMMERCIAL_YES,
  COMMERCIAL_NO,
} th_commercial_advice_t;


/**
 * Auxiliary data for plugins
 */
typedef struct pluginaux {
  LIST_ENTRY(pluginaux) pa_link;
  struct th_plugin *pa_plugin;
} pluginaux_t;

LIST_HEAD(pluginaux_list, pluginaux);


/*
 * Dispatch timer
 */
typedef void (dti_callback_t)(void *opaque, int64_t now);

typedef struct dtimer {
  LIST_ENTRY(dtimer) dti_link;
  dti_callback_t *dti_callback;
  void *dti_opaque;
  int64_t dti_expire;
} dtimer_t;



/*
 * List / Queue header declarations
 */

LIST_HEAD(th_subscription_list, th_subscription);
RB_HEAD(channel_tree, channel);
TAILQ_HEAD(channel_queue, channel);
TAILQ_HEAD(th_dvb_adapter_queue, th_dvb_adapter);
LIST_HEAD(th_v4l_adapter_list, th_v4l_adapter);
LIST_HEAD(event_list, event);
TAILQ_HEAD(event_queue, event);
LIST_HEAD(pvr_rec_list, pvr_rec);
TAILQ_HEAD(ref_update_queue, ref_update);
LIST_HEAD(th_transport_list, th_transport);
RB_HEAD(th_transport_tree, th_transport);
TAILQ_HEAD(th_transport_queue, th_transport);
RB_HEAD(th_dvb_mux_instance_tree, th_dvb_mux_instance);
LIST_HEAD(th_stream_list, th_stream);
TAILQ_HEAD(th_pkt_queue, th_pkt);
LIST_HEAD(th_pkt_list, th_pkt);
LIST_HEAD(th_muxer_list, th_muxer);
LIST_HEAD(th_muxstream_list, th_muxstream);
LIST_HEAD(th_descrambler_list, th_descrambler);
TAILQ_HEAD(th_refpkt_queue, th_refpkt);
TAILQ_HEAD(th_muxpkt_queue, th_muxpkt);
LIST_HEAD(autorec_list, autorec);

extern time_t dispatch_clock;
extern int startupcounter;
extern struct th_transport_list all_transports;
extern struct channel_tree channel_name_tree;
extern struct pvr_rec_list pvrr_global_list;
extern struct th_subscription_list subscriptions;

struct th_transport;
struct th_stream;

/*
 * Video4linux adapter
 */
typedef struct th_v4l_adapter {

  const char *tva_name;

  LIST_ENTRY(th_v4l_adapter) tva_link;

  const char *tva_path;

  pthread_t tva_ptid;

  struct th_transport_list tva_transports;

  int tva_frequency;

  pthread_cond_t tva_run_cond;

  int tva_fd;

  void *tva_dispatch_handle;


  uint32_t tva_startcode;
  uint16_t tva_packet_len;
  int tva_lenlock;

} th_v4l_adapter_t;


/*
 * Mux instance modes
 */
typedef enum {
  TDMI_IDLE,         /* Not tuned */
  TDMI_RUNNING,      /* Tuned with a subscriber */
  TDMI_IDLESCAN,     /* Just scanning */
} tdmi_state_t;

/*
 * DVB Mux instance
 */
typedef struct th_dvb_mux_instance {
  int tdmi_refcnt;

  enum {
    TDMI_QUICKSCAN_NONE,
    TDMI_QUICKSCAN_RUNNING,
    TDMI_QUICKSCAN_WAITING,
  } tdmi_quickscan;

  RB_ENTRY(th_dvb_mux_instance) tdmi_global_link;
  RB_ENTRY(th_dvb_mux_instance) tdmi_adapter_link;
  RB_ENTRY(th_dvb_mux_instance) tdmi_qscan_link;

  struct th_dvb_adapter *tdmi_adapter;

  uint16_t tdmi_snr, tdmi_signal;
  uint32_t tdmi_ber, tdmi_uncorrected_blocks;

#define TDMI_FEC_ERR_HISTOGRAM_SIZE 10
  uint32_t tdmi_fec_err_histogram[TDMI_FEC_ERR_HISTOGRAM_SIZE];
  int      tdmi_fec_err_ptr;

  time_t tdmi_time;
  LIST_HEAD(, th_dvb_table) tdmi_tables;

  pthread_mutex_t tdmi_table_lock;

  tdmi_state_t tdmi_state;

  dtimer_t tdmi_initial_scan_timer;
  const char *tdmi_status;
  char *tdmi_last_status; /* For notification updates */

  int tdmi_quality;

  time_t tdmi_got_adapter;
  time_t tdmi_lost_adapter;

  struct dvb_frontend_parameters tdmi_fe_params;
  uint8_t tdmi_polarisation;  /* for DVB-S */
  uint8_t tdmi_switchport;    /* for DVB-S */

  uint16_t tdmi_transport_stream_id;

  char *tdmi_identifier;
  char *tdmi_network;     /* Name of network, from NIT table */

  struct th_transport_list tdmi_transports; /* via tht_mux_link */

} th_dvb_mux_instance_t;


/*
 *
 */
typedef struct th_dvb_table {
  LIST_ENTRY(th_dvb_table) tdt_link;
  char *tdt_name;
  void *tdt_handle;
  struct th_dvb_mux_instance *tdt_tdmi;
  void *tdt_opaque;
  void (*tdt_callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len,
		       uint8_t tableid, void *opaque);

  int tdt_fd;
  struct dmx_sct_filter_params *tdt_fparams;

  int tdt_quickreq;
  int tdt_count;

} th_dvb_table_t;


/*
 * DVB Adapter (one of these per physical adapter)
 */
typedef struct th_dvb_adapter {

  TAILQ_ENTRY(th_dvb_adapter) tda_global_link;

  struct th_dvb_mux_instance_tree tda_muxes;
  struct th_dvb_mux_instance_tree tda_muxes_qscan_waiting;

  th_dvb_mux_instance_t *tda_mux_current;

  const char *tda_rootpath;
  char *tda_identifier;

  char *tda_displayname;

  pthread_mutex_t tda_lock;
  pthread_cond_t tda_cond;
  TAILQ_HEAD(, dvb_fe_cmd) tda_fe_cmd_queue;
  int tda_fe_errors;

  int tda_fe_fd;
  int tda_type;
  struct dvb_frontend_info *tda_fe_info;

  char *tda_demux_path;

  char *tda_dvr_path;

  struct th_transport_list tda_transports; /* Currently bound transports */

  dtimer_t tda_fec_monitor_timer;
  dtimer_t tda_mux_scanner_timer;

} th_dvb_adapter_t;


/**
 * Descrambler superclass
 *
 * Created/Destroyed on per-transport basis upon transport start/stop
 */
typedef struct th_descrambler {
  LIST_ENTRY(th_descrambler) td_transport_link;

  void (*td_table)(struct th_descrambler *d, struct th_transport *t,
		   struct th_stream *st, uint8_t *section, int section_len);

  int (*td_descramble)(struct th_descrambler *d, struct th_transport *t,
		       struct th_stream *st, uint8_t *tsb);

  void (*td_stop)(struct th_descrambler *d);

} th_descrambler_t;



/*
 * Section callback, called when a PSI table is fully received
 */
typedef void (pid_section_callback_t)(struct th_transport *t,
				      struct th_stream *pi,
				      uint8_t *section, int section_len);

/*
 * Stream, one media component for a transport
 */
typedef struct th_stream {
  LIST_ENTRY(th_stream) st_link;
  uint16_t st_pid;
  uint8_t st_cc;             /* Last CC */
  uint8_t st_cc_valid;       /* Is CC valid at all? */

  avgstat_t st_cc_errors;
  avgstat_t st_rate;

  tv_streamtype_t st_type;
  int st_demuxer_fd;
  int st_index;
  int st_peak_presentation_delay; /* Max seen diff. of DTS and PTS */

  struct psi_section *st_section;
  int st_section_docrc;           /* Set if we should verify CRC on tables */
  pid_section_callback_t *st_got_section;
  void *st_got_section_opaque;

  /* PCR recovery */

  int st_pcr_recovery_fails;
  int64_t st_pcr_real_last;     /* realtime clock when we saw last PCR */
  int64_t st_pcr_last;          /* PCR clock when we saw last PCR */
  int64_t st_pcr_drift;

  /* For transport stream packet reassembly */

  uint8_t *st_buffer;
  int st_buffer_ptr;
  int st_buffer_size;
  int st_buffer_errors;   /* Errors accumulated for this packet */
  uint32_t st_startcond;
  uint32_t st_startcode;
  uint32_t st_startcode_offset;
  int st_parser_state;
  void *st_priv;          /* Parser private data */

  struct th_pkt *st_curpkt;
  int64_t st_curpts;
  int64_t st_curdts;
  int64_t st_prevdts;
  int64_t st_nextdts;
  int st_frame_duration;

  /* DTS generator */

  int64_t st_dts_epoch;  /* upper bits (auto generated) */
  int64_t st_last_dts;

  /* Codec */

  struct AVCodecContext *st_ctx;
  struct AVCodecParserContext *st_parser;

  /* All packets currently hanging on to us */

  struct th_pkt_list st_packets;

  /* Temporary frame store for calculating PTS */

  struct th_pkt_queue st_ptsq;
  int st_ptsq_len;

  /* Temporary frame store for calculating duration */

  struct th_pkt_queue st_durationq;

  /* Final frame store */

  struct th_pkt_queue st_pktq;

  /* ca id for this stream */

  uint16_t st_caid;

  char st_lang[4]; /* ISO 639 3-letter language code */

  /* Remuxing information */
  AVRational st_tb;

  int st_vbv_size;        /* Video buffer size (in bytes) */
  int st_vbv_delay;       /* -1 if CBR */

} th_stream_t;



/*
 * A Transport (or in MPEG TS terms: a 'service')
 */
typedef struct th_transport {
  
  const char *tht_name;

  LIST_ENTRY(th_transport) tht_hash_link;

  enum {
    TRANSPORT_DVB,
    TRANSPORT_IPTV,
    TRANSPORT_V4L,
    TRANSPORT_AVGEN,
    TRANSPORT_STREAMEDFILE,
  } tht_type;

  enum {
    TRANSPORT_IDLE,
    TRANSPORT_RUNNING,
    TRANSPORT_PROBING,
  } tht_runstatus;

  th_commercial_advice_t tht_tt_commercial_advice;

  int tht_tt_rundown_content_length;
  time_t tht_tt_clock;   /* Network clock as determined by teletext decoder */
  
  struct th_stream_list tht_streams;
  th_stream_t *tht_video;
  th_stream_t *tht_audio;
  
  int64_t  tht_pcr_drift;
  uint16_t tht_pcr_pid;
  uint16_t tht_dvb_service_id;
  uint16_t tht_pmt;

  int tht_pmt_seen;

  avgstat_t tht_cc_errors;
  avgstat_t tht_rate;
  int tht_monitor_suspend;

  int tht_disabled;

  int tht_cc_error_log_limiter;
  int tht_rate_error_log_limiter;

  int64_t tht_dts_start;
  
  LIST_ENTRY(th_transport) tht_mux_link;

  RB_ENTRY(th_transport) tht_tmp_link;

  LIST_ENTRY(th_transport) tht_active_link;

  LIST_HEAD(, th_subscription) tht_subscriptions;

  int (*tht_start_feed)(struct th_transport *t, unsigned int weight,
			int status, int force_start);

  void (*tht_stop_feed)(struct th_transport *t);

  void (*tht_config_change)(struct th_transport *t);

  const char *(*tht_networkname)(struct th_transport *t);

  const char *(*tht_sourcename)(struct th_transport *t);

  int (*tht_quality_index)(struct th_transport *t);

  struct th_muxer_list tht_muxers; /* muxers */

  /*
   * Per source type structs
   */

  union {

    struct {
      struct th_dvb_mux_instance *mux_instance;
    } dvb;

    struct {
      int frequency;
      struct th_v4l_adapter *adapter;
    } v4l;
    
    struct {
      struct in_addr group_addr;
      struct in_addr interface_addr;
      int ifindex;

      int port;
      int fd;
      void *dispatch_handle;
      enum {
	IPTV_MODE_RAWUDP,
      } mode;
    } iptv;

    struct {
      struct avgen *avgen;
    } avgen;

    struct {
      struct file_input *file_input;
    } file_input;
 } u;

  char *tht_identifier;
  char *tht_svcname;
  char *tht_provider;

  enum {
    /* Service types defined in EN 300 468 */

    ST_SDTV       = 0x1,    /* SDTV (MPEG2) */
    ST_RADIO      = 0x2,
    ST_HDTV       = 0x11,   /* HDTV (MPEG2) */
    ST_AC_SDTV    = 0x16,   /* Advanced codec SDTV */
    ST_AC_HDTV    = 0x19,   /* Advanced codec HDTV */
  } tht_servicetype;

  enum {
    THT_MPEG_TS,
    THT_OTHER,
  } tht_source_type;

  /*
   * (De)scrambling support
   */

  struct th_descrambler_list tht_descramblers;
  int tht_scrambled;
  int tht_caid;

  /**
   * Autoprobing support
   */

  struct sp *tht_sp;

  /**
   * Channel mapping
   */

  LIST_ENTRY(th_transport) tht_ch_link;
  struct channel *tht_ch;
  char *tht_chname;

  /**
   * Last known status (or error)
   */			   

  dtimer_t tht_receive_timer;  /* we use this timer to trig when a transport
				  does not receive any data at all */
  int tht_last_status;

#define TRANSPORT_STATUS_UNKNOWN        0
#define TRANSPORT_STATUS_STARTING       1
#define TRANSPORT_STATUS_OK             2
#define TRANSPORT_STATUS_NO_INPUT       3
#define TRANSPORT_STATUS_NO_DESCRAMBLER 4
#define TRANSPORT_STATUS_NO_ACCESS      5
#define TRANSPORT_STATUS_MUX_ERROR      6

} th_transport_t;



#define tht_v4l_frequency u.v4l.frequency
#define tht_v4l_adapter   u.v4l.adapter

#define tht_dvb_mux_instance u.dvb.mux_instance

#define tht_iptv_group_addr      u.iptv.group_addr
#define tht_iptv_interface_addr  u.iptv.interface_addr
#define tht_iptv_ifindex         u.iptv.ifindex
#define tht_iptv_port            u.iptv.port
#define tht_iptv_dispatch_handle u.iptv.dispatch_handle
#define tht_iptv_fd              u.iptv.fd
#define tht_iptv_mode            u.iptv.mode

#define tht_avgen                u.avgen.avgen

#define tht_file_input           u.file_input.file_input

/*
 * Storage
 */
typedef struct th_storage {
  unsigned int ts_offset;
  unsigned int ts_refcount;
  int ts_fd;
  char *ts_filename;
} th_storage_t;

/*
 * A packet
 */

#define PKT_I_FRAME 1
#define PKT_P_FRAME 2
#define PKT_B_FRAME 3


typedef struct th_pkt {
  TAILQ_ENTRY(th_pkt) pkt_queue_link;
  uint8_t pkt_on_stream_queue;
  uint8_t pkt_frametype;
  uint8_t pkt_commercial;

  th_stream_t *pkt_stream;

  int64_t pkt_dts;
  int64_t pkt_pts;
  int pkt_duration;
  int pkt_refcount;


  th_storage_t *pkt_storage;
  TAILQ_ENTRY(th_pkt) pkt_disk_link;
  int pkt_storage_offset;

  uint8_t *pkt_payload;
  int pkt_payloadlen;
  TAILQ_ENTRY(th_pkt) pkt_mem_link;
} th_pkt_t;

/**
 * Referenced packets
 */
typedef struct th_refpkt {
  TAILQ_ENTRY(th_refpkt) trp_link;
  th_pkt_t *trp_pkt;
} th_refpkt_t;


/**
 * Muxed packets
 */
typedef struct th_muxpkt {
  TAILQ_ENTRY(th_muxpkt) tm_link;
  int64_t tm_pcr;
  int64_t tm_dts;

  int tm_contentsize;
  int64_t tm_deadline;   /* Packet transmission deadline */

  uint8_t tm_pkt[0];
} th_muxpkt_t;


/*
 * A mux stream reader
 */


struct th_subscription;
struct th_muxstream;

typedef void (th_mux_output_t)(void *opaque, struct th_muxstream *tms,
			       th_pkt_t *pkt);


typedef struct th_muxfifo {
  struct th_muxpkt_queue tmf_queue;
  uint32_t tmf_len;
  int tmf_contentsize;

} th_muxfifo_t;



typedef struct th_muxstream {

  LIST_ENTRY(th_muxstream) tms_muxer_link0;
  struct th_muxer *tms_muxer;
  th_stream_t *tms_stream;
  int tms_index; /* Used as PID or whatever */

  struct th_refpkt_queue tms_lookahead;

  int tms_lookahead_depth;  /* bytes in lookahead queue */
  int tms_lookahead_packets;

  th_muxfifo_t tms_cbr_fifo;
  th_muxfifo_t tms_delivery_fifo;

  int64_t tms_deadline;
  int64_t tms_delay;
  int64_t tms_delta;
  int64_t tms_mux_offset;

  dtimer_t tms_mux_timer;

  /* MPEG TS multiplex stuff */

  int tms_sc; /* start code */
  int tms_cc;

  int64_t tms_corruption_interval;
  int64_t tms_corruption_last;
  int tms_corruption_counter;

  /* Memebers used when running with ffmpeg */
  
  struct AVStream *tms_avstream;
  int tms_decoded;

  int tms_blockcnt;
  int64_t tms_dl;
  int64_t tms_staletime;
} th_muxstream_t;


/*
 *
 */


typedef void (th_mux_newpkt_t)(struct th_muxer *tm, th_stream_t *st,
			       th_pkt_t *pkt);

typedef struct th_muxer {

  th_mux_newpkt_t *tm_new_pkt;

  LIST_ENTRY(th_muxer) tm_transport_link;
  int tm_linked;

  int64_t tm_offset;

  struct th_muxstream_list tm_streams;

  struct th_subscription *tm_subscription;

  th_mux_output_t *tm_output;
  void *tm_opaque;
  

  enum {
    TM_IDLE,
    TM_WAITING_FOR_LOCK,
    TM_PLAY,
    TM_PAUSE,
  } tm_status;

} th_muxer_t;


/**
 * Output muxer for usage via ffmpeg (avformat)
 */
typedef struct th_ffmuxer {
  th_muxer_t tffm_muxer;
  
  enum {
    TFFM_STOP,
    TFFM_WAIT_SUBSCRIPTION,
    TFFM_WAIT_FOR_START,
    TFFM_WAIT_AUDIO_LOCK,
    TFFM_WAIT_VIDEO_LOCK,
    TFFM_RUNNING,
    TFFM_COMMERCIAL,

  } tffm_state;

  int tffm_header_written;

  char *tffm_printname;

  struct AVFormatContext *tffm_avfctx;
} th_ffmuxer_t;




/*
 *  Teletext
 */
typedef struct tt_page {
  int ttp_page;
  int ttp_subpage;
  int ttp_ver;
  unsigned char ttp_pagebuf[23*40 + 1];
} tt_page_t;

typedef struct tt_mag {
  tt_page_t *pageptr;
} tt_mag_t;

typedef struct tt_decoder {
  tt_mag_t mags[8];
  tt_page_t *pages[900];
  int magazine_serial;
} tt_decoder_t;



/*
 * Channel definition
 */ 
typedef struct channel {
  
  RB_ENTRY(channel) ch_name_link;
  char *ch_name;
  char *ch_sname;

  RB_ENTRY(channel) ch_identifier_link;
  int ch_id;		    

  LIST_HEAD(, th_transport) ch_transports;
  LIST_HEAD(, th_subscription) ch_subscriptions;


  struct tt_decoder ch_tt;

  enum {
    COMMERCIAL_DETECT_NONE,
    COMMERCIAL_DETECT_TTP192,
  } ch_commercial_detection;

  struct event_queue ch_epg_events;
  struct event *ch_epg_cur_event;
  char *ch_icon;

  struct pvr_rec_list ch_pvrrs;
  
  struct autorec_list ch_autorecs;

} channel_t;


/*
 * Subscription
 */

typedef enum {
  TRANSPORT_AVAILABLE,
  TRANSPORT_UNAVAILABLE,
} subscription_event_t;

typedef void (subscription_callback_t)(struct th_subscription *s,
				       subscription_event_t event,
				       void *opaque);

typedef void (subscription_raw_input_t)(struct th_subscription *s,
					void *data, int len,
					th_stream_t *st,
					void *opaque);



typedef void (subscription_status_callback_t)(struct th_subscription *s,
					      int status,
					      void *opaque);

typedef struct th_subscription {
  LIST_ENTRY(th_subscription) ths_global_link;
  int ths_weight;

  LIST_ENTRY(th_subscription) ths_channel_link;
  struct channel *ths_channel;          /* May be NULL if channel has been
					   destroyed during the
					   subscription */

  LIST_ENTRY(th_subscription) ths_transport_link;
  struct th_transport *ths_transport;   /* if NULL, ths_transport_link
					   is not linked */

  LIST_ENTRY(th_subscription) ths_subscriber_link; /* Caller is responsible
						      for this link */

  char *ths_title; /* display title */
  time_t ths_start;  /* time when subscription started */
  int ths_total_err; /* total errors during entire subscription */

  subscription_callback_t *ths_callback;
  void *ths_opaque;
  uint32_t ths_u32;

  subscription_raw_input_t *ths_raw_input;

  th_muxer_t *ths_muxer;

  subscription_status_callback_t *ths_status_callback;

} th_subscription_t;

/**
 * EPG content group
 *
 * Based on the content types defined in EN 300 468
 */


typedef struct epg_content_group {
  const char *ecg_name;
  struct epg_content_type *ecg_types[16];
} epg_content_group_t;

typedef struct epg_content_type {
  const char *ect_name;
  struct event_list ect_events;
  epg_content_group_t *ect_group;
} epg_content_type_t;

/*
 * EPG event
 */
typedef struct event {
  channel_t *e_channel;
  TAILQ_ENTRY(event) e_channel_link;

  LIST_ENTRY(event) e_hash_link;
  LIST_ENTRY(event) e_tmp_link;

  LIST_ENTRY(event) e_content_type_link;
  epg_content_type_t *e_content_type;

  time_t e_start;  /* UTC time */
  int e_duration;  /* in seconds */

  const char *e_title;   /* UTF-8 encoded */
  const char *e_desc;    /* UTF-8 encoded */

  uint16_t e_event_id;  /* DVB event id */

  uint32_t e_tag;

  int e_source; /* higer is better, and we never downgrade */

#define EVENT_SRC_XMLTV 1
#define EVENT_SRC_DVB   2

} event_t;

config_entry_t *find_mux_config(const char *muxtype, const char *muxname);
char *utf8toprintable(const char *in);
char *utf8tofilename(const char *in);
const char *htstvstreamtype2txt(tv_streamtype_t s);
uint32_t tag_get(void);
extern const char *settings_dir;
FILE *settings_open_for_write(const char *name);
FILE *settings_open_for_read(const char *name);
extern const char *sys_warning;

static inline unsigned int tvh_strhash(const char *s, unsigned int mod)
{
  unsigned int v = 5381;
  while(*s)
    v += (v << 5) + v + *s++;
  return v % mod;
}

#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) > (b) ? (a) : (b))

void tvhlog(int severity, const char *subsys, const char *fmt, ...);

#define	LOG_EMERG	0	/* system is unusable */
#define	LOG_ALERT	1	/* action must be taken immediately */
#define	LOG_CRIT	2	/* critical conditions */
#define	LOG_ERR		3	/* error conditions */
#define	LOG_WARNING	4	/* warning conditions */
#define	LOG_NOTICE	5	/* normal but significant condition */
#define	LOG_INFO	6	/* informational */
#define	LOG_DEBUG	7	/* debug-level messages */

#endif /* TV_HEAD_H */