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.c142
1 files changed, 103 insertions, 39 deletions
diff --git a/src/input/libdvdnav/vm.c b/src/input/libdvdnav/vm.c
index 740928be0..0248292b6 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.13 2003/02/20 16:02:01 mroi Exp $
+ * $Id: vm.c,v 1.14 2003/03/21 22:13:38 mroi Exp $
*
*/
@@ -251,8 +251,7 @@ dvd_reader_t *vm_get_dvd_reader(vm_t *vm) {
/* Basic Handling */
-void vm_start(vm_t *vm)
-{
+void vm_start(vm_t *vm) {
/* Set pgc to FP (First Play) pgc */
set_FP_PGC(vm);
process_command(vm, play_PGC(vm));
@@ -265,7 +264,7 @@ void vm_stop(vm_t *vm) {
}
if(vm->vtsi) {
ifoClose(vm->vtsi);
- vm->vmgi=NULL;
+ vm->vtsi=NULL;
}
if(vm->dvd) {
DVDClose(vm->dvd);
@@ -364,6 +363,48 @@ int vm_reset(vm_t *vm, const char *dvdroot) {
}
+/* copying and merging */
+
+vm_t *vm_new_copy(vm_t *source) {
+ vm_t *target = vm_new_vm();
+ int vtsN;
+ int pgcN = get_PGCN(source);
+ int pgN = (source->state).pgN;
+
+ assert(pgcN);
+
+ memcpy(target, source, sizeof(vm_t));
+
+ /* open a new vtsi handle, because the copy might switch to another VTS */
+ target->vtsi = NULL;
+ vtsN = (target->state).vtsN;
+ if (vtsN > 0) {
+ (target->state).vtsN = 0;
+ ifoOpenNewVTSI(target, target->dvd, vtsN);
+
+ /* restore pgc pointer into the new vtsi */
+ if (!set_PGCN(target, pgcN))
+ assert(0);
+ (target->state).pgN = pgN;
+ }
+
+ return target;
+}
+
+void vm_merge(vm_t *target, vm_t *source) {
+ if(target->vtsi)
+ ifoClose(target->vtsi);
+ memcpy(target, source, sizeof(vm_t));
+ memset(source, 0, sizeof(vm_t));
+}
+
+void vm_free_copy(vm_t *vm) {
+ if(vm->vtsi)
+ ifoClose(vm->vtsi);
+ free(vm);
+}
+
+
/* regular playback */
void vm_position_get(vm_t *vm, vm_position_t *position) {
@@ -399,14 +440,19 @@ void vm_position_get(vm_t *vm, vm_position_t *position) {
if (((vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector ==
(vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_vobu_start_sector) &&
((vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector -
- (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector < 250)) {
+ (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector < 1024)) {
int time;
+ int size = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].last_sector -
+ (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector;
time = ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.hour & 0xf0) * 36000;
time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.hour & 0x0f) * 3600;
time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.minute & 0xf0) * 600;
time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.minute & 0x0f) * 60;
time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.second & 0xf0) * 10;
time += ((vm->state).pgc->cell_playback[(vm->state).cellN - 1].playback_time.second & 0x0f) * 1;
+ if (size / time > 30)
+ /* datarate is too high, it might be a very short, but regular cell */
+ return;
if (time > 0xff) time = 0xff;
position->still = time;
}
@@ -458,6 +504,7 @@ int vm_jump_prev_pg(vm_t *vm) {
/* first program -> move to last program of previous PGC */
if ((vm->state).pgc->prev_pgc_nr && set_PGCN(vm, (vm->state).pgc->prev_pgc_nr)) {
process_command(vm, play_PGC(vm));
+ vm_jump_pg(vm, (vm->state).pgc->nr_of_programs);
return 1;
}
return 0;
@@ -535,10 +582,17 @@ int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) {
found = 0;
for (vts_ttn = 0; (vts_ttn < vts_ptt_srpt->nr_of_srpts) && !found; vts_ttn++) {
for (part = 0; (part < vts_ptt_srpt->title[vts_ttn].nr_of_ptts) && !found; part++) {
- if ((vts_ptt_srpt->title[vts_ttn].ptt[part].pgcn == pgcN) &&
- (vts_ptt_srpt->title[vts_ttn].ptt[part].pgn == pgN )) {
- found = 1;
- break;
+ if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgcn == pgcN) {
+ if (vts_ptt_srpt->title[vts_ttn].ptt[part].pgn == pgN) {
+ found = 1;
+ break;
+ }
+ if (part > 0 && vts_ptt_srpt->title[vts_ttn].ptt[part].pgn > pgN &&
+ vts_ptt_srpt->title[vts_ttn].ptt[part - 1].pgn < pgN) {
+ part--;
+ found = 1;
+ break;
+ }
}
}
if (found) break;
@@ -546,6 +600,11 @@ int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) {
vts_ttn++;
part++;
+ if (!found) {
+ fprintf(MSG_OUT, "libdvdnav: chapter NOT FOUND!\n");
+ return 0;
+ }
+
title = get_TT(vm, vm->state.vtsN, vts_ttn);
#ifdef TRACE
@@ -553,14 +612,10 @@ int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) {
fprintf(MSG_OUT, "libdvdnav: ************ this chapter FOUND!\n");
fprintf(MSG_OUT, "libdvdnav: VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n",
title, part,
- vts_ptt_srpt->title[ttn-1].ptt[part-1].pgcn ,
- vts_ptt_srpt->title[ttn-1].ptt[part-1].pgn );
- } else {
- fprintf(MSG_OUT, "libdvdnav: ************ this chapter NOT FOUND!\n");
+ vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgcn ,
+ vts_ptt_srpt->title[vts_ttn-1].ptt[part-1].pgn );
}
#endif
- if (!title)
- return 0;
*title_result = title;
*part_result = part;
return 1;
@@ -572,10 +627,6 @@ 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 streamN = -1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm.c:get_audio_stream audioN=%d\n",audioN);
-#endif
-
if((vm->state).domain != VTS_DOMAIN)
audioN = 0;
@@ -818,7 +869,7 @@ static link_t play_PGC(vm_t *vm) {
link_t link_values;
#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm: play_PGC:");
+ fprintf(MSG_OUT, "libdvdnav: play_PGC:");
if((vm->state).domain != FP_DOMAIN) {
fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm));
} else {
@@ -858,7 +909,7 @@ static link_t play_PGC_PG(vm_t *vm, int pgN) {
link_t link_values;
#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm: play_PGC:");
+ fprintf(MSG_OUT, "libdvdnav: play_PGC:");
if((vm->state).domain != FP_DOMAIN) {
fprintf(MSG_OUT, " (vm->state).pgcN (%i)\n", get_PGCN(vm));
} else {
@@ -909,7 +960,7 @@ static link_t play_PGC_post(vm_t *vm) {
- just go to next PGC
(This is what happens if you fall of the end of the post_cmds)
- or an error (are there more cases?) */
- if((vm->state).pgc->command_tbl &&
+ if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_post &&
vmEval_CMD((vm->state).pgc->command_tbl->post_cmds,
(vm->state).pgc->command_tbl->nr_of_post,
&(vm->state).registers, &link_values)) {
@@ -919,10 +970,11 @@ static link_t play_PGC_post(vm_t *vm) {
#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: ** Fell of the end of the pgc, continuing in NextPGC\n");
#endif
- assert((vm->state).pgc->next_pgc_nr != 0);
/* Should end up in the STOP_DOMAIN if next_pgc is 0. */
- if(!set_PGCN(vm, (vm->state).pgc->next_pgc_nr))
- assert(0);
+ if(!set_PGCN(vm, (vm->state).pgc->next_pgc_nr)) {
+ link_values.command = Exit;
+ return link_values;
+ }
return play_PGC(vm);
}
@@ -1229,8 +1281,13 @@ static int process_command(vm_t *vm, link_t link_values) {
/* Link to Resume point */
int i;
- /* Check and see if there is any rsm info!! */
- assert((vm->state).rsm_vtsN);
+ /* Check and see if there is any rsm info!! */
+ if (!(vm->state).rsm_vtsN) {
+ fprintf(MSG_OUT, "libdvdnav: trying to resume without any resume info set\n");
+ link_values.command = Exit;
+ break;
+ }
+
(vm->state).domain = VTS_DOMAIN;
ifoOpenNewVTSI(vm, vm->dvd, (vm->state).rsm_vtsN);
set_PGCN(vm, (vm->state).rsm_pgcN);
@@ -1299,8 +1356,8 @@ static int process_command(vm_t *vm, link_t link_values) {
break;
case Exit:
- fprintf(MSG_OUT, "libdvdnav: FIXME:in trouble...Link Exit - CRASHING!!!\n");
- assert(0); /* What should we do here?? */
+ vm->stopped = 1;
+ return 0;
case JumpTT:
/* Jump to VTS Title Domain */
@@ -1479,7 +1536,7 @@ static int set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part) {
pgN = vm->vtsi->vts_ptt_srpt->title[vts_ttn - 1].ptt[part - 1].pgn;
(vm->state).TT_PGCN_REG = pgcN;
- (vm->state).PTTN_REG = pgN;
+ (vm->state).PTTN_REG = part;
(vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn);
assert( (vm->state.TTN_REG) != 0 );
(vm->state).VTS_TTN_REG = vts_ttn;
@@ -1545,7 +1602,7 @@ static int set_PGN(vm_t *vm) {
return 0; /* ?? */
pb_ty = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1].pb_ty;
if(pb_ty->multi_or_random_pgc_title == /* One_Sequential_PGC_Title */ 0) {
- int dummy;
+ int dummy, part;
#if 0
/* TTN_REG can't be trusted to have a correct value here... */
vts_ptt_srpt_t *ptt_srpt = vtsi->vts_ptt_srpt;
@@ -1553,8 +1610,8 @@ static int set_PGN(vm_t *vm) {
assert(get_PGCN() == ptt_srpt->title[(vm->state).VTS_TTN_REG - 1].ptt[0].pgcn);
assert(1 == ptt_srpt->title[(vm->state).VTS_TTN_REG - 1].ptt[0].pgn);
#endif
- vm_get_current_title_part(vm, &dummy, &(vm->state).pgN);
- (vm->state).PTTN_REG = (vm->state).pgN;
+ vm_get_current_title_part(vm, &dummy, &part);
+ (vm->state).PTTN_REG = part;
} else {
/* FIXME: Handle RANDOM or SHUFFLE titles. */
fprintf(MSG_OUT, "libdvdnav: RANDOM or SHUFFLE titles are NOT handled yet.\n");
@@ -1649,16 +1706,16 @@ static int get_PGCN(vm_t *vm) {
int pgcN = 1;
pgcit = get_PGCIT(vm);
- assert(pgcit != NULL);
- while(pgcN <= pgcit->nr_of_pgci_srp) {
- if(pgcit->pgci_srp[pgcN - 1].pgc == (vm->state).pgc)
- return pgcN;
- pgcN++;
+ if (pgcit) {
+ while(pgcN <= pgcit->nr_of_pgci_srp) {
+ if(pgcit->pgci_srp[pgcN - 1].pgc == (vm->state).pgc)
+ return pgcN;
+ pgcN++;
+ }
}
fprintf(MSG_OUT, "libdvdnav: get_PGCN failed. Was trying to find pgcN in domain %d\n",
(vm->state).domain);
- /* assert(0);*/
return 0; /* error */
}
@@ -1742,6 +1799,13 @@ void vm_position_print(vm_t *vm, vm_position_t *position) {
/*
* $Log: vm.c,v $
+ * Revision 1.14 2003/03/21 22:13:38 mroi
+ * sync to libdvdnav cvs
+ * * method to try-run VM operations, now used for safer chapter skipping and menu jumps
+ * * fixed detection of current PTT to not assume a 1:1 mapping between PTTs and PGs
+ * * releasing stills when jumping to menu fixes some state inconsistencies
+ * * do not assume PGs to be physically layed out in sequence on the disc
+ *
* Revision 1.13 2003/02/20 16:02:01 mroi
* syncing to libdvdnav 0.1.5 and modifying input plugin accordingly
* quoting the ChangeLog: