
/*
 *
 * Copyright (C) 1998,1999  Thomas Mirlacher
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 * The author may be reached as dent@cosy.sbg.ac.at, or
 * Thomas Mirlacher, Jakob-Haringerstr. 2, A-5020 Salzburg,
 * Austria
 *
 *------------------------------------------------------------
 *
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include <errno.h>
//#include <unistd.h>
#include <sys/types.h>
//#include <sys/mman.h>

#include "ifo.h"
#include "misc.h"


/**
 *
 */

int ifoIsVTS (ifo_t *ifo)
{
        if (!strncmp ((char *)ifo->data[ID_MAT], "DVDVIDEO-VTS", 12)) 
		return 0;

	return -1;
}


/**
 *
 */

int ifoIsVMG (ifo_t *ifo)
{
        if (!strncmp ((char *)ifo->data[ID_MAT], "DVDVIDEO-VMG", 12))
		return 0;

	return -1;
}


/**
 *
 */

int ifoGetVOBStart (ifo_t *ifo)
{
	return ifo->vob_start;
}


#define OFF_PTT get4bytes (ifo->data[ID_MAT] + 0xC8)
#define OFF_TITLE_PGCI get4bytes (ifo->data[ID_MAT] + 0xCC)
#define OFF_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xD0)
#define OFF_TMT get4bytes (ifo->data[ID_MAT] + 0xD4)
#define OFF_MENU_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xD8)
#define OFF_MENU_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xDC)
#define OFF_TITLE_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xE0)
#define OFF_TITLE_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xE4)

#define OFF_VMG_PTT get4bytes (ifo->data[ID_MAT] + 0xC4)
#define OFF_VMG_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xC8)
#define OFF_VMG_TMT get4bytes (ifo->data[ID_MAT] + 0xD0)


/**
 *
 */

ifo_t *ifoOpen (int fd, __off64_t pos)
{
	ifo_t *ifo;

	if (!(ifo = (ifo_t *) calloc (sizeof (ifo_t), 1))) {
		fprintf (stderr, "%s/%d: memory squeeze (ifo)\n", __FILE__, __LINE__);
		return NULL;
	}

	if (!(ifo->data[ID_MAT] = (unsigned char *) calloc (DVD_VIDEO_LB_LEN, 1))) {
		fprintf (stderr, "%s/%d: memory squeeze (data)\n", __FILE__, __LINE__);
		return NULL;
	}

	ifo->pos = pos; 
	ifo->fd = fd;

	if (ifoReadLB (fd, pos, DVD_VIDEO_LB_LEN, ifo->data[ID_MAT]) < 0) {
		fprintf (stderr, "%s/%d: something went wrong when reading file. (pos %x) \n", __FILE__, __LINE__, ifo->pos);
		return NULL;
	}

	ifo->num_menu_vobs	= get4bytes (ifo->data[ID_MAT] + 0xC0);
	ifo->vob_start		= get4bytes (ifo->data[ID_MAT] + 0xC4);

printf ("num of vobs: %x vob_start %x\n", ifo->num_menu_vobs, ifo->vob_start);

	if (!ifoIsVTS (ifo)) {
		ifoReadTBL (ifo, OFF_PTT, ID_PTT);
		ifoReadTBL (ifo, OFF_TITLE_PGCI, ID_TITLE_PGCI);
		ifoReadTBL (ifo, OFF_MENU_PGCI, ID_MENU_PGCI);
		ifoReadTBL (ifo, OFF_TMT, ID_TMT);
		ifoReadTBL (ifo, OFF_MENU_CELL_ADDR, ID_MENU_CELL_ADDR);
		ifoReadTBL (ifo, OFF_MENU_VOBU_ADDR_MAP, ID_MENU_VOBU_ADDR_MAP);
		ifoReadTBL (ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
		ifoReadTBL (ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
	} else if (!ifoIsVMG (ifo)) {
		ifoReadTBL (ifo, OFF_VMG_PTT, ID_PTT);
//		ifoReadTBL (ifo, OFF_TITLE_PGCI, ID_TITLE_PGCI);
		ifoReadTBL (ifo, OFF_VMG_MENU_PGCI, ID_MENU_PGCI);
		ifoReadTBL (ifo, OFF_VMG_TMT, ID_TMT);
//		ifoReadTBL (ifo, OFF_MENU_CELL_ADDR, ID_MENU_CELL_ADDR);
//		ifoReadTBL (ifo, OFF_MENU_VOBU_ADDR_MAP, ID_MENU_VOBU_ADDR_MAP);
		ifoReadTBL (ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
		ifoReadTBL (ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
	}
	else return NULL;

	return ifo;
}


/**
 *
 */

int ifoClose (ifo_t *ifo)
{
	free (ifo->data[ID_MAT]);
	free (ifo->data[ID_PTT]);
	free (ifo->data[ID_TITLE_PGCI]);
	free (ifo->data[ID_MENU_PGCI]);
	free (ifo->data[ID_TMT]);
	free (ifo->data[ID_MENU_CELL_ADDR]);
	free (ifo->data[ID_MENU_VOBU_ADDR_MAP]);
	free (ifo->data[ID_TITLE_CELL_ADDR]);
	free (ifo->data[ID_TITLE_VOBU_ADDR_MAP]);

	free (ifo);

	return 0;
}
