/* 
 * Copyright (C) 2001 Rich Wareham <richwareham@users.sourceforge.net>
 * 
 * This file is part of libdvdnav, a DVD navigation library.
 * 
 * libdvdnav 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 2 of the License, or
 * (at your option) any later version.
 * 
 * libdvdnav 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
 *
 * $Id: dvdnav.h,v 1.31 2003/06/09 15:17:44 mroi Exp $
 *
 */

#ifndef __STREAM_DVDNAV_H_
#define __STREAM_DVDNAV_H_

#include "stream_dvdnav.h"

#ifdef USE_DVDREAD

#ifdef USE_MPDVDKIT
#if (USE_MPDVDKIT == 2)
#include "libmpdvdkit2/dvd_reader.h"
#include "libmpdvdkit2/ifo_types.h"
#include "libmpdvdkit2/ifo_read.h"
#include "libmpdvdkit2/nav_read.h"
#else
#include "libmpdvdkit/dvd_reader.h"
#include "libmpdvdkit/ifo_types.h"
#include "libmpdvdkit/ifo_read.h"
#include "libmpdvdkit/nav_read.h"
#endif
#else
#include <dvdread/dvd_reader.h>
#include <dvdread/ifo_types.h>
#include <dvdread/ifo_read.h>
#include <dvdread/nav_read.h>
#endif


extern int dvd_nav_skip_opening;
extern int dvd_nav_still;
extern int dvdnav_menutype;		/* dvdnav menu type: 0-SPU, 1-BOX, 2-SPU&BOX */
extern int dvdnav_continue_play;
extern int dvdnav_go_title;		/* dvdnav_title_play */
extern int dvdnav_go_part;		/* dvdnav_part_play */
extern int dvdnav_go_menu;		/* call main menu */
extern int dvdnav_go_audio;		/* dvdnav set new audio stream */
extern int dvdnav_go_spu;		/* dbdnav set new spu stream */
#ifdef USE_MPDVDNAV_TRACE
extern int dvdnav_trace;		/* print trace messages (only devel)*/
#endif
extern char* dvdmenu_lang;		/* nav menu language */

#ifdef HAVE_NEW_GUI
extern int	dvdnav_window_width;
extern int	dvdnav_window_height;
extern int	dvdnav_window_orig_width;
extern int	dvdnav_window_orig_height;
extern int	dvdnav_mouse_x;
extern int	dvdnav_mouse_y;
extern int	dvdnav_mouse_button;
extern int	dvdnav_mouse_set;
#endif

// dvdnav menu button types
#define DVDNAV_MENUTYPE_SPU	0
#define DVDNAV_MENUTYPE_BOX	1
#define DVDNAV_MENUTYPE_SPU_BOX	2

#undef max
#define max(x,y) ((x) > (y) ? (x) : (y))
#undef min
#define min(x,y) ((x) < (y) ? (x) : (y))

typedef struct {
  int event;             /* event number fromd dvdnav_events.h */
  void * details;        /* event details */
  int len;               /* bytes in details */
} dvdnav_event_t;

#ifndef HAVE_ASSERT_H
 #define assert( ... ) do {} while(0)
#endif




// ############################ dvd_types.h start ####################################
/*
 * DVD Menu ID
 * (see dvdnav_menu_call())
 */
typedef enum {
  /* When used in VTS domain, DVD_MENU_Escape behaves like DVD_MENU_Root,
   * but from within a menu domain, DVD_MENU_Escape resumes playback. */
  DVD_MENU_Escape     = 0,
  DVD_MENU_Title      = 2,
  DVD_MENU_Root       = 3,
  DVD_MENU_Subpicture = 4,
  DVD_MENU_Audio      = 5,
  DVD_MENU_Angle      = 6,
  DVD_MENU_Part       = 7
} DVDMenuID_t;


/*
 * Structure containing info on highlight areas
 * (see dvdnav_get_highlight_area())
 */
typedef struct {
  uint32_t palette;     /* The CLUT entries for the highlight palette 
			   (4-bits per entry -> 4 entries) */
  uint16_t sx,sy,ex,ey; /* The start/end x,y positions */
  uint32_t pts;         /* Highlight PTS to match with SPU */

  /* button number for the SPU decoder/overlaying engine */
  uint32_t buttonN;
} dvdnav_highlight_area_t;


/* the following types are currently unused */

// ############################ dvd_types.h end ######################################

/* Maximum length of an error string */
#define MAX_ERR_LEN 255

/* Use the POSIX PATH_MAX if available */
#ifdef PATH_MAX
#define MAX_PATH_LEN PATH_MAX
#else
#define MAX_PATH_LEN 255 /* Arbitrary */
#endif

#ifndef DVD_VIDEO_LB_LEN
#define DVD_VIDEO_LB_LEN 2048
#endif


// ############################ decoder.h start ######################################
/* link command types */
typedef enum {
  LinkNoLink  = 0,

  LinkTopC    = 1,
  LinkNextC   = 2,
  LinkPrevC   = 3,

  LinkTopPG   = 5,
  LinkNextPG  = 6,
  LinkPrevPG  = 7,

  LinkTopPGC  = 9,
  LinkNextPGC = 10,
  LinkPrevPGC = 11,
  LinkGoUpPGC = 12,
  LinkTailPGC = 13,

  LinkRSM     = 16,

  LinkPGCN,
  LinkPTTN,
  LinkPGN,
  LinkCN,

  Exit,

  JumpTT, /* 22 */
  JumpVTS_TT,
  JumpVTS_PTT,

  JumpSS_FP,
  JumpSS_VMGM_MENU,
  JumpSS_VTSM,
  JumpSS_VMGM_PGC,

  CallSS_FP, /* 29 */
  CallSS_VMGM_MENU,
  CallSS_VTSM,
  CallSS_VMGM_PGC,

  PlayThis
} link_cmd_t;

/* a link's data set */
typedef struct {
  link_cmd_t command;
  uint16_t   data1;
  uint16_t   data2;
  uint16_t   data3;
} link_t;

/* the VM registers */
typedef struct {
  uint16_t SPRM[24];
  uint16_t GPRM[16];
  uint8_t  GPRM_mode[16];  /* Need to have some thing to indicate normal/counter mode for every GPRM */
  struct timeval GPRM_time[16]; /* For counter mode */
} registers_t;

/* a VM command data set */
typedef struct {
  uint64_t instruction;
  uint64_t examined;
  registers_t *registers;
} vm_command_t;

/* the big VM function, executing the given commands and writing
 * the link where to continue, the return value indicates if a jump
 * has been performed */
int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands, 
	       registers_t *registers, link_t *return_values);

/* extracts some bits from the command */
uint32_t vm_getbits(vm_command_t* command, int32_t start, int32_t count);

#ifdef USE_MPDVDNAV_TRACE
/* for debugging: prints a link in readable form */
void vm_print_link(link_t value);

/* for debugging: dumps VM registers */
void vm_print_registers( registers_t *registers );
#endif
// ############################# decoder.h end #######################################

// ############################ dvdnav_events.h start #########################

/*
 * DVDNAV_BLOCK_OK
 *
 * A regular data block from the DVD has been returned.
 * This one should be demuxed and decoded for playback.
 */
#define DVDNAV_BLOCK_OK			 0

/*
 * DVDNAV_NOP
 *
 * Just ignore this.
 */
#define DVDNAV_NOP			 1

/*
 * DVDNAV_STILL_FRAME
 *
 * We have reached a still frame. The player application should wait
 * the amount of time specified by the still's length while still handling
 * user input to make menus and other interactive stills work.
 * The last delivered frame should be kept showing.
 * Once the still has timed out, call dvdnav_skip_still().
 * A length of 0xff means an infinite still which has to be skipped
 * indirectly by some user interaction.
 */
#define DVDNAV_STILL_FRAME		 2

typedef struct {
  /* The length (in seconds) the still frame should be displayed for,
   * or 0xff if infinite. */
  int length;
} dvdnav_still_event_t;

/*
 * DVDNAV_SPU_STREAM_CHANGE
 *
 * Inform the SPU decoding/overlaying engine to switch SPU channels.
 */
#define DVDNAV_SPU_STREAM_CHANGE	 3

typedef struct {
  /* The physical (MPEG) stream number for widescreen SPU display.
   * Use this, if you blend the SPU on an anamorphic image before
   * unsqueezing it. */
  int physical_wide;
  /* The physical (MPEG) stream number for letterboxed display.
   * Use this, if you blend the SPU on an anamorphic image after
   * unsqueezing it. */
  int physical_letterbox;
  /* The physical (MPEG) stream number for pan&scan display.
   * Use this, if you blend the SPU on an anamorphic image after
   * unsqueezing it the pan&scan way. */
  int physical_pan_scan;
  /* The logical (DVD) stream number. */
  int logical;
} dvdnav_spu_stream_change_event_t;

/*
 * DVDNAV_AUDIO_STREAM_CHANGE
 *
 * Inform the audio decoder to switch channels.
 */
#define DVDNAV_AUDIO_STREAM_CHANGE	 4

typedef struct {
  /* The physical (MPEG) stream number. */
  int physical;
  /* The logical (DVD) stream number. */
  int logical;
} dvdnav_audio_stream_change_event_t;

/*
 * DVDNAV_VTS_CHANGE
 *
 * Some status information like video aspect and video scale permissions do
 * not change inside a VTS. Therefore this event can be used to query such
 * information only when necessary and update the decoding/displaying
 * accordingly.
 */
#define DVDNAV_VTS_CHANGE		 5

typedef struct {
  int old_vtsN;                 /* the old VTS number */
  dvd_read_domain_t old_domain; /* the old domain */
  int new_vtsN;                 /* the new VTS number */
  dvd_read_domain_t new_domain; /* the new domain */
} dvdnav_vts_change_event_t;

/*
 * DVDNAV_CELL_CHANGE
 *
 * Some status information like the current Title and Part numbers do not
 * change inside a cell. Therefore this event can be used to query such
 * information only when necessary and update the decoding/displaying
 * accordingly.
 * Some useful information for accurate time display is also reported
 * together with this event.
 */
#define DVDNAV_CELL_CHANGE		 6

typedef struct {
  int     cellN;       /* the new cell number */
  int     pgN;         /* the current program number */
  int64_t cell_length; /* the length of the current cell in PTS ticks */
  int64_t pg_length;   /* the length of the current program in PTS ticks */
  int64_t pgc_length;  /* the length of the current program chain in PTS ticks */
  int64_t cell_start;  /* the start time of the current cell relatively to the PGC in PTS ticks */
  int64_t pg_start;    /* the start time of the current PG relatively to the PGC in PTS ticks */
} dvdnav_cell_change_event_t;

/*
 * DVDNAV_NAV_PACKET
 *
 * NAV packets are useful for various purposes. They define the button
 * highlight areas and VM commands of DVD menus, so they should in any
 * case be sent to the SPU decoder/overlaying engine for the menus to work.
 * NAV packets also provide a way to detect PTS discontinuities, because
 * they carry the start and end PTS values for the current VOBU.
 * (pci.vobu_s_ptm and pci.vobu_e_ptm) Whenever the start PTS of the
 * current NAV does not match the end PTS of the previous NAV, a PTS
 * discontinuity has occured.
 * NAV packets can also be used for time display, because they are
 * timestamped relatively to the current Cell.
 */
#define DVDNAV_NAV_PACKET		 7

/*
 * DVDNAV_STOP
 *
 * Applications should end playback here. A subsequent dvdnav_get_next_block()
 * call will restart the VM from the beginning of the DVD.
 */
#define DVDNAV_STOP			 8

/*
 * DVDNAV_HIGHLIGHT
 *
 * The current button highlight changed. Inform the overlaying engine to
 * highlight a different button. Please note, that at the moment only mode 1
 * highlights are reported this way. That means, when the button highlight
 * has been moved around by some function call, you will receive an event
 * telling you the new button. But when a button gets activated, you have
 * to handle the mode 2 highlighting (that is some different colour the
 * button turns to on activation) in your application.
 */
#define DVDNAV_HIGHLIGHT		 9

