
/*
 * PGROGRAM CHAIN INFORMATION
 *
 * Copyright (C) 1998-2000  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
 *
 *------------------------------------------------------------
 *
 * $log$
 */


#include "IFOparser.h"
extern CIFOParser *IFOGlobal;

#include <stdio.h>
#include <malloc.h>
#include <sys/types.h>
//#include <unistd.h>
#include "ifo.h"

#include "misc.h"
#include "decode.h"

#define OFFSET_START_TBL_CMD (12+8*2+32*4+8+16*PGCI_COLOR_LEN)

typedef struct {
	u_char  foo		: 8;	// don't know
	u_char	y		: 8;
	u_char	cr		: 8;
	u_char	cb		: 8;	
} pgci_color_t;

#define PGCI_COLOR_LEN 4

void ifoPrint_cell_position (u_char *ptr, u_int num);


/**
 *
 */

void ifoPrint_pgc (u_char *pgc_ptr)
{
	int i;
	u_int num;
	char *ptr = (char *)pgc_ptr;

	if (!ptr)
		return;

	TPGC  *my_pgc = &IFOGlobal->pgcs[IFOGlobal->PGCptr];

	printf ("\n\tPROGRAM CHAIN\n");
	printf ("\t---\n");

/*****/
	printf ("foo1: %x %x\n", *ptr++, *ptr++);
	printf ("num_programs: %x  num_cells: %x\n", *ptr++, *ptr++); 

/*****/
#define INT_TO_HEX(x)  (((x/16)*10)+(x%16))
	printf ("\n\t\tchain time: %02x:%02x:%02x:%02x\n",
		ptr[0],
		ptr[1],
		ptr[2],
//		ptr[3] & 0x1F);
		ptr[3] & 0x7F);
	//int x = ((ptr[1]/16)+(ptr[1]%16));
	my_pgc->chain_time = INT_TO_HEX(ptr[0])*(3600*1000) + INT_TO_HEX(ptr[1])*60*1000 + INT_TO_HEX(ptr[2])*1000 + INT_TO_HEX(ptr[3]&0x7F)*10;
	//  chain_time in milliseconds = hours, minutes, secods, cents

//	printf ("VideoMode: %s\n", decode_videomode (ptr[3] >> 8));
	printf ("%sframes/s\n", ptr[3]&0x80 ? "30" : "25 non-drop");

	ptr += 4;

/*****/
//UNKNOWN
	printf ("foo2: %x %x\n", *ptr++, *ptr++);
	printf ("foo3: %x %x\n", *ptr++, *ptr++);

/*****/
	printf ("\n\t\tAUDIO\n");
	for (i=0; i<8; i++) {		// 8 subaudio streams
		if (*ptr & 0x80) {	// avail
			printf ("\t\t\t0x%02x->0x%02x unknown:0x%02x\n",
				i,
				*ptr&0x7f,
				*(ptr+1));
		}

		ptr+=2;
	}
	
/*****/
	printf ("\n\t\tSUBPICTURE\n");
	for (i=0; i<32; i++) {
		if (*ptr & 0x80) {	// avail
			printf ("\t\t\t0x%02x 4:3 0x%02x wide 0x%02x letter 0x%02x pan 0x%02x\n",
				i,
				*ptr&0x7f,
				*(ptr+1),
				*(ptr+2),
				*(ptr+3));
		}

		ptr+=4;
	}

/*****/
//UNKNOWN
	for (i=0; i<8; i++) {
		if (!(i%16))
			printf ("\n\t0x%04x: ", i);

		printf ("%02x  ", *ptr++);
	}

/*****/
	if (ifoGetCLUT ((char *)pgc_ptr, &ptr) >= 0)
		ifoPrintCLUT ((unsigned char *)ptr);

	ifoPrint_pgc_cmd (pgc_ptr);

	if ((num = ifoGetProgramMap ((char *)pgc_ptr, &ptr)))
		ifoPrintProgramMap ((unsigned char *)ptr, num);

	if ((num = ifoGetCellPlayInfo ((char *)pgc_ptr, &ptr)))
		ifoPrintCellInfo ((unsigned char *)ptr, num);
	if( IFOGlobal->fatal_error_flag )
		return;

	if ((num = ifoGetCellPos ((char *)pgc_ptr, &ptr)))
		ifoPrintCellPos ((unsigned char *)ptr, num);
	if( IFOGlobal->fatal_error_flag )
		return;


/*****/

}	


/**
 *
 */

void ifoPrintCellPos (u_char *ptr, u_int num)
{ int i;

	TPGC  *my_pgc = &IFOGlobal->pgcs[IFOGlobal->PGCptr];

	printf ("\n\tCELL POSITION (num: %d)\n", num);

	if(num<=0){
		IFOGlobal->fatal_error_flag = 1;
		return;
	}
	for (i=0; i<num; i++) {


		printf ("\t\tVOB ID: %02x ", get2bytes (ptr));
		my_pgc->chain_cells[i].vobid  = get2bytes (ptr);
		ptr += 2;
		printf ("Cell ID: %02x\n", get2bytes (ptr));
		my_pgc->chain_cells[i].cellid = get2bytes (ptr);
		ptr += 2;
	}
}


