summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichael Roitzsch <mroi@users.sourceforge.net>2003-03-21 22:13:37 +0000
committerMichael Roitzsch <mroi@users.sourceforge.net>2003-03-21 22:13:37 +0000
commitae83701d4b53dbd4b49ffade77d85f391aee5bed (patch)
tree55db1c3ee746607f3b134731e6d7ab4fb74dc376 /src
parentcfed69ca942b61ae616b378d6209ca6b93ef7dd4 (diff)
downloadxine-lib-ae83701d4b53dbd4b49ffade77d85f391aee5bed.tar.gz
xine-lib-ae83701d4b53dbd4b49ffade77d85f391aee5bed.tar.bz2
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 CVS patchset: 4466 CVS date: 2003/03/21 22:13:37
Diffstat (limited to 'src')
-rw-r--r--src/input/libdvdnav/dvdnav.c20
-rw-r--r--src/input/libdvdnav/dvdnav.h35
-rw-r--r--src/input/libdvdnav/searching.c84
-rw-r--r--src/input/libdvdnav/vm.c142
-rw-r--r--src/input/libdvdnav/vm.h9
5 files changed, 205 insertions, 85 deletions
diff --git a/src/input/libdvdnav/dvdnav.c b/src/input/libdvdnav/dvdnav.c
index dc3acb190..a86002169 100644
--- a/src/input/libdvdnav/dvdnav.c
+++ b/src/input/libdvdnav/dvdnav.c
@@ -17,7 +17,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: dvdnav.c,v 1.17 2003/02/26 20:44:12 mroi Exp $
+ * $Id: dvdnav.c,v 1.18 2003/03/21 22:13:37 mroi Exp $
*
*/
@@ -393,6 +393,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
/* Check the STOP flag */
if(this->vm->stopped) {
+ vm_stop(this->vm);
(*event) = DVDNAV_STOP;
this->started = 0;
pthread_mutex_unlock(&this->vm_lock);
@@ -401,7 +402,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
vm_position_get(this->vm, &this->position_next);
-#ifdef TRACE
+#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: POS-NEXT ");
vm_position_print(this->vm, &this->position_next);
fprintf(MSG_OUT, "libdvdnav: POS-CUR ");
@@ -447,9 +448,9 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
}
}
this->position_current.hop_channel = this->position_next.hop_channel;
- /* Make blockN > vobu_length to do expected_nav */
+ /* Make blockN == vobu_length to do expected_nav */
this->vobu.vobu_length = 0;
- this->vobu.blockN = 1;
+ this->vobu.blockN = 0;
this->sync_wait = 0;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
@@ -569,9 +570,9 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
/* vobu info is used for mid cell resumes */
this->vobu.vobu_start = this->position_next.cell_start + this->position_next.block;
this->vobu.vobu_next = 0;
- /* Make blockN > vobu_length to do expected_nav */
+ /* Make blockN == vobu_length to do expected_nav */
this->vobu.vobu_length = 0;
- this->vobu.blockN = 1;
+ this->vobu.blockN = 0;
/* update the spu palette at least on PGC changes */
this->spu_clut_changed = 1;
@@ -979,6 +980,13 @@ uint32_t dvdnav_get_next_still_flag(dvdnav_t *this) {
/*
* $Log: dvdnav.c,v $
+ * Revision 1.18 2003/03/21 22:13:37 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.17 2003/02/26 20:44:12 mroi
* sync to current libdvdnav cvs, important change is the new DVDNAV_WAIT event,
* which allows us to keep libdvdnav and what is seen on screen in sync in certain
diff --git a/src/input/libdvdnav/dvdnav.h b/src/input/libdvdnav/dvdnav.h
index 6702f6784..69f2367cc 100644
--- a/src/input/libdvdnav/dvdnav.h
+++ b/src/input/libdvdnav/dvdnav.h
@@ -17,7 +17,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: dvdnav.h,v 1.6 2003/02/26 20:44:13 mroi Exp $
+ * $Id: dvdnav.h,v 1.7 2003/03/21 22:13:37 mroi Exp $
*
*/
@@ -376,7 +376,7 @@ dvdnav_status_t dvdnav_stop(dvdnav_t *self);
dvdnav_status_t dvdnav_go_up(dvdnav_t *self);
/**
- * Stop playing the current title and jump to the specified menu.
+ * Stop playing the current position and jump to the specified menu.
*
* \param self Pointer to dvdnav_t associated with this operation.
* \param menu Which menu to call (see DVDMenuID_t).
@@ -407,7 +407,7 @@ dvdnav_status_t dvdnav_current_title_info(dvdnav_t *self, int *title,
*/
/**
- * Stop playing the current title and start playback of the title
+ * Stop playing the current position and start playback of the title
* from the specified timecode.
*
* \par Note:
@@ -420,7 +420,12 @@ dvdnav_status_t dvdnav_time_search(dvdnav_t *self,
unsigned long int time);
/**
- * Stop playing the current title and start playback of the title
+ * 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.
+ *
* from the specified sector offset.
*
* \param self Pointer to dvdnav_t associated with this operation.
@@ -431,7 +436,7 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *self,
unsigned long int offset, int origin);
/**
- * Stop playing the current title and start playback of the title
+ * Stop playing the current position and start playback of the current title
* from the specified part (chapter).
*
* \param self Pointer to dvdnav_t associated with this operation.
@@ -440,24 +445,24 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *self,
dvdnav_status_t dvdnav_part_search(dvdnav_t *self, int part);
/**
- * Stop playing the current title and start playback of the title
- * from the previous program (if it exists).
+ * Stop playing the current position and start playback at the
+ * previous program (if it exists).
*
* \param self Pointer to dvdnav_t associated with this operation.
*/
dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *self);
/**
- * Stop playing the current title and start playback of the title
- * from the first program.
+ * Stop playing the current position and start playback at the
+ * first program.
*
* \param self Pointer to dvdnav_t associated with this operation.
*/
dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *self);
/**
- * Stop playing the current title and start playback of the title
- * from the next program (if it exists).
+ * Stop playing the current position and start playback at the
+ * next program (if it exists).
*
* \param self Pointer to dvdnav_t associated with this operation.
*/
@@ -465,11 +470,11 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *self);
/**
* Return the current position (in blocks) within the current
- * part and the length (in blocks) of said part.
+ * program and the length (in blocks) of current program.
*
* \param self Pointer to dvdnav_t associated with this operation.
* \param pos Pointer to unsigned int to get the current position.
- * \param len Pointer to unsinged int to hold the length of the current part.
+ * \param len Pointer to unsinged int to hold the length of the current program.
*/
dvdnav_status_t dvdnav_get_position(dvdnav_t *self, unsigned int *pos,
unsigned int *len);
@@ -478,6 +483,10 @@ dvdnav_status_t dvdnav_get_position(dvdnav_t *self, unsigned int *pos,
* Return the current position (in blocks) within the current
* title and the length (in blocks) of said title.
*
+ * \par Note:
+ * Current implementation is wrong and likely to behave unpredictably.
+ * Use is discouraged.
+ *
* \param self Pointer to dvdnav_t associated with this operation.
* \param pos Pointer to unsigned int to get the current position.
* \param len Pointer to unsinged int to hold the length of the current title.
diff --git a/src/input/libdvdnav/searching.c b/src/input/libdvdnav/searching.c
index 526fb94e8..195ee9705 100644
--- a/src/input/libdvdnav/searching.c
+++ b/src/input/libdvdnav/searching.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net>
*
* This file is part of libdvdnav, a DVD navigation library.
@@ -17,7 +17,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: searching.c,v 1.10 2003/03/08 14:36:13 mroi Exp $
+ * $Id: searching.c,v 1.11 2003/03/21 22:13:38 mroi Exp $
*
*/
@@ -177,14 +177,16 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
}
found = 0;
- target += state->pgc->cell_playback[first_cell_nr-1].first_sector;
for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) {
cell = &(state->pgc->cell_playback[cell_nr-1]);
- if((cell->first_sector <= target) && (cell->last_sector >= target)) {
+ length = cell->last_sector - cell->first_sector + 1;
+ if (target >= length) {
+ target -= length;
+ } else {
+ /* convert the target sector from Cell-relative to absolute physical sector */
+ target += cell->first_sector;
found = 1;
- state->cellN = cell_nr;
- state->blockN = 0;
- state->cell_restart++;
+ break;
}
}
@@ -192,10 +194,14 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
int32_t vobu, start;
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n",
- state->cellN, first_cell_nr, last_cell_nr);
+ cell_nr, first_cell_nr, last_cell_nr);
#endif
dvdnav_scan_admap(this, state->domain, target, &vobu);
- start = state->pgc->cell_playback[state->cellN - 1].first_sector;
+
+ start = state->pgc->cell_playback[cell_nr-1].first_sector;
+ state->blockN = vobu - start;
+ state->cellN = cell_nr;
+ state->cell_restart++;
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" ,
state->cellN,
@@ -204,13 +210,6 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
vobu,
start);
#endif
- state->blockN = vobu - start;
-#ifdef LOG_DEBUG
- fprintf(MSG_OUT, "libdvdnav: After vobu=%x start=%x blockN=%x\n" ,
- vobu,
- start,
- state->blockN);
-#endif
this->vm->hop_channel += HOP_SEEK;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
@@ -298,6 +297,7 @@ dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) {
}
dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
+ vm_t *try_vm;
if(!this) {
printerr("Passed a NULL pointer.");
@@ -314,12 +314,24 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: next chapter\n");
#endif
- if (!vm_jump_next_pg(this->vm)) {
- fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n");
- printerr("Skip to next chapter failed.");
- pthread_mutex_unlock(&this->vm_lock);
- return S_ERR;
+ /* make a copy of current VM and try to navigate the copy to the next PG */
+ try_vm = vm_new_copy(this->vm);
+ if (!vm_jump_next_pg(try_vm) || try_vm->stopped) {
+ vm_free_copy(try_vm);
+ /* next_pg failed, try to jump at least to the next cell */
+ try_vm = vm_new_copy(this->vm);
+ vm_get_next_cell(try_vm);
+ if (try_vm->stopped) {
+ vm_free_copy(try_vm);
+ fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n");
+ printerr("Skip to next chapter failed.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
}
+ /* merge changes on success */
+ vm_merge(this->vm, try_vm);
+ vm_free_copy(try_vm);
this->position_current.still = 0;
this->vm->hop_channel++;
#ifdef LOG_DEBUG
@@ -331,6 +343,7 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
}
dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) {
+ vm_t *try_vm;
if(!this) {
printerr("Passed a NULL pointer.");
@@ -344,12 +357,19 @@ dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) {
return S_ERR;
}
- if (vm_jump_menu(this->vm, menu)) {
+ /* make a copy of current VM and try to navigate the copy to the menu */
+ try_vm = vm_new_copy(this->vm);
+ if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) {
+ /* merge changes on success */
+ vm_merge(this->vm, try_vm);
+ vm_free_copy(try_vm);
+ this->position_current.still = 0;
this->vm->hop_channel++;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
} else {
- printerr("No such menu.");
+ vm_free_copy(try_vm);
+ printerr("No such menu or menu not reachable.");
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
@@ -358,8 +378,10 @@ dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) {
dvdnav_status_t dvdnav_get_position(dvdnav_t *this, unsigned int *pos,
unsigned int *len) {
uint32_t cur_sector;
+ uint32_t cell_nr;
uint32_t first_cell_nr;
uint32_t last_cell_nr;
+ cell_playback_t *cell;
cell_playback_t *first_cell;
cell_playback_t *last_cell;
dvd_state_t *state;
@@ -395,9 +417,21 @@ dvdnav_status_t dvdnav_get_position(dvdnav_t *this, unsigned int *pos,
last_cell_nr = state->pgc->nr_of_cells;
}
last_cell = &(state->pgc->cell_playback[last_cell_nr-1]);
+
+ *pos = -1;
+ *len = 0;
+ for (cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr++) {
+ cell = &(state->pgc->cell_playback[cell_nr-1]);
+ if (cell_nr == state->cellN) {
+ /* the current sector is in this cell,
+ * pos is length of PG up to here + sector's offset in this cell */
+ *pos = *len + cur_sector - cell->first_sector;
+ }
+ *len += cell->last_sector - cell->first_sector + 1;
+ }
+
+ assert(*pos != -1);
- *pos= cur_sector - first_cell->first_sector;
- *len= last_cell->last_sector - first_cell->first_sector;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
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:
diff --git a/src/input/libdvdnav/vm.h b/src/input/libdvdnav/vm.h
index 9b1f0cfc8..ee5e4d16f 100644
--- a/src/input/libdvdnav/vm.h
+++ b/src/input/libdvdnav/vm.h
@@ -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.h,v 1.4 2003/02/20 16:02:01 mroi Exp $
+ * $Id: vm.h,v 1.5 2003/03/21 22:13:39 mroi Exp $
*
*/
@@ -113,7 +113,7 @@ typedef struct {
#define PTL_REG registers.SPRM[13]
/* Initialisation & destruction */
-vm_t* vm_new_vm();
+vm_t *vm_new_vm();
void vm_free_vm(vm_t *vm);
/* IFO access */
@@ -128,6 +128,11 @@ 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);