typedef struct {
  int display;
  uint32_t palette;
  uint16_t sx,sy,ex,ey; /* The start/end x,y positions */
  uint32_t pts;         /* Highlight PTS to match with SPU */
  uint32_t buttonN;
} dvdnav_highlight_event_t;

/*
 * DVDNAV_SPU_CLUT_CHANGE
 *
 * Inform the SPU decoder/overlaying engine to update its colour lookup table.
 * The CLUT is given as 16 uint32_t's in the buffer.
 */
#define DVDNAV_SPU_CLUT_CHANGE		10

/*
 * DVDNAV_HOP_CHANNEL
 *
 * A non-seamless operation has been performed. Applications can drop all
 * their internal fifo's content, which will speed up the response.
 */
#define DVDNAV_HOP_CHANNEL		12

/*
 * DVDNAV_WAIT
 *
 * We have reached a point in DVD playback, where timing is critical.
 * Player application with internal fifos can introduce state
 * inconsistencies, because libdvdnav is always the fifo's length
 * ahead in the stream compared to what the application sees.
 * Such applications should wait until their fifos are empty
 * when they receive this type of event.
 * Once this is achieved, call dvdnav_skip_wait().
 */
#define DVDNAV_WAIT			13

// ############################ dvdnav_events.h start #########################

// ############################## remap.h start ###############################

typedef struct block_s block_t;

typedef struct remap_s remap_t;

remap_t* remap_loadmap( char *title);

unsigned long remap_block( 
	remap_t *map, int domain, int title, int program, 
	unsigned long cblock, unsigned long offset);

// ############################### remap.h end ################################

// ################################# vm.h start ###############################
/* DOMAIN enum */

typedef enum {
  FP_DOMAIN   = 1,
  VTS_DOMAIN  = 2,
  VMGM_DOMAIN = 4,
  VTSM_DOMAIN = 8
} domain_t;  

/**
 * State: SPRM, GPRM, Domain, pgc, pgN, cellN, ?
 */
typedef struct {
  registers_t registers;
  
  domain_t  domain;
  int       vtsN;         /* 0 is vmgm? */
  pgc_t    *pgc;          /* either this or 'int pgcN' is enough? */
  int       pgcN;         /* but provide pgcN for quick lookup */
  int       pgN;          /* is this needed? can allways fid pgN from cellN? */
  int       cellN;
  int32_t   cell_restart; /* get cell to restart */
  int       blockN;
  
  /* Resume info */
  int      rsm_vtsN;
  int      rsm_blockN;    /* of nav_packet */
  uint16_t rsm_regs[5];   /* system registers 4-8 */
  int      rsm_pgcN;
  int      rsm_cellN;
} dvd_state_t;

typedef struct vm_position_s {
  int16_t  button;        /* Button highlighted */
  int32_t  vts;           /* vts number to use */
  domain_t domain;        /* domain to use */
  int32_t  spu_channel;   /* spu channel to use */
  int32_t  angle_channel; /* angle channel to use */
  int32_t  audio_channel; /* audio channel to use */
  int32_t  hop_channel;   /* channel hopping. E.g menu button pressed */
#if 0
  /* currently unused */
  int32_t  title;         /* title number */
  int32_t  chapter;       /* chapter number */
#endif
  int32_t  cell;          /* cell number */
  int32_t  cell_restart;  /* get cell to restart */
  int32_t  cell_start;    /* sector number of start of current cell in use */
  int32_t  still;         /* is cell still */
  int32_t  block;         /* block number within cell in use */
} vm_position_t;

typedef struct {
  dvd_reader_t *dvd;
  ifo_handle_t *vmgi;
  ifo_handle_t *vtsi;
  dvd_state_t   state;
  int32_t       hop_channel;
  char          dvd_name[50];
  remap_t      *map;
  int           stopped;
#ifdef USE_MPDVDNAV
  int 	   	pgc_post_flag;
  int		auto_action_mode;

#endif
} vm_t;

/* magic number for seeking hops */
#define HOP_SEEK 0x1000


/*  Audio stream number */
#define AST_REG      registers.SPRM[1]
/*  Subpicture stream number */
#define SPST_REG     registers.SPRM[2]
/*  Angle number */
#define AGL_REG      registers.SPRM[3]
/*  Title Track Number */
#define TTN_REG      registers.SPRM[4]
/*  VTS Title Track Number */
#define VTS_TTN_REG  registers.SPRM[5]
/*  PGC Number for this Title Track */
#define TT_PGCN_REG  registers.SPRM[6]
/*  Current Part of Title (PTT) number for (One_Sequential_PGC_Title) */
#define PTTN_REG     registers.SPRM[7]
/*  Highlighted Button Number (btn nr 1 == value 1024) */
#define HL_BTNN_REG  registers.SPRM[8]
/*  Parental Level */
#define PTL_REG      registers.SPRM[13]

/* Initialisation & destruction */
vm_t *vm_new_vm(void);
void  vm_free_vm(vm_t *vm);

/* IFO access */
ifo_handle_t *vm_get_vmgi(vm_t *vm);
ifo_handle_t *vm_get_vtsi(vm_t *vm);

/* Reader Access */
dvd_reader_t *vm_get_dvd_reader(vm_t *vm);

/* Basic Handling */
void vm_start(vm_t *vm);
void vm_stop(vm_t *vm);
int  vm_reset(vm_t *vm, const char *dvdroot);

/* copying and merging  - useful for try-running an operation */
vm_t *vm_new_copy(vm_t *vm);
void  vm_merge(vm_t *target, vm_t *source);
void  vm_free_copy(vm_t *vm);

/* regular playback */
void vm_position_get(vm_t *vm, vm_position_t *position);
void vm_get_next_cell(vm_t *vm);

/* Jumping - all these return 1, if a hop has been performed */
int vm_jump_pg(vm_t *vm, int pg);
int vm_jump_cell_block(vm_t *vm, int cell, int block);
int vm_jump_title_part(vm_t *vm, int title, int part);
int vm_jump_top_pg(vm_t *vm);
int vm_jump_next_pg(vm_t *vm);
int vm_jump_prev_pg(vm_t *vm);
int vm_jump_up(vm_t *vm);
int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid);
int vm_jump_resume(vm_t *vm);
int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd);