/**
 *
 */

void ifoPrint_pgc_cmd (u_char *pgc_ptr)
{
	int i;
	u_int num_pre_cmd;
	u_int num_post_cmd;
	u_int num_cell_cmd;
	u_int len_cmd_tbl;
	u_char *ptr;

	if ((ptr = get2bytes (pgc_ptr + OFFSET_START_TBL_CMD) + pgc_ptr) == pgc_ptr) 
		return;

	num_pre_cmd	 = get2bytes (ptr);
	ptr+=2;
	num_post_cmd	 = get2bytes (ptr);
	ptr+=2;

/*****/
//cell commands
	num_cell_cmd = get2bytes (ptr);
	ptr+=2;
	len_cmd_tbl = get2bytes (ptr);
	ptr+=2;

	if (num_cell_cmd)
		printf ("\n\t\tcell commands: (num: 0x%02x)", num_cell_cmd);

/*****/
//pre commands
	if (num_pre_cmd)
		printf ("\n\t\tpre commands: (num: 0x%02x)", num_pre_cmd);
	for (i=1; i<=num_pre_cmd; i++) {
		printf ("\n\t\t\t0x%04x: ", i);
		ifoPrintVMOP (ptr);
		ptr += 8;
	}

/*****/
//post commands
	if (num_post_cmd)
		printf ("\n\n\t\tpost commands: (num: 0x%02x)", num_post_cmd);
	for (i=1; i<=num_post_cmd; i++) {
		printf ("\n\t\t\t0x%04x: ", i);
		ifoPrintVMOP (ptr);
		ptr += 8;
	}
}


/**
 *
 */

void ifoPrintCellInfo (u_char *ptr, u_int num_cell_play_info)
{
	int i;

	printf ("\n\tCELL PLAY INFO (num: %d)\n", num_cell_play_info);


	TPGC  *my_pgc = &IFOGlobal->pgcs[IFOGlobal->PGCptr];
//	my_pgc->vob_span_count = num_cell_play_info;
	if(num_cell_play_info<=0){
		IFOGlobal->fatal_error_flag = 1;
		return;
	}
		my_pgc->chain_cells.SetArraySize( num_cell_play_info );

	for (i=0; i<num_cell_play_info; i++) {
		ifo_pgci_cell_addr_t *cell_addr = (ifo_pgci_cell_addr_t *) ptr;
		printf ("\t\tstill_time: %02xs\t cell_cmd: 0x%x\tlen: %02x:%02x:%02x:%02x ",
			(bswap_32 (cell_addr->foo) >> 8) & 0xFF,
			(bswap_32 (cell_addr->foo)) & 0xFF,
			(bswap_32 (cell_addr->len_time) >> 24) & 0xFF,
			(bswap_32 (cell_addr->len_time) >> 16) & 0xFF,
			(bswap_32 (cell_addr->len_time) >> 8) & 0xFF,
			bswap_32 (cell_addr->len_time) & 0x7F);
		
		printf ("%sframes/s\n", bswap_32 (cell_addr->len_time) & 0x80 ? "30" : "25 non-drop");
		printf ("\t\t1st_vobu_start : 0x%08X  1st_ilvu_end : 0x%08X\n\t\tlast_vobu_start: 0x%08X  last_vobu_end: 0x%08X\n",
			bswap_32 (cell_addr->vobu_start),
			bswap_32 (cell_addr->ilvu_end),
			bswap_32 (cell_addr->vobu_last_start),
			bswap_32 (cell_addr->vobu_last_end));



		my_pgc->chain_cells[i].start = bswap_32(cell_addr->vobu_start)   *2048;
		// Must point to last byte of the span
		my_pgc->chain_cells[i].end   = bswap_32(cell_addr->vobu_last_end)*2048 + 2047;

		ptr += PGCI_CELL_ADDR_LEN;
	}
}		


/**
 *
 */

void ifoPrintCLUT (u_char *clut)
{
	TPGC  *my_pgc = &IFOGlobal->pgcs[IFOGlobal->PGCptr];

	pgci_color_t *pgci_color = (pgci_color_t *) clut;
	int num = 16;
	int index = 0;

	printf ("\n\t\tCLUT:\n");

	while (num--) {
		printf ("\t\t\tfoo:0x%x  Y:0x%x Cr:0x%x Cb:0x%x\n",
			pgci_color->foo,
			pgci_color->y,
			pgci_color->cr,
			pgci_color->cb);
		my_pgc->clut[index][0]   =  pgci_color->foo;
		my_pgc->clut[index][1]   =  pgci_color->y;
		my_pgc->clut[index][2]   =  pgci_color->cr;
		my_pgc->clut[index][3]   =  pgci_color->cb;
		index ++;
		pgci_color++;
	}
}


/**
 *
 */

void ifoPrintProgramMap (u_char *ptr, u_int num)
{
	int i;

	printf ("\n\n\t\tcell links: (num: %d)\n", num);
	for (i=0; i<num; i++) {
		printf ("\t\t\t0x%02x -> 0x%02x\n",
			i, *ptr);
		ptr++;
	}
}


