summaryrefslogtreecommitdiff
path: root/src/input/libdvdnav/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/libdvdnav/vm.c')
-rw-r--r--src/input/libdvdnav/vm.c170
1 files changed, 141 insertions, 29 deletions
diff --git a/src/input/libdvdnav/vm.c b/src/input/libdvdnav/vm.c
index 21f976ef8..10b9f9f32 100644
--- a/src/input/libdvdnav/vm.c
+++ b/src/input/libdvdnav/vm.c
@@ -19,7 +19,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: vm.c,v 1.4 2002/08/27 19:24:33 mroi Exp $
+ * $Id: vm.c,v 1.5 2002/09/04 11:07:47 mroi Exp $
*
*/
@@ -42,9 +42,9 @@
#include "vm.h"
#include "dvdnav_internal.h"
-/*
+
#define STRICT
-*/
+
/* Local prototypes */
@@ -110,8 +110,9 @@ static void vm_print_current_domain_state(vm_t *vm) {
fprintf(MSG_OUT, "libdvdnav: Unknown Domain: -\n");
break;
}
- fprintf(MSG_OUT, "libdvdnav: VTS:%d PG:%u CELL:%u BLOCK:%u VTS_TTN:%u TTN:%u TT_PGCN:%u\n",
+ fprintf(MSG_OUT, "libdvdnav: VTS:%d PGC:%d PG:%u CELL:%u BLOCK:%u VTS_TTN:%u TTN:%u TT_PGCN:%u\n",
(vm->state).vtsN,
+ get_PGCN(vm),
(vm->state).pgN,
(vm->state).cellN,
(vm->state).blockN,
@@ -437,6 +438,96 @@ int vm_prev_pg(vm_t *vm)
return vm_top_pg(vm);
}
+/* Get the current title and part from the current playing position. */
+/* returns S_ERR if not in the VTS_DOMAIN */
+/* FIXME: Should we do some locking here ? */
+int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result)
+{
+ vts_ptt_srpt_t *vts_ptt_srpt;
+ int title=0, part=0;
+ int found = 0;
+ int16_t pgcN, pgN;
+
+ if((!vm) || (!vm->vtsi) )
+ return S_ERR;
+
+ if(!title_result || !part_result) {
+ fprintf(MSG_OUT, "libdvdnav:vm_get_current_title_part: Passed a NULL pointer");
+ return S_ERR;
+ }
+
+ if(!(vm->state.pgc) )
+ return S_ERR;
+ if (vm->state.domain != VTS_DOMAIN)
+ return S_ERR;
+ vts_ptt_srpt = vm->vtsi->vts_ptt_srpt;
+ pgcN = get_PGCN(vm);
+ pgN = vm->state.pgN;
+ printf("VTS_PTT_SRPT - PGC: %3i PG: %3i\n",
+ pgcN, pgN);
+ for(title=0;( (title < vts_ptt_srpt->nr_of_srpts) && (found == 0) );title++) {
+ for(part=0;((part < vts_ptt_srpt->title[title].nr_of_ptts) && (found == 0));part++) {
+ if ( (vts_ptt_srpt->title[title].ptt[part].pgcn == pgcN) &&
+ (vts_ptt_srpt->title[title].ptt[part].pgn == pgN ) ) {
+ found = 1;
+ break;
+ }
+ }
+ if (found != 0) break;
+ }
+ title++;
+ part++;
+ if (found == 1) {
+ fprintf(MSG_OUT, "libdvdnav: ************ this chapter FOUND!\n");
+ printf("VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n",
+ title, part,
+ vts_ptt_srpt->title[title-1].ptt[part-1].pgcn ,
+ vts_ptt_srpt->title[title-1].ptt[part-1].pgn );
+ } else {
+ fprintf(MSG_OUT, "libdvdnav: ************ this chapter NOT FOUND!\n");
+ return S_ERR;
+ }
+ *title_result = title;
+ *part_result = part;
+ return 1;
+}
+
+/* Jump to a particlar part of a particlar title on this vts */
+/* returns S_ERR if not in the VTS_DOMAIN */
+/* FIXME: Should we do some locking here ? */
+int vm_jump_title_part(vm_t *vm, int title, int part) {
+ link_t link_values;
+ int vtsN;
+
+ if((!vm) || (!vm->vtsi) || (!vm->vmgi) )
+ return S_ERR;
+
+ if(!(vm->state.pgc) )
+ return S_ERR;
+/* if ( (title < 1) || (title > vm->vtsi->vts_ptt_srpt->nr_of_srpts) ||
+ (part < 1) || (part > vm->vtsi->vts_ptt_srpt->title[title].nr_of_ptts) ) {
+ return S_ERR;
+ }
+ */
+ if( (title < 1) || (title > vm->vmgi->tt_srpt->nr_of_srpts) ) {
+ return S_ERR;
+ }
+ vtsN = vm->vmgi->tt_srpt->title[title - 1].title_set_nr;
+
+ if(set_VTS_PTT(vm, vtsN, title, part) == -1) {
+ return S_ERR;
+ }
+ link_values = play_PGC_PG( vm, (vm->state).pgN );
+ link_values = process_command(vm,link_values);
+ assert(link_values.command == PlayThis);
+ (vm->state).blockN = link_values.data1;
+ assert( (vm->state).blockN == 0 );
+ vm->hop_channel++;
+
+ fprintf(MSG_OUT, "libdvdnav: previous chapter done\n");
+
+ return 1;
+}
static domain_t menuid2domain(DVDMenuID_t menuid)
{
@@ -854,7 +945,11 @@ static int set_PGN(vm_t *vm) {
assert(1 == ptt_srpt->title[(vm->state).VTS_TTN_REG - 1].ptt[0].pgn);
#endif
(vm->state).PTTN_REG = (vm->state).pgN;
+ } else {
+ /* FIXME: Handle RANDOM or SHUFFLE titles. */
+ fprintf(MSG_OUT, "libdvdnav: RANDOM or SHUFFLE titles are NOT handled yet.\n");
}
+
}
return 0;
@@ -949,10 +1044,10 @@ static link_t play_PG(vm_t *vm)
assert((vm->state).pgN > 0);
if((vm->state).pgN > (vm->state).pgc->nr_of_programs) {
#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: (vm->state).pgN (%i) == pgc->nr_of_programs + 1 (%i)\n",
- (vm->state).pgN, (vm->state).pgc->nr_of_programs + 1);
+ fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i) > pgc->nr_of_programs (%i)\n",
+ (vm->state).pgN, (vm->state).pgc->nr_of_programs );
#endif
- /*assert((vm->state).pgN == (vm->state).pgc->nr_of_programs + 1);*/
+ assert((vm->state).pgN == (vm->state).pgc->nr_of_programs + 1);
return play_PGC_post(vm);
}
@@ -971,8 +1066,8 @@ static link_t play_Cell(vm_t *vm)
assert((vm->state).cellN > 0);
if((vm->state).cellN > (vm->state).pgc->nr_of_cells) {
#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: (vm->state).cellN (%i) == pgc->nr_of_cells + 1 (%i)\n",
- (vm->state).cellN, (vm->state).pgc->nr_of_cells + 1);
+ fprintf(MSG_OUT, "libdvdnav: (vm->state).cellN (%i) > pgc->nr_of_cells (%i)\n",
+ (vm->state).cellN, (vm->state).pgc->nr_of_cells );
#endif
assert((vm->state).cellN == (vm->state).pgc->nr_of_cells + 1);
return play_PGC_post(vm);
@@ -1050,10 +1145,15 @@ static link_t play_Cell_post(vm_t *vm)
if(cell->cell_cmd_nr != 0) {
link_t link_values;
-#ifdef STRICT
- assert((vm->state).pgc->command_tbl != NULL);
- assert((vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr);
-#endif
+/* These asserts are now not needed.
+ * Some DVDs have no cell commands listed in the PGC,
+ * but the Cell itself points to a cell command that does not exist.
+ * For this situation, just ignore the cell command and continue.
+ *
+ * assert((vm->state).pgc->command_tbl != NULL);
+ * assert((vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr);
+ */
+
if ((vm->state).pgc->command_tbl != NULL &&
(vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr) {
#ifdef TRACE
@@ -1068,6 +1168,7 @@ static link_t play_Cell_post(vm_t *vm)
}
} else {
fprintf(MSG_OUT, "libdvdnav: Invalid Cell command\n");
+
}
}
@@ -1125,7 +1226,8 @@ static link_t play_PGC_post(vm_t *vm)
fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n");
#endif
- assert((vm->state).pgc->still_time == 0); /* FIXME $$$ */
+ /* FIXME Implement PGC Stills. Currently only Cell stills work */
+ assert((vm->state).pgc->still_time == 0);
/* eval -> updates the state and returns either
- some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN)
@@ -1153,17 +1255,18 @@ static link_t process_command(vm_t *vm, link_t link_values)
{
/* FIXME $$$ Move this to a separate function? */
vm->badness_counter++;
- if (vm->badness_counter > 1) fprintf(MSG_OUT, "libdvdnav: **** process_command re-entered %d*****\n",vm->badness_counter);
+ if (vm->badness_counter > 1) fprintf(MSG_OUT, "libdvdnav: **** WARNING: process_command re-entered %d*****\n",vm->badness_counter);
while(link_values.command != PlayThis) {
#ifdef TRACE
+ fprintf(MSG_OUT, "libdvdnav: Before printout starts:\n");
vmPrint_LINK(link_values);
fprintf(MSG_OUT, "libdvdnav: Link values %i %i %i %i\n", link_values.command,
link_values.data1, link_values.data2, link_values.data3);
- fprintf(MSG_OUT, "libdvdnav: Before:");
vm_print_current_domain_state(vm);
+ fprintf(MSG_OUT, "libdvdnav: Before printout ends.\n");
#endif
switch(link_values.command) {
@@ -1381,7 +1484,7 @@ static link_t process_command(vm_t *vm, link_t link_values)
assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */
if(set_VTS_PTT(vm,(vm->state).vtsN, link_values.data1, link_values.data2) == -1)
assert(0);
- link_values = play_PGC_PG(vm, link_values.data2);
+ link_values = play_PGC_PG( vm, (vm->state).pgN );
break;
case JumpSS_FP:
@@ -1495,8 +1598,9 @@ static link_t process_command(vm_t *vm, link_t link_values)
}
#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: After:");
+ fprintf(MSG_OUT, "libdvdnav: After printout starts:\n");
vm_print_current_domain_state(vm);
+ fprintf(MSG_OUT, "libdvdnav: After printout ends.\n");
#endif
}
@@ -1558,8 +1662,10 @@ static int set_VTS_PTT(vm_t *vm, int vtsN, int /* is this really */ vts_ttn, int
if(vtsN != (vm->state).vtsN)
ifoOpenNewVTSI(vm, vm->dvd, vtsN); /* Also sets (vm->state).vtsN */
- assert(vts_ttn <= vm->vtsi->vts_ptt_srpt->nr_of_srpts);
- assert(part <= vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].nr_of_ptts);
+ if ((vts_ttn < 1) || (vts_ttn > vm->vtsi->vts_ptt_srpt->nr_of_srpts) ||
+ (part < 1) || (part > vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].nr_of_ptts) ) {
+ return S_ERR;
+ }
pgcN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgcn;
pgN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgn;
@@ -1608,21 +1714,24 @@ static int get_ID(vm_t *vm, int id)
pgcit = get_PGCIT(vm);
assert(pgcit != NULL);
fprintf(MSG_OUT, "libdvdnav: ** Searching for menu (0x%x) entry PGC\n", id);
-
+
+ /* Force high bit set. */
+ id |=0x80;
/* Get menu/title */
for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
- if((pgcit->pgci_srp[i].entry_id & 0x7f) == id) {
- assert((pgcit->pgci_srp[i].entry_id & 0x80) == 0x80);
+ if( (pgcit->pgci_srp[i].entry_id) == id) {
pgcN = i + 1;
+ fprintf(MSG_OUT, "libdvdnav: Found menu.\n");
return pgcN;
}
}
- fprintf(MSG_OUT, "libdvdnav: ** No such id/menu (%d) entry PGC\n", id);
+ fprintf(MSG_OUT, "libdvdnav: ** No such id/menu (0x%02x) entry PGC\n", id & 0x7f);
for(i = 0; i < pgcit->nr_of_pgci_srp; i++) {
- fprintf(MSG_OUT, "libdvdnav: Available menus: 0x%x\n",
- pgcit->pgci_srp[i].entry_id);
+ if ( (pgcit->pgci_srp[i].entry_id & 0x80) == 0x80) {
+ fprintf(MSG_OUT, "libdvdnav: Available menus: 0x%x\n",
+ pgcit->pgci_srp[i].entry_id & 0x7f);
+ }
}
- assert(0); /* Use assert for now, until the error is handled. */
return -1; /* error */
}
@@ -1639,7 +1748,6 @@ static int set_PGC(vm_t *vm, int pgcN)
assert(pgcit != NULL); /* ?? Make this return -1 instead */
if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) {
fprintf(MSG_OUT, "libdvdnav: ** No such pgcN = %d\n", pgcN);
- assert(0);
return -1; /* error */
}
@@ -1669,7 +1777,7 @@ static int get_PGCN(vm_t *vm)
}
fprintf(MSG_OUT, "libdvdnav: get_PGCN failed. Trying to find pgcN in domain %d \n",
(vm->state).domain);
- assert(0);
+ /* assert(0);*/
return -1; /* error */
}
@@ -1802,6 +1910,7 @@ static pgcit_t* get_PGCIT(vm_t *vm) {
pgcit = get_MENU_PGCIT(vm, vm->vtsi, (vm->state).registers.SPRM[0]);
break;
case VMGM_DOMAIN:
+ case FP_DOMAIN:
pgcit = get_MENU_PGCIT(vm, vm->vmgi, (vm->state).registers.SPRM[0]);
break;
default:
@@ -1817,6 +1926,9 @@ static pgcit_t* get_PGCIT(vm_t *vm) {
/*
* $Log: vm.c,v $
+ * Revision 1.5 2002/09/04 11:07:47 mroi
+ * sync to libdvdnav cvs
+ *
* Revision 1.4 2002/08/27 19:24:33 mroi
* sync to libdvdnav cvs, this should now conform to the way xine outputs
* its console messages (write to stdout, "libdvdnav: " in front each line)