/* getting information */
int vm_get_current_menu(vm_t *vm, int *menuid);
int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result);
int vm_get_audio_stream(vm_t *vm, int audioN);
int vm_get_subp_stream(vm_t *vm, int subpN, int mode);
int vm_get_audio_active_stream(vm_t *vm);
int vm_get_subp_active_stream(vm_t *vm, int mode);
void vm_get_angle_info(vm_t *vm, int *current, int *num_avail);
#if 0
/* currently unused */
void vm_get_audio_info(vm_t *vm, int *current, int *num_avail);
void vm_get_subp_info(vm_t *vm, int *current, int *num_avail);
void vm_get_video_res(vm_t *vm, int *width, int *height);
#endif
int  vm_get_video_aspect(vm_t *vm);
int  vm_get_video_scale_permission(vm_t *vm);
video_attr_t vm_get_video_attr(vm_t *vm);
audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN);
subp_attr_t  vm_get_subp_attr(vm_t *vm, int streamN);

#ifdef USE_MPDVDNAV_TRACE
/* Debug */
void vm_position_print(vm_t *vm, vm_position_t *position);
#endif

#ifdef USE_MPDVDNAV
int vm_get_PGCN(vm_t *vm);
#endif

// ################################# vm.h end #################################

// ############################## vmcmd.h start ###############################
void vm_print_mnemonic(vm_cmd_t *command);
void vm_print_cmd(int row, vm_cmd_t *command);
// ############################### vmcmd.h end ################################

// ######################### dvdnav_internal.h start #################################
#ifdef WIN32

/* pthread_mutex_* wrapper for win32 */
#include <windows.h>
#include <process.h>
typedef CRITICAL_SECTION pthread_mutex_t;
#define pthread_mutex_init(a, b) InitializeCriticalSection(a)
#define pthread_mutex_lock(a)    EnterCriticalSection(a)
#define pthread_mutex_unlock(a)  LeaveCriticalSection(a)
#define pthread_mutex_destroy(a)

/* replacement gettimeofday implementation */
#include <sys/timeb.h>
static inline int gettimeofday( struct timeval *tv, void *tz )
{
  struct timeb t;
  ftime( &t );
  tv->tv_sec = t.time;
  tv->tv_usec = t.millitm * 1000;
  return 0;
}
#include <io.h> /* read() */
#define lseek64 _lseeki64

#else

#include <pthread.h>

#endif /* WIN32 */


typedef struct read_cache_s read_cache_t;


typedef struct dvdnav_vobu_s {
  int32_t vobu_start;  /* Logical Absolute. MAX needed is 0x300000 */
  int32_t vobu_length;
  int32_t blockN;      /* Relative offset */
  int32_t vobu_next;   /* Relative offset */
} dvdnav_vobu_t;  
   
/** The main DVDNAV type **/

struct dvdnav_s {
  /* General data */
  char        path[MAX_PATH_LEN]; /* Path to DVD device/dir */
  dvd_file_t *file;               /* Currently opened file */
 
  /* Position data */
  vm_position_t position_next;
  vm_position_t position_current;
  dvdnav_vobu_t vobu;  

  /* NAV data */
  pci_t pci;
  dsi_t dsi;
  uint32_t last_cmd_nav_lbn;      /* detects when a command is issued on an already left NAV */
  
  /* Flags */
  int skip_still;                 /* Set when skipping a still */
  int sync_wait;                  /* applications should wait till they are in sync with us */
  int sync_wait_skip;             /* Set when skipping wait state */
  int spu_clut_changed;           /* The SPU CLUT changed */ 
  int started;                    /* vm_start has been called? */
  int use_read_ahead;             /* 1 - use read-ahead cache, 0 - don't */
  int pgc_based;                  /* positioning works PGC based instead of PG based */
  
  /* VM */
  vm_t *vm;
  pthread_mutex_t vm_lock;

  /* Read-ahead cache */
  read_cache_t *cache;

  /* Errors */
  char err_str[MAX_ERR_LEN];
};
// ######################### dvdnav_internal.h end ###################################


// ############################# dvdnav.h start ######################################



typedef struct dvdnav_s dvdnav_t;
typedef int32_t dvdnav_status_t;

#define DVDNAV_STATUS_ERR 0
#define DVDNAV_STATUS_OK  1

dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path);

/*
 * Closes a dvdnav_t previously opened with dvdnav_open(), freeing any 
 * memory associated with it.
 */
dvdnav_status_t dvdnav_close(dvdnav_t *self);

/*
 * Resets the DVD virtual machine and cache buffers.
 */
dvdnav_status_t dvdnav_reset(dvdnav_t *self);

/*
 * Fills a pointer with a value pointing to a string describing
 * the path associated with an open dvdnav_t. It assigns *path to NULL
 * on error.
 */
dvdnav_status_t dvdnav_path(dvdnav_t *self, const char **path);

/*
 * Returns a human-readable string describing the last error.
 */
const char* dvdnav_err_to_string(dvdnav_t *self);


/*********************************************************************
 * changing and reading DVD player characteristics                   *
 *********************************************************************/

/*
 * These functions allow you to manipulate the various global characteristics
 * of the DVD playback engine.
 */

/*
 * Sets the region mask (bit 0 set implies region 1, bit 1 set implies
 * region 2, etc) of the virtual machine. Generally you will only need to set
 * this if you are playing RCE discs which query the virtual machine as to its
 * region setting. 
 *
 * This has _nothing_ to do with the region setting of the DVD drive.
 */
dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *self, int32_t region_mask);

/*
 * Returns the region mask (bit 0 set implies region 1, bit 1 set implies
 * region 2, etc) of the virtual machine.
 *
 * This has _nothing_ to do with the region setting of the DVD drive.
 */
dvdnav_status_t dvdnav_get_region_mask(dvdnav_t *self, int32_t *region_mask);

/*
 * Specify whether read-ahead caching should be used. You may not want this if your
 * decoding engine does its own buffering.
 *
 * The default read-ahead cache does not use an additional thread for the reading
 * (see read_cache.c for a threaded cache, but note that this code is currently
 * unmaintained). It prebuffers on VOBU level by reading ahead several buffers
 * on every read request. The speed of this prebuffering has been optimized to
 * also work on slow DVD drives.
 *
 * If in addition you want to prevent memcpy's to improve performance, have a look
 * at dvdnav_get_next_cache_block().
 */
dvdnav_status_t dvdnav_set_readahead_flag(dvdnav_t *self, int32_t read_ahead_flag);

/*
 * Query whether read-ahead caching/buffering will be used.
 */
dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *self, int32_t *read_ahead_flag);

/*
 * Specify whether the positioning works PGC or PG based.
 * Programs (PGs) on DVDs are similar to Chapters and a program chain (PGC)
 * usually covers a whole feature. This affects the behaviour of the
 * functions dvdnav_get_position() and dvdnav_sector_search(). See there.
 * Default is PG based positioning.
 */
dvdnav_status_t dvdnav_set_PGC_positioning_flag(dvdnav_t *self, int32_t pgc_based_flag);

/*
 * Query whether positioning is PG or PGC based.
 */
dvdnav_status_t dvdnav_get_PGC_positioning_flag(dvdnav_t *self, int32_t *pgc_based_flag);

/*********************************************************************
 * reading data                                                      *
 *********************************************************************/

/*
 * These functions are used to poll the playback enginge and actually get data 
 * off the DVD.
 */

/*
 * Attempts to get the next block off the DVD and copies it into the buffer 'buf'. 
 * If there is any special actions that may need to be performed, the value
 * pointed to by 'event' gets set accordingly.
 *
 * If 'event' is DVDNAV_BLOCK_OK then 'buf' is filled with the next block
 * (note that means it has to be at /least/ 2048 bytes big). 'len' is
 * then set to 2048.
 *
 * Otherwise, buf is filled with an appropriate event structure and
 * len is set to the length of that structure.
 *
 * See the dvdnav_events.h header for information on the various events.
 */
dvdnav_status_t dvdnav_get_next_block(dvdnav_t *self, uint8_t *buf,
				      int32_t *event, int32_t *len);

/*
 * This basically does the same as dvdnav_get_next_block. The only difference is
 * that it avoids a memcopy, when the requested block was found in the cache.
 * I such a case (cache hit) this function will return a different pointer than
 * the one handed in, pointing directly into the relevant block in the cache.
 * Those pointers must _never_ be freed but instead returned to the library via
 * dvdnav_free_cache_block().
 */
dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *self, uint8_t **buf,
					    int32_t *event, int32_t *len);

/*
 * All buffers which came from the internal cache (when dvdnav_get_next_cache_block()
 * returned a buffer different from the one handed in) have to be freed with this
 * function. Although handing in other buffers not from the cache doesn't cause any harm.
 */
dvdnav_status_t dvdnav_free_cache_block(dvdnav_t *self, unsigned char *buf);

/*
 * If we are currently in a still-frame this function skips it.
 *
 * See also the DVDNAV_STILL_FRAME event.
 */
dvdnav_status_t dvdnav_still_skip(dvdnav_t *self);

#ifdef USE_MPDVDNAV
/*
 * If we are currently in a still-frame this function repeat it.
 *
 * See also the DVDNAV_STILL_FRAME event.
 */
dvdnav_status_t dvdnav_still_back(dvdnav_t *self);
/*
 * Clear wait flags and repeat current cell.
 */
dvdnav_status_t dvdnav_wait_back(dvdnav_t *self);
/*
 * Clear wait & still flags
 */
dvdnav_status_t dvdnav_wait_still_clear(dvdnav_t *self);
/*
 * Wheather the still event will be in the current cell?
 */
dvdnav_status_t dvdnav_is_still_cell(dvdnav_t *self, int *flag);
#endif
/*
 * If we are currently in WAIT state, that is: the application is required to
 * wait for its fifos to become empty, calling this signals libdvdnav that this
 * is achieved and that it can continue.
 *
 * See also the DVDNAV_WAIT event.
 */
dvdnav_status_t dvdnav_wait_skip(dvdnav_t *self);

/*
 * Returns the still time from the currently playing cell.
 * The still time is given in seconds with 0xff meaning an indefinite still.
 *
 * This function can be used to detect still frames before they are reached.
 * Some players might need this to prepare for a frame to be shown for a
 * longer time than usual.
 */
uint32_t dvdnav_get_next_still_flag(dvdnav_t *self);

/*
 * Stops playback. The next event obtained with one of the get_next_block
 * functions will be a DVDNAV_STOP event.
 *
 * It is not required to call this before dvdnav_close().
 */
dvdnav_status_t dvdnav_stop(dvdnav_t *self);


/*********************************************************************
 * title/part navigation                                             *
 *********************************************************************/

/*
 * Returns the number of titles on the disk.
 */
dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *self, int32_t *titles);

/*
 * Returns the number of parts within the given title.
 */
dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *self, int32_t title, int32_t *parts);

/*
 * Plays the specified title of the DVD from its beginning (that is: part 1).
 */
dvdnav_status_t dvdnav_title_play(dvdnav_t *self, int32_t title);

/*
 * Plays the specified title, starting from the specified part.
 */
dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32_t title, int32_t part);

/*
 * Play the specified amount of parts of the specified title of
 * the DVD then STOP.
 *
 * Currently unimplemented!
 */
dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *self, int32_t title,
					   int32_t part, int32_t parts_to_play);

/*
 * Play the specified title starting from the specified time.
 *
 * Currently unimplemented!
 */
dvdnav_status_t dvdnav_time_play(dvdnav_t *self, int32_t title,
				 uint64_t time);

/*
 * Stop playing the current position and jump to the specified menu.
 *
 * See also DVDMenuID_t from libdvdread
 */
dvdnav_status_t dvdnav_menu_call(dvdnav_t *self, DVDMenuID_t menu);

/*
 * Return the title number and part currently being played.
 * A title of 0 indicates, we are in a menu. In this case, part
 * is set to the current menu's ID.
 */
dvdnav_status_t dvdnav_current_title_info(dvdnav_t *self, int32_t *title,
					  int32_t *part);

/*
 * Return the current position (in blocks) within the current
 * title and the length (in blocks) of said title.
 * 
 * Current implementation is wrong and likely to behave unpredictably!
 * Use is discouraged!
 */
dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *self,
					     uint32_t *pos,
					     uint32_t *len);

/*
 * This function is only available for compatibility reasons.
 *
 * Stop playing the current position and start playback of the current title
 * from the specified part.
 */
dvdnav_status_t dvdnav_part_search(dvdnav_t *self, int32_t part);


/*********************************************************************
 * program chain/program navigation                                  *
 *********************************************************************/

/*
 * Stop playing the current position and start playback from the last
 * VOBU boundary before the given sector. The sector number is not
 * meant to be an absolute physical DVD sector, but a relative sector
 * in the current program. This function cannot leave the current
 * program and will fail, if asked to do so.
 *
 * If program chain based positioning is enabled
 * (see dvdnav_set_PGC_positioning_flag()), this will seek to the relative
 * sector inside the current program chain.
 *
 * 'origin' can be one of SEEK_SET, SEEK_CUR, SEEK_END as defined in
 * fcntl.h.
 */
dvdnav_status_t dvdnav_sector_search(dvdnav_t *self, 
				     uint64_t offset, int32_t origin);

/*
 * Stop playing the current position and start playback of the title
 * from the specified timecode.
 *
 * Currently unimplemented!
 */
dvdnav_status_t dvdnav_time_search(dvdnav_t *self, 
				   uint64_t time);

/*
 * Stop playing current position and play the "GoUp"-program chain.
 * (which generally leads to the title menu or a higer-level menu).
 */
dvdnav_status_t dvdnav_go_up(dvdnav_t *self);

/*
 * Stop playing the current position and start playback at the
 * previous program (if it exists).
 */
dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *self);

/*
 * Stop playing the current position and start playback at the
 * first program.
 */
dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *self);

/*
 * Stop playing the current position and start playback at the
 * next program (if it exists).
 */
dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *self);

/*
 * Return the current position (in blocks) within the current
 * program and the length (in blocks) of current program.
 *
 * If program chain based positioning is enabled
 * (see dvdnav_set_PGC_positioning_flag()), this will return the
 * relative position in and the length of the current program chain.
 */
dvdnav_status_t dvdnav_get_position(dvdnav_t *self, uint32_t *pos,
				    uint32_t *len);
#ifdef USE_MPDVDNAV
/*
 * Get current PGC number
 */
dvdnav_status_t dvdnav_get_pgc(dvdnav_t *self, int *pg_num);
#endif

/*********************************************************************
 * menu highlights                                                   *
 *********************************************************************/

/*
 * Most functions related to highlights take a NAV PCI packet as a parameter.
 * While you can get the such a packet from libdvdnav, for players with internal
 * FIFOs, this will result in errors, because due to the FIFO length, libdvdnav will
 * be ahead in the stream compared to what the user is seeing on screen.
 * Therefore, player applications who have a NAV packet available, which is
 * better in sync with the actual playback should always pass this one to these
 * functions.
 */

/*
 * Get the currently highlighted button 
 * number (1..36) or 0 if no button is highlighted.
 */
dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *self, int32_t *button);

/*
 * Returns the Presentation Control Information (PCI) structure associated
 * with the current position.
 *
 * Read the general notes above.
 * See also libdvdreads nav_types.h for definition of pci_t.
 */
pci_t* dvdnav_get_current_nav_pci(dvdnav_t *self);

/*
 * Returns the DSI (data search information) structure associated
 * with the current position.
 *
 * Read the general notes above.
 * See also libdvdreads nav_types.h for definition of dsi_t.
 */
dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *self);

/*
 * Get the area associated with a certain button.
 */
dvdnav_status_t dvdnav_get_highlight_area(pci_t *nav_pci , int32_t button, int32_t mode,
					  dvdnav_highlight_area_t *highlight);

#ifdef USE_MPDVDNAV
/*
 * Enable & disable auto action mode
 */
dvdnav_status_t dvdnav_button_select_auto_action(dvdnav_t *self, int mode);
#endif
/*
 * Move button highlight around as suggested by function name (e.g. with arrow keys).
 */
dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *self, pci_t *pci);
dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *self, pci_t *pci);
dvdnav_status_t dvdnav_right_button_select(dvdnav_t *self, pci_t *pci);
dvdnav_status_t dvdnav_left_button_select(dvdnav_t *self, pci_t *pci);

/*
 * Activate ("press") the currently highlighted button.
 */
dvdnav_status_t dvdnav_button_activate(dvdnav_t *self, pci_t *pci);

/*
 * Highlight a specific button.
 */
dvdnav_status_t dvdnav_button_select(dvdnav_t *self, pci_t *pci, int32_t button);

/*
 * Activate ("press") specified button.
 */
dvdnav_status_t dvdnav_button_select_and_activate(dvdnav_t *self, pci_t *pci, int32_t button);

/*
 * Activate (press) a button and execute specified command.
 */
dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *self, int32_t button, vm_cmd_t *cmd);

/*
 * Select button at specified video frame coordinates.
 */
dvdnav_status_t dvdnav_mouse_select(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y);

/*
 * Activate ("press") button at specified video frame coordinates.
 */
dvdnav_status_t dvdnav_mouse_activate(dvdnav_t *self, pci_t *pci, int32_t x, int32_t y);


/*********************************************************************
 * languages                                                         *
 *********************************************************************/

/* 
 * The language codes expected by these functions are two character
 * codes as defined in ISO639.
 */

/*
 * Set which menu language we should use per default.
 */
dvdnav_status_t dvdnav_menu_language_select(dvdnav_t *self,
					   char *code);

/*
 * Set which audio language we should use per default.
 */
dvdnav_status_t dvdnav_audio_language_select(dvdnav_t *self,
					    char *code);

/*
 * Set which spu language we should use per default.
 */
dvdnav_status_t dvdnav_spu_language_select(dvdnav_t *self,
					  char *code);


/*********************************************************************
 * obtaining stream attributes                                       *
 *********************************************************************/

/*
 * Return a string describing the title of the DVD.
 * This is an ID string encoded on the disc by the author. In many cases
 * this is a descriptive string such as `THE_MATRIX' but sometimes is sigularly
 * uninformative such as `PDVD-011421'. Some DVD authors even forget to set this,
 * so you may also read the default of the authoring software they used, like
 * `DVDVolume'.
 */
dvdnav_status_t dvdnav_get_title_string(dvdnav_t *self, const char **title_str);

/*
 * Get video aspect code.
 * The aspect code does only change on VTS boundaries.
 * See the DVDNAV_VTS_CHANGE event.
 * 
 * 0 -- 4:3, 2 -- 16:9
 */
uint8_t dvdnav_get_video_aspect(dvdnav_t *self);

/*
 * Get video scaling permissions.
 * The scaling permission does only change on VTS boundaries.
 * See the DVDNAV_VTS_CHANGE event.
 *
 * bit0 set = deny letterboxing, bit1 set = deny pan&scan
 */
uint8_t dvdnav_get_video_scale_permission(dvdnav_t *self);

/*
 * Converts a *logical* audio stream id into language code
 * (returns 0xffff if no such stream).
 */
uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *self, uint8_t stream);

/*
 * Converts a *logical* subpicture stream id into country code 
 * (returns 0xffff if no such stream).
 */
uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *self, uint8_t stream);

/*
 * Converts a *physical* (MPEG) audio stream id into a logical stream number.
 */
int8_t dvdnav_get_audio_logical_stream(dvdnav_t *self, uint8_t audio_num);

#ifdef USE_MPDVDNAV
dvdnav_status_t dvdnav_get_audio_attr(dvdnav_t *self, uint8_t audio_mum, audio_attr_t *audio_attr);
#endif

/*
 * Converts a *physical* (MPEG) subpicture stream id into a logical stream number.
 */
int8_t dvdnav_get_spu_logical_stream(dvdnav_t *self, uint8_t subp_num);

#ifdef USE_MPDVDNAV
dvdnav_status_t dvdnav_get_spu_attr(dvdnav_t *self, uint8_t audio_mum, subp_attr_t *subp_attr);
#endif

/*
 * Get active audio stream.
 */
int8_t dvdnav_get_active_audio_stream(dvdnav_t *self);

/*
 * Get active spu stream.
 */
int8_t dvdnav_get_active_spu_stream(dvdnav_t *self);


/*********************************************************************
 * multiple angles                                                   *
 *********************************************************************/

/*
 * The libdvdnav library abstracts away the difference between seamless and
 * non-seamless angles. From the point of view of the programmer you just set the
 * angle number and all is well in the world. You will always see only the
 * selected angle coming from the get_next_block functions.
 *
 * Note:
 * It is quite possible that some tremendously strange DVD feature might change the
 * angle number from under you. Generally you should always view the results from
 * dvdnav_get_angle_info() as definitive only up to the next time you call
 * dvdnav_get_next_block().
 */

/*
 * Sets the current angle. If you try to follow a non existant angle
 * the call fails.
 */
dvdnav_status_t dvdnav_angle_change(dvdnav_t *self, int32_t angle);

/*
 * Returns the current angle and number of angles present.
 */
dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *self, int32_t *current_angle,
				      int32_t *number_of_angles);

/*********************************************************************
 * domain queries                                                    *
 *********************************************************************/

/*
 * Are we in the First Play domain?
 */
int8_t dvdnav_is_domain_fp(dvdnav_t *self);

/*
 * Are we in the Video management Menu domain?
 */
int8_t dvdnav_is_domain_vmgm(dvdnav_t *self);

/*
 * Are we in the Video Title Menu domain?
 */
int8_t dvdnav_is_domain_vtsm(dvdnav_t *self);

/*
 * Are we in the Video Title Set domain?
 */
int8_t dvdnav_is_domain_vts(dvdnav_t *self);

// ############################## dvdnav.h end #######################################

// ########################### read_cache.h start ####################################
#define READ_CACHE_CHUNKS 10

/* all cache chunks must be memory aligned to allow use of raw devices */
#define ALIGNMENT 2048

#define READ_AHEAD_SIZE_MIN 4
#define READ_AHEAD_SIZE_MAX 512

typedef struct read_cache_chunk_s {
  uint8_t     *cache_buffer;
  uint8_t     *cache_buffer_base;  /* used in malloc and free for alignment */
  int32_t      cache_start_sector; /* -1 means cache invalid */
  int32_t      cache_read_count;   /* this many sectors are already read */
  size_t       cache_block_count;  /* this many sectors will go in this chunk */
  size_t       cache_malloc_size;
  int          cache_valid;
  int          usage_count;  /* counts how many buffers where issued from this chunk */
} read_cache_chunk_t;

struct read_cache_s {
  read_cache_chunk_t  chunk[READ_CACHE_CHUNKS];
  int                 current;
  int                 freeing;  /* is set to one when we are about to dispose the cache */
  uint32_t            read_ahead_size;
  int                 read_ahead_incr;
  int                 last_sector;
  pthread_mutex_t     lock;

  /* Bit of strange cross-linking going on here :) -- Gotta love C :) */
  dvdnav_t           *dvd_self;
};


/* Opaque cache type -- defined in dvdnav_internal.h */
/* typedef struct read_cache_s read_cache_t; */

/* EXPERIMENTAL: Setting the following to 1 will use an experimental multi-threaded
 *               read-ahead cache. 
 */
#define _MULTITHREAD_ 0

/* Constructor/destructors */
read_cache_t *dvdnav_read_cache_new(dvdnav_t* dvd_self);
void dvdnav_read_cache_free(read_cache_t* self);

/* This function MUST be called whenever self->file changes. */
void dvdnav_read_cache_clear(read_cache_t *self);
/* This function is called just after reading the NAV packet. */
void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count);
/* This function will do the cache read.
 * The buffer handed in must be malloced to take one dvd block.
 * On a cache hit, a different buffer will be returned though.
 * Those buffers must _never_ be freed. */
int dvdnav_read_cache_block(read_cache_t *self, int sector, size_t block_count, uint8_t **buf);
// ############################ read_cache.h end #####################################

typedef struct stream_dvdnav_event_flg_st {
    unsigned int nop : 1;			// 1
    unsigned int still_frame : 1;		// 2
    unsigned int spu_stream_change : 1;		// 3
    unsigned int audio_stream_change : 1;	// 4
    unsigned int vts_change : 1;		// 5
    unsigned int cell_change : 1;		// 6
    unsigned int nav_packet : 1;		// 7
    unsigned int stop : 1;			// 8
    unsigned int highlight : 1;			// 9
    unsigned int spu_clut_change : 1;		// 10
    unsigned int none1 : 1;
    unsigned int hop_channel : 1;		// 12
    unsigned int wait : 1;			// 13
    unsigned int none2 : 2;
    unsigned int isevent : 1;
} stream_dvdnav_event_flg_t;


typedef struct stream_dvdnav_event_st {
stream_dvdnav_event_flg_t eventflag;
off_t			eventid;
// store dvdnav event parameters
// DVDNAV_STILL_FRAME
int 			still_length;
// DVDNAV_SPU_STREAM_CHANGE
int 			spu_physical_wide;
int 			spu_physical_letterbox;
int 			spu_physical_pan_scan;
// DVDNAV_AUDIO_STREAM_CHANGE
int 			audio_physical;
int 			audio_logical;
// DVDNAV_VTS_CHANGE
int 			vts_old_vtsN;
dvd_read_domain_t 	vts_old_domain;
int 			vts_new_vtsN;
dvd_read_domain_t 	vts_new_domain;
// DVDNAV_CELL_CHANGE
int 			cell_cellN;
int 			cell_pgN;
int64_t 		cell_cell_length;
int64_t 		cell_pg_length;
int64_t 		cell_pgc_length;
int64_t 		cell_cell_start;
int64_t 		cell_pg_start;
// DVDNAV_HIGHLIGHT
int			hl_display;
uint32_t		hl_palette;
uint16_t		hl_sx,hl_sy,hl_ex,hl_ey;
uint32_t		hl_pts;
uint32_t		hl_buttonN;
// DVDNAV_SPU_CLUT_CHANGE
uint32_t 		spu_clut[16];
uint32_t		spu_palette;
} stream_dvdnav_event_t;



typedef struct {
 int id; // 0 - 31 mpeg; 128 - 159 ac3; 160 - 191 pcm
 int language; 
 int type;
 int channels;
} nstream_language_t;

typedef struct {
    dvdnav_t			*dvdnav;		/* libdvdnav handle */
    char			*filename;
    int				started;		/* libdvdnav start */
    int				stopflg;		/* libdvdnav stop event */
    int 			vts_domain;		/* is vts domain flag */
    int		   		old_vts_domain;		/* old vts domain flag */
    uint32_t			tpos;			/* title pos */
    uint32_t			tlen;			/* title length */

    int				event_lock;		/* event lock */
    int32_t 			title;			/* current title number */
    int32_t 			part;			/* current chapter number */
    int32_t			lasttitle;		/* last title number */
    int32_t			lastpart;		/* last chapter number */

    uint8_t  			alang;			/* current audio language */
    uint8_t  			slang;			/* current spu language */
    uint8_t 			aspect;			/* current video aspect */
    uint32_t			titles_nr;		/* number of titles */
    uint32_t			chapters_nr;		/* number of chapters in actual title */
    int 			nr_of_channels;		/* number of audio channels */
    nstream_language_t 		audio_streams[32]; 	/* audio properties */
    int				nr_of_subtitles;	/* number of subtitles */
    nstream_language_t 		subtitles[32];		/* subtitles properties */
    stream_dvdnav_event_t	event;			/* dvdnav event storage structure */
    int				stillflg;		/* still frame mode */
    unsigned int		cell_timer;		/* pgc cell timmer */    
    int				back_from_timer;	/* if back from timer then nav_demux_seek required */

    int				cell_cellN;		/* last cellN */
    int				cell_pgN;		/* last pgN */
    int				cell_pgcN;		/* last pgcN */
    int				lock_pgN;		/* lock pgN */
    int				lock_pgcN;		/* lock pgcN */
} dvdnav_priv_t;

// open new dvdnav stream
dvdnav_priv_t * new_dvdnav_stream(char * filename, uint32_t titlenum);
// read dvdnav block or event
int dvdnav_stream_read(dvdnav_priv_t * dvdnav_priv, unsigned char *buf, int *len,stream_dvdnav_event_t *event);
// clear all stored event
void dvdnav_event_clear(dvdnav_priv_t * dvdnav_priv);
// close and free dvdnav
void free_dvdnav_stream(dvdnav_priv_t * dvdnav_priv);
// get palette
unsigned int * dvdnav_stream_get_palette(dvdnav_priv_t * dvdnav_priv);
// call menu action UP,DOWN,LEFT,RIGHT,ACTIVATE & MENU
int dvdnav_menu_action(dvdnav_priv_t * dvdnav_priv, int action);
void dvdnav_stream_fullstart(dvdnav_priv_t *dvdnav_priv);
// is dvdnav stop event?
int dvdnav_reallyeof(dvdnav_priv_t * dvdnav_priv);
// set languages
void dvdnav_set_language(dvdnav_priv_t *dvdnav_priv, char* alang, char *slang, char *mlang);
// get lang sid
int dvdnav_lang_from_sid(dvdnav_priv_t * dvdnav_priv, int id);
// get subtitles number
int dvdnav_number_of_subs(dvdnav_priv_t * dvdnav_priv);
// enable/disable event lock mode
void dvdnav_event_lock(dvdnav_priv_t * dvdnav_priv, int lock_mode);
// is event lock?
int dvdnav_isevent_lock(dvdnav_priv_t * dvdnav_priv);
// get highlight properties
void dvdnav_get_highlight(dvdnav_priv_t *dvdnav_priv,dvdnav_highlight_event_t *highlight_event);
// get current button palette
void dvdnav_get_button_palette(dvdnav_priv_t *dvdnav_priv,uint32_t *palette);
#ifdef HAVE_NEW_GUI
// hadler gmplayer mouse 
void dvdnav_mouse(dvdnav_priv_t * dvdnav_priv);
#endif // HAVE_NEW_GUI
#endif // USE_DVDREAD

#endif
