summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/input/input_dvd.c350
-rw-r--r--src/input/libdvdnav/decoder.c17
-rw-r--r--src/input/libdvdnav/decoder.h24
-rw-r--r--src/input/libdvdnav/diff_against_cvs.patch35
-rw-r--r--src/input/libdvdnav/dvdnav.c891
-rw-r--r--src/input/libdvdnav/dvdnav.h149
-rw-r--r--src/input/libdvdnav/dvdnav_events.h57
-rw-r--r--src/input/libdvdnav/dvdnav_internal.h48
-rw-r--r--src/input/libdvdnav/highlight.c299
-rw-r--r--src/input/libdvdnav/navigation.c135
-rw-r--r--src/input/libdvdnav/read_cache.c4
-rw-r--r--src/input/libdvdnav/remap.c32
-rw-r--r--src/input/libdvdnav/remap.h20
-rw-r--r--src/input/libdvdnav/searching.c324
-rw-r--r--src/input/libdvdnav/settings.c62
-rw-r--r--src/input/libdvdnav/vm.c1685
-rw-r--r--src/input/libdvdnav/vm.h141
-rw-r--r--src/input/libdvdnav/vmcmd.c6
-rw-r--r--src/input/libdvdnav/vmcmd.h4
19 files changed, 1977 insertions, 2306 deletions
diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c
index e8961055e..b5f254621 100644
--- a/src/input/input_dvd.c
+++ b/src/input/input_dvd.c
@@ -18,7 +18,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: input_dvd.c,v 1.128 2003/02/14 18:00:38 heikos Exp $
+ * $Id: input_dvd.c,v 1.129 2003/02/20 16:01:57 mroi Exp $
*
*/
@@ -110,10 +110,6 @@
/* Some misc. defines */
#define DVD_BLOCK_SIZE 2048
-#ifndef BUF_DEMUX_BLOCK
-#define BUF_DEMUX_BLOCK 0x05000000
-#endif
-#define VIDEO_FILL_THROTTLE 5
/* Debugging macros */
#ifdef __GNUC__
@@ -159,8 +155,7 @@ typedef struct {
char *mrl; /* Current MRL */
int mode;
dvdnav_t *dvdnav; /* Handle for libdvdnav */
- char dvd_name[128];
- size_t dvd_name_length;
+ const char *dvd_name;
/*
xine_mrl_t **mrls;
int num_mrls;
@@ -174,6 +169,7 @@ typedef struct {
void (*free_buffer)(buf_element_t *);
int mem_stack;
unsigned char *mem[1024];
+ int freeing;
} dvd_input_plugin_t;
typedef struct {
@@ -198,7 +194,6 @@ typedef struct {
} dvd_input_class_t;
static void dvd_handle_events(dvd_input_plugin_t *this);
-static void flush_buffers(dvd_input_plugin_t *this);
static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode);
/* Callback on device name change */
@@ -300,10 +295,10 @@ void update_title_display(dvd_input_plugin_t *this) {
}
ui_str_length = strlen(this->ui_title);
- if (this->dvd_name[0] != 0 && (ui_str_length + this->dvd_name_length < MAX_STR_LEN)) {
- snprintf(this->ui_title+ui_str_length, MAX_STR_LEN - ui_str_length,
- ", %s",
- &this->dvd_name[0]);
+ if (this->dvd_name && this->dvd_name[0] &&
+ (ui_str_length + strlen(this->dvd_name) < MAX_STR_LEN)) {
+ snprintf(this->ui_title+ui_str_length, MAX_STR_LEN - ui_str_length,
+ ", %s", this->dvd_name);
}
#ifdef INPUT_DEBUG
printf("input_dvd: Changing title to read '%s'\n", this->ui_title);
@@ -330,12 +325,10 @@ static void dvd_plugin_dispose (input_plugin_t *this_gen) {
trace_print("Called\n");
xine_event_dispose_queue (this->event_queue);
- if(this->opened || this->dvdnav)
- dvdnav_close(this->dvdnav);
- this->dvdnav = NULL;
- this->opened = 0;
- this->dvd_name[0] = 0;
- this->dvd_name_length = 0;
+ dvdnav_close(this->dvdnav);
+ /* raise the freeing flag, so that the plugin will be freed as soon
+ * as all buffers have returned to the libdvdnav read ahead cache */
+ this->freeing = 1;
}
@@ -438,6 +431,11 @@ static void dvd_plugin_free_buffer(buf_element_t *buf) {
pthread_mutex_unlock(&this->buf_mutex);
/* give this buffer back to xine's pool */
buf->free_buffer(buf);
+ if (this->freeing && !this->mem_stack) {
+ /* all buffers returned, we can free the plugin now */
+ pthread_mutex_destroy(&this->buf_mutex);
+ free(this);
+ }
}
static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
@@ -476,8 +474,8 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
}
switch(event) {
- case DVDNAV_BLOCK_OK:
- {
+ case DVDNAV_BLOCK_OK:
+ {
buf->content = block;
buf->type = BUF_DEMUX_BLOCK;
@@ -488,64 +486,57 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
this->seekable = 1;
finished = 1;
- }
+ }
break;
- case DVDNAV_NOP:
- {
- /* Nothing */
- }
+ case DVDNAV_NOP:
break;
- case DVDNAV_STILL_FRAME:
- {
-
- /* OK, So xine no-longer accepts BUF_VIDEO_FILLs, find out
- * how else we provide the hint
- */
- dvdnav_still_event_t *still_event =
- (dvdnav_still_event_t*)(block);
- buf->type = BUF_CONTROL_NOP;
- finished = 1;
+ case DVDNAV_STILL_FRAME:
+ {
+ dvdnav_still_event_t *still_event =
+ (dvdnav_still_event_t*)block;
+ buf->type = BUF_CONTROL_NOP;
+ finished = 1;
- /* stills are not seekable */
- this->seekable = 0;
-
- /* Xine's method of doing still-frames */
- if (this->pause_timer == 0) {
+ /* stills are not seekable */
+ this->seekable = 0;
+
+ /* Xine's method of doing still-frames */
+ if (this->pause_timer == 0) {
#ifdef INPUT_DEBUG
- printf("input_dvd: Stillframe! (pause time = 0x%02x)\n",
+ printf("input_dvd: Stillframe! (pause time = 0x%02x)\n",
still_event->length);
#endif
- this->pause_timer = still_event->length;
- this->pause_end_time = time(NULL) + this->pause_timer;
- this->pause_counter = 0;
- break;
- }
-
- if(this->pause_timer == 0xff) {
- this->pause_counter++;
- xine_usec_sleep(100000);
- break;
- }
- if ( (this->pause_timer != 0xFF) &&
- (time(NULL) >= this->pause_end_time) ){
- this->pause_timer = 0;
- this->pause_end_time = 0;
- dvdnav_still_skip(this->dvdnav);
- break;
- }
- if(this->pause_timer) {
- this->pause_counter++;
+ this->pause_timer = still_event->length;
+ this->pause_end_time = time(NULL) + this->pause_timer;
+ this->pause_counter = 0;
+ break;
+ }
+
+ if(this->pause_timer == 0xff) {
+ this->pause_counter++;
+ xine_usec_sleep(50000);
+ break;
+ }
+ if ((this->pause_timer != 0xff) &&
+ (time(NULL) >= this->pause_end_time)) {
+ this->pause_timer = 0;
+ this->pause_end_time = 0;
+ dvdnav_still_skip(this->dvdnav);
+ break;
+ }
+ if(this->pause_timer) {
+ this->pause_counter++;
#ifdef INPUT_DEBUG
- printf("input_dvd: Stillframe! (pause_timer = 0x%02x) counter=%d\n",
+ printf("input_dvd: Stillframe! (pause_timer = 0x%02x) counter=%d\n",
still_event->length, this->pause_counter);
#endif
- xine_usec_sleep(100000);
- break;
- }
- }
- break;
- case DVDNAV_SPU_STREAM_CHANGE:
- {
+ xine_usec_sleep(50000);
+ break;
+ }
+ }
+ break;
+ case DVDNAV_SPU_STREAM_CHANGE:
+ {
dvdnav_spu_stream_change_event_t *stream_event =
(dvdnav_spu_stream_change_event_t*) (block);
buf->content = block;
@@ -560,10 +551,10 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
stream_event->physical_pan_scan);
#endif
finished = 1;
- }
+ }
break;
- case DVDNAV_AUDIO_STREAM_CHANGE:
- {
+ case DVDNAV_AUDIO_STREAM_CHANGE:
+ {
dvdnav_audio_stream_change_event_t *stream_event =
(dvdnav_audio_stream_change_event_t*) (block);
buf->content = block;
@@ -573,15 +564,13 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
printf("input_dvd: AUDIO stream %d\n", stream_event->physical);
#endif
finished = 1;
- }
+ }
break;
- case DVDNAV_HIGHLIGHT:
- {
- xine_dvd_send_button_update(this, 0);
- }
+ case DVDNAV_HIGHLIGHT:
+ xine_dvd_send_button_update(this, 0);
break;
- case DVDNAV_VTS_CHANGE:
- {
+ case DVDNAV_VTS_CHANGE:
+ {
int aspect, permission;
#ifdef INPUT_DEBUG
printf("input_dvd: VTS change\n");
@@ -596,60 +585,50 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen,
buf->decoder_info[2] = aspect;
buf->decoder_info[3] = permission;
finished = 1;
- }
+ }
break;
- case DVDNAV_CELL_CHANGE:
- {
- xine_event_t event;
-
- /* Tell Xine to update the UI */
- event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
- event.stream = this->stream;
- event.data = NULL;
- event.data_length = 0;
- xine_event_send(this->stream, &event);
-
- update_title_display(this);
- }
+ case DVDNAV_CELL_CHANGE:
+ {
+ xine_event_t event;
+
+ /* Tell Xine to update the UI */
+ event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
+ event.stream = this->stream;
+ event.data = NULL;
+ event.data_length = 0;
+ xine_event_send(this->stream, &event);
+
+ update_title_display(this);
+ }
break;
- case DVDNAV_SEEK_DONE:
- {
-#ifdef INPUT_DEBUG
- printf("input_dvd: Seek done\n");
-#endif
- /* FIXME: This should send a message to clear all currently displaying subtitle. */
- }
+ case DVDNAV_HOP_CHANNEL:
+ xine_demux_flush_engine(this->stream);
break;
- case DVDNAV_HOP_CHANNEL:
- {
- flush_buffers(this);
- break;
- }
- case DVDNAV_NAV_PACKET:
- {
+ case DVDNAV_NAV_PACKET:
+ {
buf->content = block;
buf->type = BUF_DEMUX_BLOCK;
finished = 1;
- }
+ }
break;
- case DVDNAV_SPU_CLUT_CHANGE:
- {
+ case DVDNAV_SPU_CLUT_CHANGE:
+ {
buf->content = block;
buf->type = BUF_SPU_DVD;
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE;
buf->decoder_info[2] = SPU_DVD_SUBTYPE_CLUT;
finished = 1;
- }
+ }
break;
- case DVDNAV_STOP:
- {
+ case DVDNAV_STOP:
+ {
if (buf->mem != block) dvdnav_free_cache_block(this->dvdnav, block);
buf->free_buffer(buf);
/* return NULL to indicate end of stream */
return NULL;
- }
- default:
+ }
+ default:
printf("input_dvd: FIXME: Unknown event (%i)\n", event);
break;
}
@@ -702,8 +681,6 @@ static off_t dvd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin
}
return dvdnav_sector_search(this->dvdnav, offset / DVD_BLOCK_SIZE , origin) * DVD_BLOCK_SIZE;
-
- return -1;
}
static off_t dvd_plugin_get_current_pos (input_plugin_t *this_gen){
@@ -731,7 +708,6 @@ static off_t dvd_plugin_get_length (input_plugin_t *this_gen) {
if(!this || !this->dvdnav) {
return 0;
}
-
result = dvdnav_get_position(this->dvdnav, &pos, &length);
return (off_t)length * (off_t)2048;
}
@@ -778,11 +754,6 @@ static char* dvd_plugin_get_mrl (input_plugin_t *this_gen) {
return this->mrl;
}
-static void flush_buffers(dvd_input_plugin_t *this) {
-
- xine_demux_flush_engine(this->stream);
-}
-
static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode) {
int32_t button;
int32_t show;
@@ -920,8 +891,8 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
return;
}
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
- xine_dvd_send_button_update(this, 1);
- dvdnav_button_activate(this->dvdnav, &nav_pci);
+ if (dvdnav_button_activate(this->dvdnav, &nav_pci) == DVDNAV_STATUS_OK)
+ xine_dvd_send_button_update(this, 1);
}
}
break;
@@ -933,8 +904,8 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
}
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
xine_input_data_t *input = event->data;
- xine_dvd_send_button_update(this, 1);
- dvdnav_mouse_activate(this->dvdnav, &nav_pci, input->x, input->y);
+ if (dvdnav_mouse_activate(this->dvdnav, &nav_pci, input->x, input->y) == DVDNAV_STATUS_OK)
+ xine_dvd_send_button_update(this, 1);
}
}
break;
@@ -950,63 +921,49 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
case XINE_EVENT_INPUT_MOUSE_MOVE:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
xine_input_data_t *input = event->data;
/* printf("input_dvd: Mouse move (x,y) = (%i,%i)\n", input->x, input->y); */
dvdnav_mouse_select(this->dvdnav, &nav_pci, input->x, input->y);
- xine_dvd_send_button_update(this, 0);
}
}
break;
case XINE_EVENT_INPUT_UP:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_upper_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_DOWN:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_lower_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_LEFT:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_left_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_RIGHT:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
- if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
+ if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) )
dvdnav_right_button_select(this->dvdnav, &nav_pci);
- xine_dvd_send_button_update(this, 0);
- }
break;
}
case XINE_EVENT_INPUT_NUMBER_9:
@@ -1030,13 +987,11 @@ static void dvd_handle_events(dvd_input_plugin_t *this) {
case XINE_EVENT_INPUT_NUMBER_0:
{
pci_t nav_pci;
- if(!this->stream || !this->stream->spu_decoder_plugin) {
+ if(!this->stream || !this->stream->spu_decoder_plugin)
return;
- }
if (this->stream->spu_decoder_plugin->get_nav_pci(this->stream->spu_decoder_plugin, &nav_pci) ) {
- dvdnav_button_select(this->dvdnav, &nav_pci, this->typed_buttonN);
- xine_dvd_send_button_update(this, 1);
- dvdnav_button_activate(this->dvdnav, &nav_pci);
+ if (dvdnav_button_select_and_activate(this->dvdnav, &nav_pci, this->typed_buttonN) == DVDNAV_STATUS_OK)
+ xine_dvd_send_button_update(this, 1);
this->typed_buttonN = 0;
}
break;
@@ -1199,12 +1154,12 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
xine_event_t event;
static char *handled_mrl = "dvd:/";
+ trace_print("Called\n");
+
/* Check we can handle this MRL */
if (strncasecmp (data, handled_mrl, strlen(handled_mrl) ) != 0)
return NULL;
- printf("input_dvd.c: open_plugin called.\n");
-
this = (dvd_input_plugin_t *) xine_xmalloc (sizeof (dvd_input_plugin_t));
if (this == NULL) {
printf("input_dvd.c: xine_xmalloc failed!!!! You have run out of memory\n");
@@ -1231,8 +1186,7 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
this->seekable = 0;
this->buttonN = 0;
this->typed_buttonN = 0;
- this->dvd_name[0] = 0;
- this->dvd_name_length = 0;
+ this->dvd_name = NULL;
this->mrl = NULL;
/*
this->mrls = NULL;
@@ -1241,15 +1195,14 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
pthread_mutex_init(&this->buf_mutex, NULL);
this->mem_stack = 0;
- trace_print("Called\n");
+ this->freeing = 0;
+
this->event_queue = xine_event_new_queue (this->stream);
/* printf("input_dvd: open1: dvdnav=%p opened=%d\n",this->dvdnav, this->opened); */
/* printf("data=%p\n",data);
if (data) printf("data=%s\n",data); */
- this->mrl = strdup(data);
+ this->mrl = strdup(data);
this->pause_timer = 0;
- this->dvd_name[0] = 0;
- this->dvd_name_length = 0;
/* we already checked the "dvd:/" MRL above */
locator = &this->mrl[strlen(handled_mrl)];
@@ -1277,8 +1230,6 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
this->mode = MODE_NAVIGATE;
}
- printf("input_dvd.c:open_plugin:dvd_device=%s\n",class->dvd_device);
-
if(this->opened) {
if ( intended_dvd_device==this->current_dvd_device ) {
/* Already open, so skip opening */
@@ -1304,61 +1255,8 @@ static input_plugin_t *open_plugin (input_class_t *class_gen, xine_stream_t *str
this->opened=1;
this->current_dvd_device=intended_dvd_device;
}
- if (1) {
- int fd, i;
- off64_t off;
- uint8_t data[DVD_VIDEO_LB_LEN];
-
- /* Read DVD name */
- fd=open(intended_dvd_device, O_RDONLY);
- if (fd > 0) {
- off = lseek64( fd, 32 * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
- if( off == ( 32 * (int64_t) DVD_VIDEO_LB_LEN ) ) {
- off = read( fd, data, DVD_VIDEO_LB_LEN );
- close(fd);
- if (off == ( (int64_t) DVD_VIDEO_LB_LEN )) {
- printf("input_dvd: DVD Title: ");
- for(i=25; i < 73; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- printf("%c", data[i]);
- } else {
- printf(" ");
- }
- }
- strncpy(&this->dvd_name[0], &data[25], 48);
- /* printf("input_dvd: TITLE:%s\n",&this->dvd_name[0]); */
- this->dvd_name[48]=0;
- this->dvd_name_length=strlen(&this->dvd_name[0]);
- printf("\ninput_dvd: DVD Serial Number: ");
- for(i=73; i < 89; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- printf("%c", data[i]);
- } else {
- printf(" ");
- }
- }
- printf("\ninput_dvd: DVD Title (Alternative): ");
- for(i=89; i < 128; i++ ) {
- if((data[i] == 0)) break;
- if((data[i] > 32) && (data[i] < 127)) {
- printf("%c", data[i]);
- } else {
- printf(" ");
- }
- }
- printf("\n");
- } else {
- printf("input_dvd: Can't read name block. Probably not a DVD-ROM device.\n");
- }
- } else {
- printf("input_dvd: Can't seek to block %u\n", 32 );
- }
- } else {
- printf("input_dvd: NAME OPEN FAILED\n");
- }
- }
+
+ dvdnav_get_title_string(this->dvdnav, &this->dvd_name);
/* config callbacks may react now */
class->ip = this;
@@ -1464,7 +1362,7 @@ static xine_mrl_t **dvd_class_get_dir (input_class_t *this_gen,
}
#endif
-static char ** dvd_class_get_autoplay_list (input_class_t *this_gen,
+static char **dvd_class_get_autoplay_list (input_class_t *this_gen,
int *num_files) {
dvd_input_class_t *this = (dvd_input_class_t *) this_gen;
@@ -1658,6 +1556,16 @@ static void *init_class (xine_t *xine, void *data) {
/*
* $Log: input_dvd.c,v $
+ * Revision 1.129 2003/02/20 16:01:57 mroi
+ * syncing to libdvdnav 0.1.5 and modifying input plugin accordingly
+ * quoting the ChangeLog:
+ * * some bugfixes
+ * * code cleanup
+ * * build process polishing
+ * * more sensible event order in get_next_block to ensure useful event delivery
+ * * VOBU level resume
+ * * fixed: seeking in a multiangle feature briefly showed the wrong angle
+ *
* Revision 1.128 2003/02/14 18:00:38 heikos
* FreeBSD compile fixes
*
diff --git a/src/input/libdvdnav/decoder.c b/src/input/libdvdnav/decoder.c
index c7d27eeb0..d10fe154e 100644
--- a/src/input/libdvdnav/decoder.c
+++ b/src/input/libdvdnav/decoder.c
@@ -18,7 +18,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: decoder.c,v 1.5 2002/09/04 11:07:47 mroi Exp $
+ * $Id: decoder.c,v 1.6 2003/02/20 16:01:58 mroi Exp $
*
*/
@@ -41,13 +41,14 @@ uint32_t vm_getbits(command_t *command, int start, int count) {
uint64_t bit_mask=0xffffffffffffffff; /* I could put -1 instead */
uint64_t examining = 0;
int32_t bits;
+
if (count == 0) return 0;
if ( ((count+start) > 64) ||
(count > 32) ||
(start > 63) ||
(count < 0) ||
- (start < 0) ){
+ (start < 0) ) {
fprintf(MSG_OUT, "libdvdnav: Bad call to vm_getbits. Parameter out of range\n");
assert(0);
}
@@ -101,7 +102,7 @@ static uint16_t eval_reg(command_t* command, uint8_t reg) {
if(reg & 0x80) {
if ((reg & 0x1f) == 20) {
fprintf(MSG_OUT, "libdvdnav: Suspected RCE Region Protection!!!");
- }
+ }
return command->registers->SPRM[reg & 0x1f]; /* FIXME max 24 not 32 */
} else {
return get_GPRM(command->registers, reg & 0x0f) ;
@@ -570,8 +571,7 @@ static int32_t eval_command(uint8_t *bytes, registers_t* registers, link_t *retu
return res;
}
-/* Evaluate a set of commands in the given register set (which is
- * modified */
+/* Evaluate a set of commands in the given register set (which is modified) */
int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands,
registers_t *registers, link_t *return_values) {
int32_t i = 0;
@@ -587,6 +587,7 @@ int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands,
fprintf(MSG_OUT, "libdvdnav: --------------------------------------------\n");
fprintf(MSG_OUT, "libdvdnav: Single stepping commands\n");
#endif
+
i = 0;
while(i < num_commands && total < 100000) {
int32_t line;
@@ -594,6 +595,7 @@ int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands,
#ifdef TRACE
vmPrint_CMD(i, &commands[i]);
#endif
+
line = eval_command(&commands[i].bytes[0], registers, return_values);
if (line < 0) { /* Link command */
@@ -621,6 +623,8 @@ int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands,
return 0;
}
+#ifdef TRACE
+
static char *linkcmd2str(link_cmd_t cmd) {
switch(cmd) {
case LinkNoLink:
@@ -762,3 +766,6 @@ void vmPrint_registers( registers_t *registers ) {
fprintf(MSG_OUT, "%04lx|", registers->GPRM_time[i].tv_sec & 0xffff);
fprintf(MSG_OUT, "\n");
}
+
+#endif
+
diff --git a/src/input/libdvdnav/decoder.h b/src/input/libdvdnav/decoder.h
index 24657e889..6a91323f7 100644
--- a/src/input/libdvdnav/decoder.h
+++ b/src/input/libdvdnav/decoder.h
@@ -18,7 +18,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: decoder.h,v 1.4 2002/09/04 11:07:47 mroi Exp $
+ * $Id: decoder.h,v 1.5 2003/02/20 16:01:58 mroi Exp $
*
*/
@@ -30,9 +30,7 @@
#include "ifo_types.h" /* vm_cmd_t */
-/* Uncomment for tracing */
-/* #define TRACE */
-
+/* link command types */
typedef enum {
LinkNoLink = 0,
@@ -76,6 +74,7 @@ typedef enum {
PlayThis
} link_cmd_t;
+/* a link's data set */
typedef struct {
link_cmd_t command;
uint16_t data1;
@@ -83,6 +82,7 @@ typedef struct {
uint16_t data3;
} link_t;
+/* the VM registers */
typedef struct {
uint16_t SPRM[24];
uint16_t GPRM[16];
@@ -90,18 +90,28 @@ typedef struct {
struct timeval GPRM_time[16]; /* For counter mode */
} registers_t;
-typedef struct
-{
+/* a VM command data set */
+typedef struct {
uint64_t instruction;
uint64_t examined;
registers_t *registers;
} command_t;
+/* the big VM function, executing the given commands and writing
+ * the link where to continue, the return value indicates if a jump
+ * has been performed */
int vmEval_CMD(vm_cmd_t commands[], int num_commands,
registers_t *registers, link_t *return_values);
+/* extracts some bits from the command */
+uint32_t vm_getbits(command_t* command, int start, int count);
+
+#ifdef TRACE
+/* for debugging: prints a link in readable form */
void vmPrint_LINK(link_t value);
+
+/* for debugging: dumps VM registers */
void vmPrint_registers( registers_t *registers );
-uint32_t vm_getbits(command_t* command, int start, int count);
+#endif
#endif /* DECODER_H_INCLUDED */
diff --git a/src/input/libdvdnav/diff_against_cvs.patch b/src/input/libdvdnav/diff_against_cvs.patch
index c07584634..e7c3ae9d5 100644
--- a/src/input/libdvdnav/diff_against_cvs.patch
+++ b/src/input/libdvdnav/diff_against_cvs.patch
@@ -18,16 +18,11 @@
-#include <dvdread/ifo_types.h> /* vm_cmd_t */
+#include "ifo_types.h" /* vm_cmd_t */
- /* Uncomment for tracing */
- /* #define TRACE */
+ /* link command types */
+ typedef enum {
--- src/input/libdvdnav/dvdnav.c Wed Sep 4 12:50:34 2002
+++ src/input/libdvdnav/dvdnav.c Wed Sep 4 12:50:42 2002
-@@ -30,11 +30,11 @@
- */
-
- #include <pthread.h>
--#include <dvdnav.h>
-+#include "dvdnav.h"
+@@ -33,7 +33,7 @@
#include "dvdnav_internal.h"
#include "read_cache.h"
@@ -36,7 +31,7 @@
#include <stdlib.h>
#include <stdio.h>
-@@ -183,7 +183,7 @@
+@@ -68,7 +68,7 @@
struct timeval time;
/* Create a new structure */
@@ -92,17 +87,22 @@
+#include "ifo_types.h"
- /* Maximum length of an error string */
+ /* Uncomment for VM command tracing */
--- src/input/libdvdnav/highlight.c Wed Sep 4 12:50:34 2002
+++ src/input/libdvdnav/highlight.c Wed Sep 4 12:55:44 2002
-@@ -34,10 +34,10 @@
+@@ -30,7 +30,7 @@
#include "dvdnav_internal.h"
#include "vm.h"
-#include <dvdread/nav_types.h>
+#include "nav_types.h"
+ /*
+ #define BUTTON_TESTING
+@@ -38,7 +38,7 @@
+
#ifdef BUTTON_TESTING
+
-#include <dvdread/nav_print.h>
+#include "nav_print.h"
#include "vmcmd.h"
@@ -110,20 +110,15 @@
static void print_time(dvd_time_t *dtime) {
--- src/input/libdvdnav/searching.c Fri Jul 26 12:58:10 2002
+++ src/input/libdvdnav/searching.c Fri Aug 9 22:03:20 2002
-@@ -25,11 +25,11 @@
- #include "config.h"
- #endif
-
--#include <dvdnav.h>
-+#include "dvdnav.h"
+@@ -30,7 +30,7 @@
#include "dvdnav_internal.h"
#include "vm.h"
-#include <dvdread/nav_types.h>
+#include "nav_types.h"
- /* Searching API calls */
-
+ /*
+ #define LOG_DEBUG
--- src/input/libdvdnav/vm.c Sat Jul 6 18:12:09 2002
+++ src/input/libdvdnav/vm.c Fri Aug 9 22:03:48 2002
@@ -37,8 +37,8 @@
@@ -147,4 +142,4 @@
+#include "ifo_types.h" /* Only for vm_cmd_t */
#include "decoder.h"
- void vmPrint_mnemonic(vm_cmd_t *command);
+ #ifdef TRACE
diff --git a/src/input/libdvdnav/dvdnav.c b/src/input/libdvdnav/dvdnav.c
index aad3bccbb..eeb69015d 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.12 2003/01/29 02:02:03 miguelfreitas Exp $
+ * $Id: dvdnav.c,v 1.13 2003/02/20 16:01:58 mroi Exp $
*
*/
@@ -30,7 +30,6 @@
*/
#include <pthread.h>
-#include "dvdnav.h"
#include "dvdnav_internal.h"
#include "read_cache.h"
@@ -42,121 +41,9 @@
#include "remap.h"
-/*
- * NOTE:
- * All NLCK_*() function are not mutex locked, this made them reusable in
- * a locked context. Take care.
- *
- */
-
-/* Current domain (backend to dvdnav_is_domain_() funcs) */
-static int8_t NLCK_dvdnav_is_domain(dvdnav_t *this, domain_t domain) {
- dvd_state_t *state;
-
- if((!this) || (!this->started) || (!this->vm))
- return -1;
-
- state = &(this->vm->state);
+static dvdnav_status_t dvdnav_clear(dvdnav_t * this) {
+ /* clear everything except file, vm, mutex, readahead */
- if(!state)
- return -1;
-
- return (state->domain == domain) ? 1 : 0;
-}
-
-static int8_t _dvdnav_is_domain(dvdnav_t *this, domain_t domain) {
- int8_t retval;
-
- pthread_mutex_lock(&this->vm_lock);
- retval = NLCK_dvdnav_is_domain(this, domain);
- pthread_mutex_unlock(&this->vm_lock);
-
- return retval;
-}
-
-static int8_t NCLK_dvdnav_get_audio_logical_stream(dvdnav_t *this, uint8_t audio_num) {
- dvd_state_t *state;
- int8_t logical = -1;
-
- if(!NLCK_dvdnav_is_domain(this, VTS_DOMAIN))
- audio_num = 0;
-
- state = &(this->vm->state);
- if (!state || !state->pgc)
- return -1;
-
- if(audio_num < 8) {
- if(state->pgc->audio_control[audio_num] & (1 << 15)) {
- logical = (state->pgc->audio_control[audio_num] >> 8) & 0x07;
- }
- }
-
- return logical;
-}
-
-static int8_t NCLK_dvdnav_get_spu_logical_stream(dvdnav_t *this, uint8_t subp_num) {
- dvd_state_t *state;
- ifo_handle_t *vtsi;
-
- if(!this)
- return -1;
-
- state = &(this->vm->state);
- vtsi = this->vm->vtsi;
-
- if(!vtsi || subp_num >= vtsi->vtsi_mat->nr_of_vts_subp_streams)
- return -1;
-
- return vm_get_subp_stream(this->vm, subp_num, 0);
-}
-
-static int8_t NLCK_dvdnav_get_active_spu_stream(dvdnav_t *this) {
- dvd_state_t *state;
- int8_t subp_num;
- int stream_num;
-
- state = &(this->vm->state);
- subp_num = state->SPST_REG & ~0x40;
- stream_num = NCLK_dvdnav_get_spu_logical_stream(this, subp_num);
-
- if(stream_num == -1)
- for(subp_num = 0; subp_num < 32; subp_num++)
- if(state->pgc->subp_control[subp_num] & (1 << 31)) {
- stream_num = NCLK_dvdnav_get_spu_logical_stream(this, subp_num);
- break;
- }
-
- return stream_num;
-}
-
-uint8_t dvdnav_get_video_aspect(dvdnav_t *this) {
- uint8_t retval;
-
- pthread_mutex_lock(&this->vm_lock);
- retval = (uint8_t) vm_get_video_aspect(this->vm);
- pthread_mutex_unlock(&this->vm_lock);
-
- return retval;
-}
-
-uint8_t dvdnav_get_video_scale_permission(dvdnav_t *this) {
- uint8_t retval;
-
- pthread_mutex_lock(&this->vm_lock);
- retval = (uint8_t) vm_get_video_scale_permission(this->vm);
- pthread_mutex_unlock(&this->vm_lock);
-
- return retval;
-}
-
-dvdnav_status_t dvdnav_clear(dvdnav_t * this) {
- if (!this) {
- printerr("Passed a NULL pointer");
- return S_ERR;
- }
- /* clear everything except path, file, vm, mutex, readahead */
-
- /* path */
if (this->file) DVDCloseFile(this->file);
this->file = NULL;
this->open_vtsN = -1;
@@ -168,17 +55,15 @@ dvdnav_status_t dvdnav_clear(dvdnav_t * this) {
/* Set initial values of flags */
this->position_current.still = 0;
this->skip_still = 0;
- this->stop = 0;
this->spu_clut_changed = 0;
- this->started=0;
- /* this->use_read_ahead */
+ this->started = 0;
dvdnav_read_cache_clear(this->cache);
return S_OK;
}
-dvdnav_status_t dvdnav_open(dvdnav_t** dest, char *path) {
+dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {
dvdnav_t *this;
struct timeval time;
@@ -188,10 +73,9 @@ dvdnav_status_t dvdnav_open(dvdnav_t** dest, char *path) {
(*dest) = NULL;
this = (dvdnav_t*)malloc(sizeof(dvdnav_t));
if(!this)
- return S_ERR;
+ return S_ERR;
memset(this, 0, (sizeof(dvdnav_t) ) ); /* Make sure this structure is clean */
- (*dest) = this;
-
+
pthread_mutex_init(&this->vm_lock, NULL);
/* Initialise the error string */
printerr("");
@@ -199,13 +83,13 @@ dvdnav_status_t dvdnav_open(dvdnav_t** dest, char *path) {
/* Initialise the VM */
this->vm = vm_new_vm();
if(!this->vm) {
- printerr("Error initialising the DVD VM");
+ printerr("Error initialising the DVD VM.");
pthread_mutex_destroy(&this->vm_lock);
free(this);
return S_ERR;
}
- if(vm_reset(this->vm, path) == -1) {
- printerr("Error starting the VM / opening the DVD device");
+ if(!vm_reset(this->vm, path)) {
+ printerr("Error starting the VM / opening the DVD device.");
pthread_mutex_destroy(&this->vm_lock);
vm_free_vm(this->vm);
free(this);
@@ -215,34 +99,34 @@ dvdnav_status_t dvdnav_open(dvdnav_t** dest, char *path) {
/* Set the path. FIXME: Is a deep copy 'right' */
strncpy(this->path, path, MAX_PATH_LEN);
- dvdnav_clear(this);
-
/* Pre-open and close a file so that the CSS-keys are cached. */
this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), 0, DVD_READ_MENU_VOBS);
- if (this->file) DVDCloseFile(this->file);
- this->file = NULL;
/* Start the read-ahead cache. */
this->cache = dvdnav_read_cache_new(this);
- /* Seed the random numbers. So that the DVD VM Command rand()i
- * gives a different start value each time a DVD is played.
- */
- gettimeofday(&time,NULL);
+ /* Seed the random numbers. So that the DVD VM Command rand()
+ * gives a different start value each time a DVD is played. */
+ gettimeofday(&time, NULL);
srand(time.tv_usec);
+ dvdnav_clear(this);
+
+ (*dest) = this;
return S_OK;
}
dvdnav_status_t dvdnav_close(dvdnav_t *this) {
- if(!this) {
- printerr("Passed a NULL pointer");
- return S_ERR;
- }
+
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: close:called\n");
#endif
+ if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
+
if (this->file) {
DVDCloseFile(this->file);
#ifdef LOG_DEBUG
@@ -252,24 +136,18 @@ dvdnav_status_t dvdnav_close(dvdnav_t *this) {
}
/* Free the VM */
- if(this->vm) {
+ if(this->vm)
vm_free_vm(this->vm);
- }
- if (this->file) {
- DVDCloseFile(this->file);
-#ifdef LOG_DEBUG
- fprintf(MSG_OUT, "libdvdnav: close2:file closing\n");
-#endif
- this->file = NULL;
- }
+
pthread_mutex_destroy(&this->vm_lock);
/* We leave the final freeing of the entire structure to the cache,
* because we don't know, if there are still buffers out in the wild,
* that must return first. */
- if(this->cache) {
+ if(this->cache)
dvdnav_read_cache_free(this->cache);
- } else free(this);
+ else
+ free(this);
return S_OK;
}
@@ -280,101 +158,83 @@ dvdnav_status_t dvdnav_reset(dvdnav_t *this) {
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: reset:called\n");
#endif
+
if(!this) {
- printerr("Passed a NULL pointer");
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
-#ifdef LOG_DEBUG
- fprintf(MSG_OUT, "libdvdnav: getting lock\n");
-#endif
+
pthread_mutex_lock(&this->vm_lock);
+
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: reseting vm\n");
#endif
- if(vm_reset(this->vm, NULL) == -1) {
- printerr("Error restarting the VM");
+ if(!vm_reset(this->vm, NULL)) {
+ printerr("Error restarting the VM.");
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: clearing dvdnav\n");
#endif
- result=dvdnav_clear(this);
-#ifdef LOG_DEBUG
- fprintf(MSG_OUT, "libdvdnav: unlocking\n");
-#endif
+ result = dvdnav_clear(this);
+
pthread_mutex_unlock(&this->vm_lock);
return result;
}
-dvdnav_status_t dvdnav_path(dvdnav_t *this, char** path) {
- if(!this || !path || !(*path)) {
+dvdnav_status_t dvdnav_path(dvdnav_t *this, const char** path) {
+
+ if(!this || !path) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
- /* FIXME: Is shallow copy 'right'? */
(*path) = this->path;
return S_OK;
}
-char* dvdnav_err_to_string(dvdnav_t *this) {
- if(!this) {
- /* Shold this be "passed a NULL pointer?" */
+const char* dvdnav_err_to_string(dvdnav_t *this) {
+
+ if(!this)
return "Hey! You gave me a NULL pointer you naughty person!";
- }
return this->err_str;
}
-/**
+/*
* Returns 1 if block contains NAV packet, 0 otherwise.
* Precesses said NAV packet if present.
*
* Most of the code in here is copied from xine's MPEG demuxer
* so any bugs which are found in that should be corrected here also.
*/
-int dvdnav_decode_packet(dvdnav_t *this, uint8_t *p, dsi_t* nav_dsi, pci_t* nav_pci) {
- int bMpeg1=0;
+static int dvdnav_decode_packet(dvdnav_t *this, uint8_t *p, dsi_t *nav_dsi, pci_t *nav_pci) {
+ int bMpeg1 = 0;
uint32_t nHeaderLen;
uint32_t nPacketLen;
uint32_t nStreamID;
-/* uint8_t *p_start=p; */
-
-
- if (p==NULL) {
- fprintf(MSG_OUT, "libdvdnav: Passed a NULL pointer.\n");
- return 0;
- }
-
- /* dprint("Checking packet...\n"); */
if (p[3] == 0xBA) { /* program stream pack header */
-
int nStuffingBytes;
- /* xprintf (VERBOSE|DEMUX, "program stream pack header\n"); */
-
bMpeg1 = (p[4] & 0x40) == 0;
if (bMpeg1) {
- p += 12;
+ p += 12;
} else { /* mpeg2 */
nStuffingBytes = p[0xD] & 0x07;
p += 14 + nStuffingBytes;
}
}
-
if (p[3] == 0xbb) { /* program stream system header */
- int nHeaderLen;
-
nHeaderLen = (p[4] << 8) | p[5];
p += 6 + nHeaderLen;
}
/* we should now have a PES packet here */
-
if (p[0] || p[1] || (p[2] != 1)) {
fprintf(MSG_OUT, "libdvdnav: demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]);
return 0;
@@ -387,14 +247,14 @@ int dvdnav_decode_packet(dvdnav_t *this, uint8_t *p, dsi_t* nav_dsi, pci_t* nav_
p += nHeaderLen;
if (nStreamID == 0xbf) { /* Private stream 2 */
-/*
- * int i;
- * fprintf(MSG_OUT, "libdvdnav: nav packet=%u\n",p-p_start-6);
- * for(i=0;i<80;i++) {
- * fprintf(MSG_OUT, "%02x ",p[i-6]);
- * }
- * fprintf(MSG_OUT, "\n");
- */
+#if 0
+ int i;
+ fprintf(MSG_OUT, "libdvdnav: nav packet=%u\n",p-p_start-6);
+ for(i=0;i<80;i++)
+ fprintf(MSG_OUT, "%02x ",p[i-6]);
+ fprintf(MSG_OUT, "\n");
+#endif
+
if(p[0] == 0x00) {
navRead_PCI(nav_pci, p+1);
}
@@ -405,9 +265,7 @@ int dvdnav_decode_packet(dvdnav_t *this, uint8_t *p, dsi_t* nav_dsi, pci_t* nav_
if(p[6] == 0x01) {
nPacketLen = p[4] << 8 | p[5];
p += 6;
- /* dprint("NAV DSI packet\n"); */
navRead_DSI(nav_dsi, p+1);
-
}
return 1;
}
@@ -417,7 +275,7 @@ int dvdnav_decode_packet(dvdnav_t *this, uint8_t *p, dsi_t* nav_dsi, pci_t* nav_
/* DSI is used for most angle stuff.
* PCI is used for only non-seemless angle stuff
*/
-int dvdnav_get_vobu(dvdnav_t *self, dsi_t* nav_dsi, pci_t* nav_pci, dvdnav_vobu_t* vobu) {
+static int dvdnav_get_vobu(dvdnav_t *this, dsi_t *nav_dsi, pci_t *nav_pci, dvdnav_vobu_t *vobu) {
uint32_t next;
int angle, num_angle;
@@ -436,70 +294,72 @@ int dvdnav_get_vobu(dvdnav_t *self, dsi_t* nav_dsi, pci_t* nav_pci, dvdnav_vobu_
* Should really assert if bit 31 != 1
*/
- /* Relative offset from vobu_start */
- vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff );
-
- /* Old code -- may still be sueful one day
+#if 0
+ /* Old code -- may still be useful one day */
if(nav_dsi->vobu_sri.next_vobu != SRI_END_OF_CELL ) {
vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff );
} else {
vobu->vobu_next = vobu->vobu_length;
- } */
+ }
+#else
+ /* Relative offset from vobu_start */
+ vobu->vobu_next = ( nav_dsi->vobu_sri.next_vobu & 0x3fffffff );
+#endif
- dvdnav_get_angle_info(self, &angle, &num_angle);
-#if 0
+ vm_get_angle_info(this->vm, &angle, &num_angle);
+
/* FIMXE: The angle reset doesn't work for some reason for the moment */
-
+#if 0
if((num_angle < angle) && (angle != 1)) {
- printf("OOOOOOO angle ends!\n");
+ fprintf(MSG_OUT, "libdvdnav: angle ends!\n");
/* This is to switch back to angle one when we
* finish with angles. */
- dvdnav_angle_change(self, 1);
+ dvdnav_angle_change(this, 1);
}
#endif
if(num_angle != 0) {
- next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1];
- if(next != 0) {
+ if((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) {
if((next & 0x3fffffff) != 0) {
- if(next & 0x80000000) {
+ if(next & 0x80000000)
vobu->vobu_next = - (int32_t)(next & 0x3fffffff);
- } else {
+ else
vobu->vobu_next = + (int32_t)(next & 0x3fffffff);
- }
}
-
- } else if( nav_dsi->sml_agli.data[angle-1].address != 0 ) {
- next = nav_dsi->sml_agli.data[angle-1].address;
+ } else if((next = nav_dsi->sml_agli.data[angle-1].address) != 0) {
vobu->vobu_length = nav_dsi->sml_pbi.ilvu_ea;
- if((next & 0x80000000) && (next != 0x7fffffff)) {
+ if((next & 0x80000000) && (next != 0x7fffffff))
vobu->vobu_next = - (int32_t)(next & 0x3fffffff);
- } else {
+ else
vobu->vobu_next = + (int32_t)(next & 0x3fffffff);
- }
}
}
return 1;
}
-/* This is the main get_next_block function which actually gets the media stream video and audio etc.
- * The use of this function is optional, with the application programmer
- * free to implement their own version of this function
- * FIXME: Make the function calls from here public API calls.
+/*
+ * These are the main get_next_block function which actually get the media stream video and audio etc.
+ *
+ * There are two versions: The second one is using the zero-copy read ahead cache and therefore
+ * hands out pointers targetting directly into the cache.
+ * The first one uses a memcopy to fill this cache block into the application provided memory.
+ * The benefit of this first one is that no special memory management is needed. The application is
+ * the only one responsible of allocating and freeing the memory associated with the pointer.
+ * The drawback is the additional memcopy.
*/
dvdnav_status_t dvdnav_get_next_block(dvdnav_t *this, unsigned char *buf,
- int *event, int *len) {
+ int *event, int *len) {
unsigned char *block;
dvdnav_status_t status;
block = buf;
status = dvdnav_get_next_cache_block(this, &block, event, len);
- if (block != buf) {
+ if (status == S_OK && block != buf) {
/* we received a block from the cache, copy it, so we can give it back */
memcpy(buf, block, DVD_VIDEO_LB_LEN);
dvdnav_free_cache_block(this, block);
@@ -508,14 +368,16 @@ dvdnav_status_t dvdnav_get_next_block(dvdnav_t *this, unsigned char *buf,
}
dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
- int *event, int *len) {
+ int *event, int *len) {
dvd_state_t *state;
int result;
+
if(!this || !event || !len || !buf || !*buf) {
- printerr("Passed a NULL pointer");
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
- pthread_mutex_lock(&this->vm_lock);
+
+ pthread_mutex_lock(&this->vm_lock);
if(!this->started) {
/* Start the VM */
@@ -528,45 +390,168 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
(*len) = 0;
/* Check the STOP flag */
- if(this->stop) {
+ if(this->vm->stopped) {
(*event) = DVDNAV_STOP;
+ this->started = 0;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
- /* Check the STILLFRAME flag */
- /* FIXME: Still cell, not still frame */
- if(this->position_current.still != 0) {
- dvdnav_still_event_t still_event;
-
- still_event.length = this->position_current.still;
+ vm_position_get(this->vm, &this->position_next);
+
+#ifdef TRACE
+ fprintf(MSG_OUT, "libdvdnav: POS-NEXT ");
+ vm_position_print(this->vm, &this->position_next);
+ fprintf(MSG_OUT, "libdvdnav: POS-CUR ");
+ vm_position_print(this->vm, &this->position_current);
+#endif
- (*event) = DVDNAV_STILL_FRAME;
- (*len) = sizeof(dvdnav_still_event_t);
- memcpy(*buf, &(still_event), sizeof(dvdnav_still_event_t));
-
+ /* did we hop? */
+ if(this->position_current.hop_channel != this->position_next.hop_channel) {
+ (*event) = DVDNAV_HOP_CHANNEL;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: HOP_CHANNEL\n");
+#endif
+ if (this->position_next.hop_channel > HOP_SEEK) {
+ int num_angles = 0, current;
+
+ /* we seeked -> check for multiple angles */
+ vm_get_angle_info(this->vm, &current, &num_angles);
+ if (num_angles > 1) {
+ int result, block;
+ /* we have to skip the first VOBU when seeking in a multiangle feature,
+ * because it might belong to the wrong angle */
+ block = this->position_next.cell_start + this->position_next.block;
+ result = dvdnav_read_cache_block(this->cache, block, 1, buf);
+ if(result <= 0) {
+ printerr("Error reading NAV packet.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ /* Decode nav into pci and dsi. Then get next VOBU info. */
+ if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) {
+ printerr("Expected NAV packet but none found.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ dvdnav_get_vobu(this, &this->dsi, &this->pci, &this->vobu);
+ /* skip to next, if there is a next */
+ if (this->vobu.vobu_next != SRI_END_OF_CELL) {
+ this->vobu.vobu_start += this->vobu.vobu_next;
+ this->vobu.vobu_next = 0;
+ }
+ /* update VM state */
+ this->vm->state.blockN = this->vobu.vobu_start - this->position_next.cell_start;
+ }
+ }
+ this->position_current.hop_channel = this->position_next.hop_channel;
+ /* Make blockN > vobu_length to do expected_nav */
+ this->vobu.vobu_length = 0;
+ this->vobu.blockN = 1;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
- vm_position_get(this->vm,&this->position_next);
- /**********
- fprintf(MSG_OUT, "libdvdnav: POS-NEXT ");
- vm_position_print(this->vm, &this->position_next);
- fprintf(MSG_OUT, "libdvdnav: POS-CUR ");
- vm_position_print(this->vm, &this->position_current);
- **********/
+ /* Check to see if we need to change the currently opened VOB */
+ if((this->position_current.vts != this->position_next.vts) ||
+ (this->position_current.domain != this->position_next.domain)) {
+ dvd_read_domain_t domain;
+ int vtsN;
+ dvdnav_vts_change_event_t vts_event;
+
+ if(this->file) {
+ DVDCloseFile(this->file);
+ this->file = NULL;
+ }
+
+ vts_event.old_vtsN = this->open_vtsN;
+ vts_event.old_domain = this->open_domain;
+
+ /* Use the DOMAIN to find whether to open menu or title VOBs */
+ switch(this->position_next.domain) {
+ case FP_DOMAIN:
+ case VMGM_DOMAIN:
+ domain = DVD_READ_MENU_VOBS;
+ vtsN = 0;
+ break;
+ case VTSM_DOMAIN:
+ domain = DVD_READ_MENU_VOBS;
+ vtsN = this->position_next.vts;
+ break;
+ case VTS_DOMAIN:
+ domain = DVD_READ_TITLE_VOBS;
+ vtsN = this->position_next.vts;
+ break;
+ default:
+ printerr("Unknown domain when changing VTS.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+
+ this->position_current.vts = this->position_next.vts;
+ this->position_current.domain = this->position_next.domain;
+ dvdnav_read_cache_clear(this->cache);
+ this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), vtsN, domain);
+ vts_event.new_vtsN = this->position_next.vts;
+ vts_event.new_domain = this->position_next.domain;
+
+ /* If couldn't open the file for some reason, moan */
+ if(this->file == NULL) {
+ printerrf("Error opening vtsN=%i, domain=%i.", vtsN, domain);
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
- if(this->position_current.hop_channel != this->position_next.hop_channel) {
- this->position_current.hop_channel = this->position_next.hop_channel;
- (*event) = DVDNAV_HOP_CHANNEL;
- (*len) = 0;
+ /* File opened successfully so return a VTS change event */
+ (*event) = DVDNAV_VTS_CHANGE;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: VTS_CHANGE\n");
+#endif
+ (*len) = sizeof(vts_event);
+ memcpy(*buf, &(vts_event), sizeof(vts_event));
+
+ this->spu_clut_changed = 1;
+ this->position_current.cell = -1; /* Force an update */
+ this->position_current.spu_channel = -1; /* Force an update */
+ this->position_current.audio_channel = -1; /* Force an update */;
+
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
+ /* Check if the cell changed */
+ if( (this->position_current.cell != this->position_next.cell) ||
+ (this->position_current.cell_restart != this->position_next.cell_restart) ||
+ (this->position_current.cell_start != this->position_next.cell_start) ) {
+
+ (*event) = DVDNAV_CELL_CHANGE;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: CELL_CHANGE\n");
+#endif
+ (*len) = 0;
+
+ this->position_current.cell = this->position_next.cell;
+ this->position_current.cell_restart = this->position_next.cell_restart;
+ this->position_current.cell_start = this->position_next.cell_start;
+ this->position_current.block = this->position_next.block;
+
+ /* 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 */
+ this->vobu.vobu_length = 0;
+ this->vobu.blockN = 1;
+
+ /* update the spu palette at least on PGC changes */
+ this->spu_clut_changed = 1;
+ this->position_current.spu_channel = -1; /* Force an update */
+ this->position_current.audio_channel = -1; /* Force an update */
-
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_OK;
+ }
+
+ /* has the CLUT changed? */
if(this->spu_clut_changed) {
(*event) = DVDNAV_SPU_CLUT_CHANGE;
#ifdef LOG_DEBUG
@@ -575,15 +560,14 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
(*len) = 16 * sizeof(uint32_t);
memcpy(*buf, &(state->pgc->palette), 16 * sizeof(uint32_t));
this->spu_clut_changed = 0;
-#ifdef LOG_DEBUG
- fprintf(MSG_OUT, "libdvdnav: SPU_CLUT_CHANGE returning S_OK\n");
-#endif
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
-
+
+ /* has the SPU channel changed? */
if(this->position_current.spu_channel != this->position_next.spu_channel) {
dvdnav_spu_stream_change_event_t stream_change;
+
(*event) = DVDNAV_SPU_STREAM_CHANGE;
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE\n");
@@ -592,7 +576,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
stream_change.physical_wide = vm_get_subp_active_stream(this->vm, 0);
stream_change.physical_letterbox = vm_get_subp_active_stream(this->vm, 1);
stream_change.physical_pan_scan = vm_get_subp_active_stream(this->vm, 2);
- memcpy(*buf, &(stream_change), sizeof( dvdnav_spu_stream_change_event_t));
+ memcpy(*buf, &(stream_change), sizeof(dvdnav_spu_stream_change_event_t));
this->position_current.spu_channel = this->position_next.spu_channel;
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: SPU_STREAM_CHANGE stream_id_wide=%d\n",stream_change.physical_wide);
@@ -609,15 +593,17 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
return S_OK;
}
}
-
+
+ /* has the audio channel changed? */
if(this->position_current.audio_channel != this->position_next.audio_channel) {
dvdnav_audio_stream_change_event_t stream_change;
+
(*event) = DVDNAV_AUDIO_STREAM_CHANGE;
#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: AUDIO_STREAM_CHANGE\n");
#endif
(*len) = sizeof(dvdnav_audio_stream_change_event_t);
- stream_change.physical= vm_get_audio_active_stream( this->vm );
+ stream_change.physical = vm_get_audio_active_stream( this->vm );
memcpy(*buf, &(stream_change), sizeof( dvdnav_audio_stream_change_event_t));
this->position_current.audio_channel = this->position_next.audio_channel;
#ifdef LOG_DEBUG
@@ -628,115 +614,41 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
}
/* Check the HIGHLIGHT flag */
- /* FIXME: Use BUTTON instead of HIGHLIGHT. */
if(this->position_current.button != this->position_next.button) {
dvdnav_highlight_event_t hevent;
- hevent.display = 1;
- hevent.buttonN = this->position_next.button;
-
- this->position_current.button = this->position_next.button;
-
(*event) = DVDNAV_HIGHLIGHT;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: HIGHLIGHT\n");
+#endif
(*len) = sizeof(hevent);
+ hevent.display = 1;
+ hevent.buttonN = this->position_next.button;
memcpy(*buf, &(hevent), sizeof(hevent));
+ this->position_current.button = this->position_next.button;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
- /* Check to see if we need to change the currently opened VOB */
- if((this->position_current.vts != this->position_next.vts) ||
- (this->position_current.domain != this->position_next.domain)) {
- dvd_read_domain_t domain;
- int vtsN;
- dvdnav_vts_change_event_t vts_event;
-
- if(this->file) {
- dvdnav_read_cache_clear(this->cache);
- DVDCloseFile(this->file);
- this->file = NULL;
- }
-
- vts_event.old_vtsN = this->open_vtsN;
- vts_event.old_domain = this->open_domain;
-
- /* Use the current DOMAIN to find whether to open menu or title VOBs */
- switch(this->position_next.domain) {
- case FP_DOMAIN:
- case VMGM_DOMAIN:
- domain = DVD_READ_MENU_VOBS;
- vtsN = 0;
- break;
- case VTSM_DOMAIN:
- domain = DVD_READ_MENU_VOBS;
- vtsN = this->position_next.vts;
- break;
- case VTS_DOMAIN:
- domain = DVD_READ_TITLE_VOBS;
- vtsN = this->position_next.vts;
- break;
- default:
- printerr("Unknown domain when changing VTS.");
- pthread_mutex_unlock(&this->vm_lock);
- return S_ERR;
- }
-
- this->position_current.vts = this->position_next.vts;
- this->position_current.domain = this->position_next.domain;
- dvdnav_read_cache_clear(this->cache);
- this->file = DVDOpenFile(vm_get_dvd_reader(this->vm), vtsN, domain);
- vts_event.new_vtsN = this->position_next.vts;
- vts_event.new_domain = this->position_next.domain;
-
- /* If couldn't open the file for some reason, moan */
- if(this->file == NULL) {
- printerrf("Error opening vtsN=%i, domain=%i.", vtsN, domain);
- pthread_mutex_unlock(&this->vm_lock);
- return S_ERR;
- }
-
- /* File opened successfully so return a VTS change event */
- (*event) = DVDNAV_VTS_CHANGE;
- memcpy(*buf, &(vts_event), sizeof(vts_event));
- (*len) = sizeof(vts_event);
+ /* Check the STILLFRAME flag */
+ if(this->position_current.still != 0) {
+ dvdnav_still_event_t still_event;
- /* On a VTS change, we want to disable any highlights which
- * may have been shown (FIXME: is this valid?) */
- this->spu_clut_changed = 1;
- this->position_current.cell = -1; /* Force an update */
- this->position_current.spu_channel = -1; /* Force an update */
- this->position_current.audio_channel = -1; /* Force an update */;
-
- pthread_mutex_unlock(&this->vm_lock);
- return S_OK;
- }
- /* FIXME: Don't really need "cell", we only need vobu_start */
- if( (this->position_current.cell != this->position_next.cell) ||
- (this->position_current.cell_restart != this->position_next.cell_restart) ||
- (this->position_current.vobu_start != this->position_next.vobu_start) ||
- (this->position_current.vobu_next != this->position_next.vobu_next) ) {
- this->position_current.cell = this->position_next.cell;
- this->position_current.cell_restart = this->position_next.cell_restart;
- /* vobu_start changes when PGC or PG changes. */
- this->position_current.vobu_start = this->position_next.vobu_start;
- this->position_current.vobu_next = this->position_next.vobu_next;
- /* FIXME: Need to set vobu_start, vobu_next */
- this->vobu.vobu_start = this->position_next.vobu_start;
- /* vobu_next is use for mid cell resumes */
- this->vobu.vobu_next = this->position_next.vobu_next;
- this->vobu.vobu_length = 0;
- this->vobu.blockN = this->vobu.vobu_length + 1;
- /* Make blockN > vobu_lenght to do expected_nav */
- (*event) = DVDNAV_CELL_CHANGE;
- (*len) = 0;
+ (*event) = DVDNAV_STILL_FRAME;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: STILL_FRAME\n");
+#endif
+ (*len) = sizeof(dvdnav_still_event_t);
+ still_event.length = this->position_current.still;
+ memcpy(*buf, &(still_event), sizeof(dvdnav_still_event_t));
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
-
-
- if (this->vobu.blockN > this->vobu.vobu_length) {
- /* End of VOBU */
+ /* Have we reached the end of a VOBU? */
+ if (this->vobu.blockN >= this->vobu.vobu_length) {
+
+ /* Have we reached the end of a cell? */
if(this->vobu.vobu_next == SRI_END_OF_CELL) {
/* End of Cell from NAV DSI info */
#ifdef LOG_DEBUG
@@ -745,58 +657,28 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
this->position_current.still = this->position_next.still;
if( this->position_current.still == 0 || this->skip_still ) {
- vm_get_next_cell(this->vm);
- vm_position_get(this->vm,&this->position_next);
- /* FIXME: Need to set vobu_start, vobu_next */
- this->position_current.still = 0; /* still gets activated at end of cell */
- this->skip_still = 0;
- this->position_current.cell = this->position_next.cell;
- this->position_current.vobu_start = this->position_next.vobu_start;
- this->position_current.vobu_next = this->position_next.vobu_next;
- this->vobu.vobu_start = this->position_next.vobu_start;
- /* vobu_next is use for mid cell resumes */
- this->vobu.vobu_next = this->position_next.vobu_next;
- this->vobu.vobu_length = 0;
- this->vobu.blockN = this->vobu.vobu_length + 1;
- /* Make blockN > vobu_next to do expected_nav */
- /* update the spu palette on PGC changes */
- this->spu_clut_changed = 1;
- this->position_current.spu_channel = -1; /* Force an update */
- this->position_current.audio_channel = -1; /* Force an update */;
- (*event) = DVDNAV_CELL_CHANGE;
- (*len) = 0;
- pthread_mutex_unlock(&this->vm_lock);
- return S_OK;
- } else {
- dvdnav_still_event_t still_event;
- still_event.length = this->position_current.still;
- (*event) = DVDNAV_STILL_FRAME;
- (*len) = sizeof(dvdnav_still_event_t);
- memcpy(*buf, &(still_event), sizeof(dvdnav_still_event_t));
- pthread_mutex_unlock(&this->vm_lock);
- return S_OK;
+ /* no active cell still -> get us to the next cell */
+ vm_get_next_cell(this->vm);
+ this->position_current.still = 0; /* still gets activated at end of cell */
+ this->skip_still = 0;
}
-
- /* Only set still after whole VOBU has been output. */
- /*
- if(this->position_next.still != 0) {
- this->position_current.still = this->position_next.still;
- }
- */
-
+ /* handle related state changes in next iteration */
+ (*event) = DVDNAV_NOP;
+ (*len) = 0;
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_OK;
}
- /* Perform the jump if necessary (this is always a
- * VOBU boundary). */
-
- if (this->vm->map) {
- this->vobu.vobu_next = remap_block( this->vm->map,
- this->vm->state.domain, this->vm->state.TTN_REG,
- this->vm->state.pgN,
- this->vobu.vobu_start, this->vobu.vobu_next);
- }
+ /* Perform remapping jump if necessary (this is always a
+ * VOBU boundary). */
+ if (this->vm->map) {
+ this->vobu.vobu_next = remap_block( this->vm->map,
+ this->vm->state.domain, this->vm->state.TTN_REG,
+ this->vm->state.pgN,
+ this->vobu.vobu_start, this->vobu.vobu_next);
+ }
- /* result = DVDReadBlocks(this->file, this->vobu.vobu_start + this->vobu.vobu_next, 1, buf); */
+ /* at the start of the next VOBU -> expecting NAV packet */
result = dvdnav_read_cache_block(this->cache, this->vobu.vobu_start + this->vobu.vobu_next, 1, buf);
if(result <= 0) {
@@ -804,31 +686,29 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
- /* Decode nav into pci and dsi. */
- /* Then get next VOBU info. */
- if(dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci) == 0) {
+ /* Decode nav into pci and dsi. Then get next VOBU info. */
+ if(!dvdnav_decode_packet(this, *buf, &this->dsi, &this->pci)) {
printerr("Expected NAV packet but none found.");
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
- dvdnav_get_vobu(this, &this->dsi,&this->pci, &this->vobu);
- this->vobu.blockN=1;
- /* FIXME: We need to update the vm state->blockN with which VOBU we are in.
- * This is so RSM resumes to the VOBU level and not just the CELL level.
- * This should be implemented with a new Public API call.
+ /* We need to update the vm state->blockN with which VOBU we are in.
+ * This is so RSM resumes to the VOBU level and not just the CELL level.
*/
- /* We cache one past the end of the VOBU,
- * in the hope it might catch the next NAV packet as well.
- * This reduces the amount of read commands sent to the DVD device.
- * A cache miss will only happen for 3 reasons.
- * 1) Seeking
- * 2) Menu change
- * 3) The next VOBU does not immeadiately follow the current one. E.g. Multi Angles, ILVU.
+ this->vm->state.blockN = this->vobu.vobu_start - this->position_current.cell_start;
+
+ dvdnav_get_vobu(this, &this->dsi, &this->pci, &this->vobu);
+ this->vobu.blockN = 0;
+ /* Give the cache a hint about the size of next VOBU.
+ * This improves pre-caching, because the VOBU will almost certainly be read entirely.
*/
dvdnav_pre_cache_blocks(this->cache, this->vobu.vobu_start+1, this->vobu.vobu_length+1);
/* Successfully got a NAV packet */
(*event) = DVDNAV_NAV_PACKET;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: NAV_PACKET\n");
+#endif
(*len) = 2048;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
@@ -836,52 +716,76 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *this, unsigned char **buf,
/* If we've got here, it must just be a normal block. */
if(!this->file) {
- printerr("Attempting to read without opening file");
+ printerr("Attempting to read without opening file.");
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
+ this->vobu.blockN++;
result = dvdnav_read_cache_block(this->cache, this->vobu.vobu_start + this->vobu.blockN, 1, buf);
if(result <= 0) {
printerr("Error reading from DVD.");
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
- this->vobu.blockN++;
- (*len) = 2048;
(*event) = DVDNAV_BLOCK_OK;
+ (*len) = 2048;
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
-uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *this, uint8_t stream) {
- audio_attr_t attr;
+dvdnav_status_t dvdnav_get_title_string(dvdnav_t *this, const char **title_str) {
+
+ if(!this || !title_str) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
+
+ (*title_str) = this->vm->dvd_name;
+ return S_OK;
+}
+
+uint8_t dvdnav_get_video_aspect(dvdnav_t *this) {
+ uint8_t retval;
if(!this)
return -1;
- pthread_mutex_lock(&this->vm_lock);
- attr = vm_get_audio_attr(this->vm, stream);
- pthread_mutex_unlock(&this->vm_lock);
+ pthread_mutex_lock(&this->vm_lock);
+ retval = (uint8_t)vm_get_video_aspect(this->vm);
+ pthread_mutex_unlock(&this->vm_lock);
- if(attr.lang_type != 1)
- return 0xffff;
+ return retval;
+}
+
+uint8_t dvdnav_get_video_scale_permission(dvdnav_t *this) {
+ uint8_t retval;
- return attr.lang_code;
+ if(!this)
+ return -1;
+
+ pthread_mutex_lock(&this->vm_lock);
+ retval = (uint8_t)vm_get_video_scale_permission(this->vm);
+ pthread_mutex_unlock(&this->vm_lock);
+
+ return retval;
}
-int8_t dvdnav_get_audio_logical_stream(dvdnav_t *this, uint8_t audio_num) {
- int8_t retval;
+uint16_t dvdnav_audio_stream_to_lang(dvdnav_t *this, uint8_t stream) {
+ audio_attr_t attr;
if(!this)
return -1;
pthread_mutex_lock(&this->vm_lock);
- retval = NCLK_dvdnav_get_audio_logical_stream(this, audio_num);
+ attr = vm_get_audio_attr(this->vm, stream);
pthread_mutex_unlock(&this->vm_lock);
-
- return retval;
+
+ if(attr.lang_type != 1)
+ return 0xffff;
+
+ return attr.lang_code;
}
uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *this, uint8_t stream) {
@@ -900,16 +804,54 @@ uint16_t dvdnav_spu_stream_to_lang(dvdnav_t *this, uint8_t stream) {
return attr.lang_code;
}
+int8_t dvdnav_get_audio_logical_stream(dvdnav_t *this, uint8_t audio_num) {
+ int8_t retval;
+
+ if(!this)
+ return -1;
+
+ pthread_mutex_lock(&this->vm_lock);
+ if (!this->vm->state.pgc) {
+ pthread_mutex_unlock(&this->vm_lock);
+ return -1;
+ }
+ retval = vm_get_audio_stream(this->vm, audio_num);
+ pthread_mutex_unlock(&this->vm_lock);
+
+ return retval;
+}
+
int8_t dvdnav_get_spu_logical_stream(dvdnav_t *this, uint8_t subp_num) {
int8_t retval;
if(!this)
return -1;
+ pthread_mutex_lock(&this->vm_lock);
+ if (!this->vm->state.pgc) {
+ pthread_mutex_unlock(&this->vm_lock);
+ return -1;
+ }
+ retval = vm_get_subp_stream(this->vm, subp_num, 0);
+ pthread_mutex_unlock(&this->vm_lock);
+
+ return retval;
+}
+
+int8_t dvdnav_get_active_audio_stream(dvdnav_t *this) {
+ int8_t retval;
+
+ if(!this)
+ return -1;
+
pthread_mutex_lock(&this->vm_lock);
- retval = NCLK_dvdnav_get_spu_logical_stream(this, subp_num);
+ if (!this->vm->state.pgc) {
+ pthread_mutex_unlock(&this->vm_lock);
+ return -1;
+ }
+ retval = vm_get_audio_active_stream(this->vm);
pthread_mutex_unlock(&this->vm_lock);
-
+
return retval;
}
@@ -920,98 +862,111 @@ int8_t dvdnav_get_active_spu_stream(dvdnav_t *this) {
return -1;
pthread_mutex_lock(&this->vm_lock);
- retval = NLCK_dvdnav_get_active_spu_stream(this);
+ if (!this->vm->state.pgc) {
+ pthread_mutex_unlock(&this->vm_lock);
+ return -1;
+ }
+ retval = vm_get_subp_active_stream(this->vm, 0);
pthread_mutex_unlock(&this->vm_lock);
return retval;
}
+static int8_t dvdnav_is_domain(dvdnav_t *this, domain_t domain) {
+ int8_t retval;
+
+ if (!this || !this->started)
+ return -1;
+
+ pthread_mutex_lock(&this->vm_lock);
+ retval = (this->vm->state.domain == domain);
+ pthread_mutex_unlock(&this->vm_lock);
+
+ return retval;
+}
+
/* First Play domain. (Menu) */
int8_t dvdnav_is_domain_fp(dvdnav_t *this) {
- return _dvdnav_is_domain(this, FP_DOMAIN);
+ return dvdnav_is_domain(this, FP_DOMAIN);
}
/* Video management Menu domain. (Menu) */
int8_t dvdnav_is_domain_vmgm(dvdnav_t *this) {
- return _dvdnav_is_domain(this, VMGM_DOMAIN);
+ return dvdnav_is_domain(this, VMGM_DOMAIN);
}
/* Video Title Menu domain (Menu) */
int8_t dvdnav_is_domain_vtsm(dvdnav_t *this) {
- return _dvdnav_is_domain(this, VTSM_DOMAIN);
+ return dvdnav_is_domain(this, VTSM_DOMAIN);
}
/* Video Title domain (playing movie). */
int8_t dvdnav_is_domain_vts(dvdnav_t *this) {
- return _dvdnav_is_domain(this, VTS_DOMAIN);
+ return dvdnav_is_domain(this, VTS_DOMAIN);
}
-/* Generally delegate angle information handling to
- * VM */
+/* Generally delegate angle information handling to VM */
dvdnav_status_t dvdnav_angle_change(dvdnav_t *this, int angle) {
int num, current;
if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
- if(dvdnav_get_angle_info(this, &current, &num) != S_OK) {
- printerr("Error getting angle info");
- return S_ERR;
- }
-
+ pthread_mutex_lock(&this->vm_lock);
+ vm_get_angle_info(this->vm, &current, &num);
/* Set angle SPRM if valid */
if((angle > 0) && (angle <= num)) {
this->vm->state.AGL_REG = angle;
} else {
- printerr("Passed an invalid angle number");
+ printerr("Passed an invalid angle number.");
+ pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
-/* FIXME: change order of current_angle, number_of_angles */
-dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *this, int* current_angle,
- int *number_of_angles) {
- if(!this || !this->vm) {
- return S_ERR;
- }
- if(!current_angle || !number_of_angles) {
- printerr("Passed a NULL pointer");
+dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *this, int *current_angle,
+ int *number_of_angles) {
+ if(!this || !current_angle || !number_of_angles) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
- vm_get_angle_info(this->vm, number_of_angles, current_angle);
+ pthread_mutex_lock(&this->vm_lock);
+ vm_get_angle_info(this->vm, current_angle, number_of_angles);
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
-dvdnav_status_t dvdnav_get_cell_info(dvdnav_t *this, int* current_angle,
- int *number_of_angles) {
- if(!this || !this->vm) {
- return S_ERR;
- }
- *current_angle=this->position_next.cell;
- return S_OK;
-}
-
pci_t* dvdnav_get_current_nav_pci(dvdnav_t *this) {
- if(!this || !this->vm) return 0;
+ if(!this) return 0;
return &this->pci;
}
dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *this) {
- if(!this || !this->vm) return 0;
+ if(!this) return 0;
return &this->dsi;
}
uint32_t dvdnav_get_next_still_flag(dvdnav_t *this) {
- if(!this || !this->vm) {
- return S_ERR;
- }
+ if(!this) return -1;
return this->position_next.still;
}
/*
* $Log: dvdnav.c,v $
+ * Revision 1.13 2003/02/20 16:01:58 mroi
+ * syncing to libdvdnav 0.1.5 and modifying input plugin accordingly
+ * quoting the ChangeLog:
+ * * some bugfixes
+ * * code cleanup
+ * * build process polishing
+ * * more sensible event order in get_next_block to ensure useful event delivery
+ * * VOBU level resume
+ * * fixed: seeking in a multiangle feature briefly showed the wrong angle
+ *
* Revision 1.12 2003/01/29 02:02:03 miguelfreitas
* avoid segfault
*
diff --git a/src/input/libdvdnav/dvdnav.h b/src/input/libdvdnav/dvdnav.h
index 2af610b26..c48245713 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.4 2002/09/20 12:53:53 mroi Exp $
+ * $Id: dvdnav.h,v 1.5 2003/02/20 16:01:59 mroi Exp $
*
*/
@@ -56,9 +56,6 @@ typedef int dvdnav_status_t;
#define DVDNAV_STATUS_ERR 0
#define DVDNAV_STATUS_OK 1
-/**
- * NOTE: */
-
/**
* \defgroup init Initialisation & housekeeping functions
* These functions allow you to open a DVD device and associate it
@@ -84,7 +81,7 @@ typedef int dvdnav_status_t;
* \param dest Pointer to a dvdnav_t pointer to fill in.
* \param path Any libdvdread acceptable path
*/
-dvdnav_status_t dvdnav_open(dvdnav_t** dest, char *path);
+dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path);
/**
* Closes a dvdnav_t previously opened with dvdnav_open(), freeing any
@@ -109,7 +106,7 @@ dvdnav_status_t dvdnav_reset(dvdnav_t *self);
* \param self Pointer to dvdnav_t associated with this operation.
* \param path Pointer to char* to fill in.
*/
-dvdnav_status_t dvdnav_path(dvdnav_t *self, char** path);
+dvdnav_status_t dvdnav_path(dvdnav_t *self, const char** path);
/**
* Returns a human-readable string describing the last error.
@@ -117,7 +114,7 @@ dvdnav_status_t dvdnav_path(dvdnav_t *self, char** path);
* \param self Pointer to dvdnav_t associated with this operation.
* \returns A pointer to said string.
*/
-char* dvdnav_err_to_string(dvdnav_t *self);
+const char* dvdnav_err_to_string(dvdnav_t *self);
/** \@} */
@@ -156,8 +153,7 @@ dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *self, int mask);
/**
* Specify whether read-ahead caching should be used. You may not want this if your
- * decoding engine does its own buffering or if you don't like the fact that this is
- * implemented in a multithreaded manner.
+ * decoding engine does its own buffering.
*
* \param self Pointer to dvdnav_t associated with this operation.
* \param use_readahead 0 - no, 1 - yes
@@ -214,7 +210,7 @@ dvdnav_status_t dvdnav_get_next_block(dvdnav_t *self, unsigned char *buf,
* I such a case (cache hit) this function will return a different pointer than
* the one handed in, pointing directly into the relevant block in the cache.
* Those pointer must _never_ be freed but instead returned to the library via
- + dvdnav_free_cache_block.
+ * dvdnav_free_cache_block().
*
* \param self Pointer to dvdnav_t associated with this operation.
* \param buf Buffer (at least 2048 octets) to fill with next block/event structure.
@@ -226,7 +222,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *self, unsigned char **buf,
int *event, int *len);
/**
- * All buffers which came from the internal cache (when dvdnav_get_next_cache_block
+ * All buffers which came from the internal cache (when dvdnav_get_next_cache_block()
* returned a buffer different from the one handed in) have to be freed with this
* function. Although handing in other buffers not from the cache doesn't cause any harm.
*
@@ -254,6 +250,17 @@ uint8_t dvdnav_get_video_aspect(dvdnav_t *self);
uint8_t dvdnav_get_video_scale_permission(dvdnav_t *self);
/**
+ * Return a string describing the title. This is an ID string encoded on the
+ * disc byt the author. In many cases this is a descriptive string such as
+ * `<tt>THE_MATRIX</tt>' but sometimes is sigularly uninformative such as
+ * `<tt>PDVD-011421</tt>'.
+ *
+ * \param self Pointer to dvdnav_t associated with this operation.
+ * \param title_str Pointer to C-style string to receive a string describing the title.
+ */
+dvdnav_status_t dvdnav_get_title_string(dvdnav_t *self, const char **title_str);
+
+/**
* @}
*/
@@ -290,6 +297,13 @@ dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *self, int title, int *parts
dvdnav_status_t dvdnav_still_skip(dvdnav_t *self);
/**
+ * Returns the still time status from the next cell
+ *
+ * \param self Pointer to dvdnav_t associated with this operation.
+ */
+uint32_t dvdnav_get_next_still_flag(dvdnav_t *self);
+
+/**
* Plays a specified title of the DVD.
*
* \param self Pointer to dvdnav_t associated with this operation.
@@ -298,8 +312,7 @@ dvdnav_status_t dvdnav_still_skip(dvdnav_t *self);
dvdnav_status_t dvdnav_title_play(dvdnav_t *self, int title);
/**
- * Plays the specifiec title, starting from the specified
- * part (chapter).
+ * Plays the specifiec title, starting from the specified part.
*
* \param self Pointer to dvdnav_t associated with this operation.
* \param title 1..99 -- Title number to play.
@@ -320,7 +333,7 @@ dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int title, int part);
* \param parts_to_play 1..999 -- Number of parts to play.
*/
dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *self, int title,
- int part, int parts_to_play);
+ int part, int parts_to_play);
/**
* Play the specified title starting from the specified time
@@ -333,7 +346,7 @@ dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *self, int title,
* \param time Timecode to start from (hours, minutes, seconds + frames).
*/
dvdnav_status_t dvdnav_time_play(dvdnav_t *self, int title,
- unsigned long int time);
+ unsigned long int time);
/**
* Stops playing the current title (causes a STOP action in
@@ -354,6 +367,27 @@ 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.
+ *
+ * \param self Pointer to dvdnav_t associated with this operation.
+ * \param menu Which menu to call (see DVDMenuID_t).
+ *
+ * \sa DVDMenuID_t (from <tt>libdvdread</tt>)
+ */
+dvdnav_status_t dvdnav_menu_call(dvdnav_t *self, DVDMenuID_t menu);
+
+/**
+ * Return the title number and part currently being played or
+ * -1 if in a menu.
+ *
+ * \param self Pointer to dvdnav_t associated with this operation.
+ * \param title Pointer to into which will receive the current title number.
+ * \param part Pointer to into which will receive the current part number.
+ */
+dvdnav_status_t dvdnav_current_title_info(dvdnav_t *self, int *title,
+ int *part);
+
+/**
* @}
*/
@@ -374,7 +408,7 @@ dvdnav_status_t dvdnav_go_up(dvdnav_t *self);
* \param time Timecode to start from.
*/
dvdnav_status_t dvdnav_time_search(dvdnav_t *self,
- unsigned long int time);
+ unsigned long int time);
/**
* Stop playing the current title and start playback of the title
@@ -385,7 +419,7 @@ dvdnav_status_t dvdnav_time_search(dvdnav_t *self,
* \param origin Start from here, start or end.
*/
dvdnav_status_t dvdnav_sector_search(dvdnav_t *self,
- unsigned long int offset, int origin);
+ unsigned long int offset, int origin);
/**
* Stop playing the current title and start playback of the title
@@ -421,38 +455,6 @@ dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *self);
dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *self);
/**
- * Stop playing the current title 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).
- *
- * \sa DVDMenuID_t (from <tt>libdvdread</tt>)
- */
-dvdnav_status_t dvdnav_menu_call(dvdnav_t *self, DVDMenuID_t menu);
-
-/**
- * Return the title number and chapter currently being played or
- * -1 if in a menu.
- *
- * \param self Pointer to dvdnav_t associated with this operation.
- * \param title Pointer to into which will receive the current title number.
- * \param part Pointer to into which will receive the current part number.
- */
-dvdnav_status_t dvdnav_current_title_info(dvdnav_t *self, int *title,
- int *part);
-
-/**
- * Return a string describing the title. This is an ID string encoded on the
- * disc byt the author. In many cases this is a descriptive string such as
- * `<tt>THE_MATRIX</tt>' but sometimes is sigularly uninformative such as
- * `<tt>PDVD-011421</tt>'.
- *
- * \param self Pointer to dvdnav_t associated with this operation.
- * \param title_str Pointer to C-style string to receive a string describing the title.
- */
-dvdnav_status_t dvdnav_get_title_string(dvdnav_t *self, char **title_str);
-
-/**
* Return the current position (in blocks) within the current
* part and the length (in blocks) of said part.
*
@@ -460,7 +462,7 @@ dvdnav_status_t dvdnav_get_title_string(dvdnav_t *self, char **title_str);
* \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.
*/
-dvdnav_status_t dvdnav_get_position(dvdnav_t *self, unsigned int* pos,
+dvdnav_status_t dvdnav_get_position(dvdnav_t *self, unsigned int *pos,
unsigned int *len);
/**
@@ -472,7 +474,7 @@ dvdnav_status_t dvdnav_get_position(dvdnav_t *self, unsigned int* pos,
* \param len Pointer to unsinged int to hold the length of the current title.
*/
dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *self,
- unsigned int* pos,
+ unsigned int *pos,
unsigned int *len);
/**
@@ -482,6 +484,14 @@ dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *self,
/**
* \defgroup highlight Highlights
*
+ * Most functions related to highlights take a NAV PCI packet as a parameter.
+ * While you can get the such a packet from libdvdnav, for players with internal
+ * FIFOs, this will result in errors, because due to the FIFO length, libdvdnav will
+ * be ahead in the stream compared to what the user is seeing on screen.
+ * Therefore, player applications who have a NAV packet available, which is
+ * better in sync with the actual playback should always pass this one to these
+ * functions.
+ *
* @{
*/
@@ -527,7 +537,7 @@ dsi_t* dvdnav_get_current_nav_dsi(dvdnav_t *self);
* \sa dvdnav_highlight_area_t
*/
dvdnav_status_t dvdnav_get_highlight_area(pci_t* nav_pci , int32_t button, int32_t mode,
- dvdnav_highlight_area_t* highlight);
+ dvdnav_highlight_area_t* highlight);
/**
* Move button highlight around as suggested by function name (e.g. with arrow keys).
@@ -535,18 +545,22 @@ dvdnav_status_t dvdnav_get_highlight_area(pci_t* nav_pci , int32_t button, int32
* \param self Pointer to dvdnav_t associated with this operation.
*/
dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *self, pci_t *pci);
+
/**
* Move button highlight around as suggested by function name (e.g. with arrow keys).
*
* \param self Pointer to dvdnav_t associated with this operation.
*/
+
dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *self, pci_t *pci);
+
/**
* Move button highlight around as suggested by function name (e.g. with arrow keys).
*
* \param self Pointer to dvdnav_t associated with this operation.
*/
dvdnav_status_t dvdnav_right_button_select(dvdnav_t *self, pci_t *pci);
+
/**
* Move button highlight around as suggested by function name (e.g. with arrow keys).
*
@@ -664,7 +678,7 @@ dvdnav_status_t dvdnav_spu_language_select(dvdnav_t *self,
* \param audio 0..7 -- Stream number.
*/
dvdnav_status_t dvdnav_physical_audio_stream_change(dvdnav_t *self,
- int audio);
+ int audio);
/**
* Set a specific logical audio stream.
@@ -673,7 +687,7 @@ dvdnav_status_t dvdnav_physical_audio_stream_change(dvdnav_t *self,
* \param audio 0..7 -- Stream number.
*/
dvdnav_status_t dvdnav_logical_audio_stream_change(dvdnav_t *self,
- int audio);
+ int audio);
/**
* Set the int pointed to to the current PHYSICAL audio
@@ -735,7 +749,7 @@ dvdnav_status_t dvdnav_get_physical_spu_stream(dvdnav_t *self,
* \param display Pointer which will receive value.
*/
dvdnav_status_t dvdnav_get_logical_spu_stream(dvdnav_t *self,
- int* stream, int* disply);
+ int* stream, int* disply);
/**
* Converts a *logical* audio stream id into country code
@@ -772,6 +786,13 @@ int8_t dvdnav_get_audio_logical_stream(dvdnav_t *self, uint8_t audio_num);
int8_t dvdnav_get_spu_logical_stream(dvdnav_t *self, uint8_t subp_num);
/**
+ * Get active audio stream.
+ *
+ * \param self Pointer to dvdnav_t associated with this operation.
+ */
+int8_t dvdnav_get_active_audio_stream(dvdnav_t *self);
+
+/**
* Get active spu stream.
*
* \param self Pointer to dvdnav_t associated with this operation.
@@ -815,20 +836,7 @@ dvdnav_status_t dvdnav_angle_change(dvdnav_t *self, int angle);
* \param number_of_angles Pointer to int which will get the number of angles.
*/
dvdnav_status_t dvdnav_get_angle_info(dvdnav_t *self, int* current_angle,
- int *number_of_angles);
-
-/**
- * FIXME: WTF does this do? -- High qulaity documentation huh?
- */
-dvdnav_status_t dvdnav_get_cell_info(dvdnav_t *self, int* current_angle,
- int *number_of_angles);
-
-/**
- * Returns the still time status from the next cell
- *
- * \param self Pointer to dvdnav_t associated with this operation.
- */
-uint32_t dvdnav_get_next_still_flag(dvdnav_t *self);
+ int *number_of_angles);
/**
* @}
@@ -849,18 +857,21 @@ uint32_t dvdnav_get_next_still_flag(dvdnav_t *self);
* \returns -1 on failure, 1 if condition is true, 0 if condition is false
*/
int8_t dvdnav_is_domain_fp(dvdnav_t *self);
+
/**
* Are we in the Video management Menu domain. (Menu)
* \param self Pointer to dvdnav_t associated with this operation.
* \returns -1 on failure, 1 if condition is true, 0 if condition is false
*/
int8_t dvdnav_is_domain_vmgm(dvdnav_t *self);
+
/**
* Are we in the Video Title Menu domain (Menu)
* \param self Pointer to dvdnav_t associated with this operation.
* \returns -1 on failure, 1 if condition is true, 0 if condition is false
*/
int8_t dvdnav_is_domain_vtsm(dvdnav_t *self);
+
/**
* Are we in the Video Title domain (playing movie)?
* \param self Pointer to dvdnav_t associated with this operation.
diff --git a/src/input/libdvdnav/dvdnav_events.h b/src/input/libdvdnav/dvdnav_events.h
index 79ff68979..a807bd5ea 100644
--- a/src/input/libdvdnav/dvdnav_events.h
+++ b/src/input/libdvdnav/dvdnav_events.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_events.h,v 1.3 2002/08/09 22:52:14 mroi Exp $
+ * $Id: dvdnav_events.h,v 1.4 2003/02/20 16:01:59 mroi Exp $
*
*/
@@ -35,21 +35,19 @@
/*** EVENTS ***/
-#define DVDNAV_BLOCK_OK 0 /*!< The next black was returned */
-#define DVDNAV_NOP 1 /*!< No action should be taken */
-#define DVDNAV_STILL_FRAME 2 /*!< The preceeding block was the last in a
- still frame. */
-#define DVDNAV_SPU_STREAM_CHANGE 3 /*!< The SPU stream was changed */
-#define DVDNAV_AUDIO_STREAM_CHANGE 4 /*!< The Audio stream was changed */
-#define DVDNAV_VTS_CHANGE 5 /*!< We have changed VTS */
-#define DVDNAV_CELL_CHANGE 6 /*!< We have jumped to a new cell */
-#define DVDNAV_NAV_PACKET 7 /*!< The packet just passed was the NAV packet */
-#define DVDNAV_STOP 8 /*!< The last block was final, no more are coming */
-#define DVDNAV_HIGHLIGHT 9 /*!< Change highlight region */
-#define DVDNAV_SPU_CLUT_CHANGE 10 /*!< SPU CLUT */
-#define DVDNAV_SEEK_DONE 11 /*!< Seek done, subtitles should be reset */
-#define DVDNAV_HOP_CHANNEL 12 /*!< Sent when non-seemless stream change has happed
- E.g. Menu button pressed causing change in menu */
+#define DVDNAV_BLOCK_OK 0 /*!< The next block was returned */
+#define DVDNAV_NOP 1 /*!< No action should be taken */
+#define DVDNAV_STILL_FRAME 2 /*!< The preceeding block was the last in a still frame */
+#define DVDNAV_SPU_STREAM_CHANGE 3 /*!< The SPU stream was changed */
+#define DVDNAV_AUDIO_STREAM_CHANGE 4 /*!< The Audio stream was changed */
+#define DVDNAV_VTS_CHANGE 5 /*!< We have changed VTS */
+#define DVDNAV_CELL_CHANGE 6 /*!< We have jumped to a new cell */
+#define DVDNAV_NAV_PACKET 7 /*!< The packet just passed was a NAV packet */
+#define DVDNAV_STOP 8 /*!< The last block was final, no more are coming */
+#define DVDNAV_HIGHLIGHT 9 /*!< Change highlight region */
+#define DVDNAV_SPU_CLUT_CHANGE 10 /*!< SPU CLUT changed */
+#define DVDNAV_HOP_CHANNEL 12 /*!< Sent when non-seemless stream change has happed */
+
/*** EVENT TYPES ***/
@@ -60,17 +58,17 @@ typedef struct {
int length; /*!<
The length (in seconds) the still frame
should be displayed for, or 0xff if
- indefinate. */
+ indefinite. */
} dvdnav_still_event_t;
/**
* Structure providing information on DVDNAV_SPU_STREAM_CHANGE events.
*/
typedef struct {
- int physical_wide; /*!< The physical (MPEG) stream number for widescreen display. */
+ int physical_wide; /*!< The physical (MPEG) stream number for widescreen display. */
int physical_letterbox; /*!< The physical (MPEG) stream number for letterboxed display. */
- int physical_pan_scan; /*!< The physical (MPEG) stream number for pan&scan display. */
- int logical; /*!< The logical (DVD) stream number. */
+ int physical_pan_scan; /*!< The physical (MPEG) stream number for pan&scan display. */
+ int logical; /*!< The logical (DVD) stream number. */
} dvdnav_spu_stream_change_event_t;
/**
@@ -85,18 +83,20 @@ typedef struct {
* Structure providing information on DVDNAV_VTS_CHANGE events.
*/
typedef struct {
- int old_vtsN; /*!< The old VTS number */
+ int old_vtsN; /*!< The old VTS number */
dvd_read_domain_t old_domain; /*!< The old domain */
- int new_vtsN; /*!< The new VTS number */
+ int new_vtsN; /*!< The new VTS number */
dvd_read_domain_t new_domain; /*!< The new domain */
} dvdnav_vts_change_event_t;
+/* FIXME: These are unused. */
+#if 0
/**
* Structure providing information on DVDNAV_CELL_CHANGE events.
*/
typedef struct {
cell_playback_t *old_cell; /*!< The old cell (or NULL if this is
- the first cell) */
+ the first cell) */
cell_playback_t *new_cell; /*!< The cell_playback_t for the new cell */
} dvdnav_cell_change_event_t;
@@ -107,15 +107,18 @@ typedef struct {
pci_t *pci;
dsi_t *dsi;
} dvdnav_nav_packet_event_t;
+#endif
/**
* Structure providing information on DVDNAV_HIGHLIGHT events.
+ * The event only fills in display and buttonN.
+ * The rest can be get with dvdnav_get_highlight_area().
*/
typedef struct {
- int display; /*!< 0 - hide, 1 - show, entries below only guaranteed useful
- if this is '1' */
- uint32_t palette; /*!< The CLUT entries for the highlight palette
- (4-bits per entry -> 4 entries) */
+ int display; /*!< 0 - hide, 1 - show, entries below only guaranteed useful
+ if this is '1' */
+ uint32_t palette; /*!< The CLUT entries for the highlight palette
+ (4-bits per entry -> 4 entries) */
uint16_t sx,sy,ex,ey; /*!< The start/end x,y positions */
uint32_t pts; /*!< Highlight PTS to match with SPU */
uint32_t buttonN; /*!< Button number for the SPU decoder. */
diff --git a/src/input/libdvdnav/dvdnav_internal.h b/src/input/libdvdnav/dvdnav_internal.h
index cca3a75fa..71b0dcf75 100644
--- a/src/input/libdvdnav/dvdnav_internal.h
+++ b/src/input/libdvdnav/dvdnav_internal.h
@@ -18,7 +18,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_internal.h,v 1.5 2002/10/24 15:04:41 jkeil Exp $
+ * $Id: dvdnav_internal.h,v 1.6 2003/02/20 16:01:59 mroi Exp $
*
*/
@@ -46,6 +46,12 @@
#include "ifo_types.h"
+/* Uncomment for VM command tracing */
+/* #define TRACE */
+
+/* where should libdvdnav write its messages (stdout/stderr) */
+#define MSG_OUT stdout
+
/* Maximum length of an error string */
#define MAX_ERR_LEN 255
@@ -53,16 +59,13 @@
#ifdef PATH_MAX
#define MAX_PATH_LEN PATH_MAX
#else
-#define MAX_PATH_LEN 255 /* Arbitary */
+#define MAX_PATH_LEN 255 /* Arbitrary */
#endif
#ifndef DVD_VIDEO_LB_LEN
#define DVD_VIDEO_LB_LEN 2048
#endif
-/* where should libdvdnav write its messages (stdout/stderr) */
-#define MSG_OUT stdout
-
typedef struct read_cache_s read_cache_t;
/*
@@ -113,20 +116,20 @@ typedef struct {
#endif
typedef struct dvdnav_vobu_s {
- int32_t vobu_start; /* Logical Absolute. MAX needed is 0x300000 */
- int32_t vobu_length; /* Relative offset */
- int32_t blockN; /* Relative offset */
- int32_t vobu_next; /* Relative offset */
+ int32_t vobu_start; /* Logical Absolute. MAX needed is 0x300000 */
+ int32_t vobu_length;
+ int32_t blockN; /* Relative offset */
+ int32_t vobu_next; /* Relative offset */
} dvdnav_vobu_t;
-/* The main DVDNAV type */
+/** The main DVDNAV type **/
struct dvdnav_s {
/* General data */
- char path[MAX_PATH_LEN]; /* Path to DVD device/dir */
+ char path[MAX_PATH_LEN]; /* Path to DVD device/dir */
dvd_file_t *file; /* Currently opened file */
- int open_vtsN; /* The domain and number of the... */
- int open_domain; /* ..currently opened VOB */
+ int open_vtsN; /* The domain and number of the... */
+ int open_domain; /* ..currently opened VOB */
/* Position data */
vm_position_t position_next;
@@ -138,20 +141,15 @@ struct dvdnav_s {
dsi_t dsi;
/* Flags */
- int skip_still; /* Set when skipping a still */
- int stop; /* Are we stopped? (note not paused, actually stopped) */
- int spu_clut_changed; /* The SPU CLUT changed */
- int started; /* vm_start has been called? */
- int use_read_ahead; /* 1 - use read-ahead cache, 0 - don't */
+ int skip_still; /* Set when skipping a still */
+ int spu_clut_changed; /* The SPU CLUT changed */
+ int started; /* vm_start has been called? */
+ int use_read_ahead; /* 1 - use read-ahead cache, 0 - don't */
+
/* VM */
- vm_t* vm;
+ vm_t *vm;
pthread_mutex_t vm_lock;
- /* Highlight */
- int hli_state; /* State of highlight: 0 - disabled,
- 1 - selected,
- 2 - activated */
-
/* Read-ahead cache */
read_cache_t *cache;
@@ -167,8 +165,8 @@ struct dvdnav_s {
#define printerrf(...) snprintf(this->err_str, MAX_ERR_LEN, __VA_ARGS__);
#endif
#define printerr(str) strncpy(this->err_str, str, MAX_ERR_LEN);
-/* Save my typing */
+/* Save my typing */
#define S_ERR DVDNAV_STATUS_ERR
#define S_OK DVDNAV_STATUS_OK
diff --git a/src/input/libdvdnav/highlight.c b/src/input/libdvdnav/highlight.c
index d0cfac713..f7000dfb5 100644
--- a/src/input/libdvdnav/highlight.c
+++ b/src/input/libdvdnav/highlight.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: highlight.c,v 1.6 2002/09/20 12:53:53 mroi Exp $
+ * $Id: highlight.c,v 1.7 2003/02/20 16:01:59 mroi Exp $
*
*/
@@ -25,23 +25,25 @@
#include "config.h"
#endif
-/*
-#define BUTTON_TESTING
-*/
#include <assert.h>
-#include <dvdnav.h>
#include "dvdnav_internal.h"
#include "vm.h"
#include "nav_types.h"
+/*
+#define BUTTON_TESTING
+*/
+
#ifdef BUTTON_TESTING
+
#include "nav_print.h"
#include "vmcmd.h"
static void print_time(dvd_time_t *dtime) {
const char *rate;
+
assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
@@ -69,18 +71,18 @@ static void print_time(dvd_time_t *dtime) {
static void nav_print_PCI_GI(pci_gi_t *pci_gi) {
int i;
- fprintf(MSG_OUT,"pci_gi:\n");
- fprintf(MSG_OUT,"nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn);
- fprintf(MSG_OUT,"vobu_cat 0x%04x\n", pci_gi->vobu_cat);
- fprintf(MSG_OUT,"vobu_uop_ctl 0x%08x\n", *(uint32_t*)&pci_gi->vobu_uop_ctl);
- fprintf(MSG_OUT,"vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm);
- fprintf(MSG_OUT,"vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm);
- fprintf(MSG_OUT,"vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm);
- fprintf(MSG_OUT,"e_eltm ");
+ fprintf(MSG_OUT,"libdvdnav: pci_gi:\n");
+ fprintf(MSG_OUT,"libdvdnav: nv_pck_lbn 0x%08x\n", pci_gi->nv_pck_lbn);
+ fprintf(MSG_OUT,"libdvdnav: vobu_cat 0x%04x\n", pci_gi->vobu_cat);
+ fprintf(MSG_OUT,"libdvdnav: vobu_uop_ctl 0x%08x\n", *(uint32_t*)&pci_gi->vobu_uop_ctl);
+ fprintf(MSG_OUT,"libdvdnav: vobu_s_ptm 0x%08x\n", pci_gi->vobu_s_ptm);
+ fprintf(MSG_OUT,"libdvdnav: vobu_e_ptm 0x%08x\n", pci_gi->vobu_e_ptm);
+ fprintf(MSG_OUT,"libdvdnav: vobu_se_e_ptm 0x%08x\n", pci_gi->vobu_se_e_ptm);
+ fprintf(MSG_OUT,"libdvdnav: e_eltm ");
print_time(&pci_gi->e_eltm);
fprintf(MSG_OUT,"\n");
- fprintf(MSG_OUT,"vobu_isrc \"");
+ fprintf(MSG_OUT,"libdvdnav: vobu_isrc \"");
for(i = 0; i < 32; i++) {
char c = pci_gi->vobu_isrc[i];
if((c >= ' ') && (c <= '~'))
@@ -99,10 +101,10 @@ static void nav_print_NSML_AGLI(nsml_agli_t *nsml_agli) {
if(j == 0)
return;
- fprintf(MSG_OUT,"nsml_agli:\n");
+ fprintf(MSG_OUT,"libdvdnav: nsml_agli:\n");
for(i = 0; i < 9; i++)
if(nsml_agli->nsml_agl_dsta[i])
- fprintf(MSG_OUT,"nsml_agl_c%d_dsta 0x%08x\n", i + 1,
+ fprintf(MSG_OUT,"libdvdnav: nsml_agl_c%d_dsta 0x%08x\n", i + 1,
nsml_agli->nsml_agl_dsta[i]);
}
@@ -111,24 +113,24 @@ static void nav_print_HL_GI(hl_gi_t *hl_gi, int *btngr_ns, int *btn_ns) {
if((hl_gi->hli_ss & 0x03) == 0)
return;
- fprintf(MSG_OUT,"hl_gi:\n");
- fprintf(MSG_OUT,"hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03);
- fprintf(MSG_OUT,"hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm);
- fprintf(MSG_OUT,"hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm);
- fprintf(MSG_OUT,"btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm);
+ fprintf(MSG_OUT,"libdvdnav: hl_gi:\n");
+ fprintf(MSG_OUT,"libdvdnav: hli_ss 0x%01x\n", hl_gi->hli_ss & 0x03);
+ fprintf(MSG_OUT,"libdvdnav: hli_s_ptm 0x%08x\n", hl_gi->hli_s_ptm);
+ fprintf(MSG_OUT,"libdvdnav: hli_e_ptm 0x%08x\n", hl_gi->hli_e_ptm);
+ fprintf(MSG_OUT,"libdvdnav: btn_se_e_ptm 0x%08x\n", hl_gi->btn_se_e_ptm);
*btngr_ns = hl_gi->btngr_ns;
- fprintf(MSG_OUT,"btngr_ns %d\n", hl_gi->btngr_ns);
- fprintf(MSG_OUT,"btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty);
- fprintf(MSG_OUT,"btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty);
- fprintf(MSG_OUT,"btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty);
+ fprintf(MSG_OUT,"libdvdnav: btngr_ns %d\n", hl_gi->btngr_ns);
+ fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 1, hl_gi->btngr1_dsp_ty);
+ fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 2, hl_gi->btngr2_dsp_ty);
+ fprintf(MSG_OUT,"libdvdnav: btngr%d_dsp_ty 0x%02x\n", 3, hl_gi->btngr3_dsp_ty);
- fprintf(MSG_OUT,"btn_ofn %d\n", hl_gi->btn_ofn);
+ fprintf(MSG_OUT,"libdvdnav: btn_ofn %d\n", hl_gi->btn_ofn);
*btn_ns = hl_gi->btn_ns;
- fprintf(MSG_OUT,"btn_ns %d\n", hl_gi->btn_ns);
- fprintf(MSG_OUT,"nsl_btn_ns %d\n", hl_gi->nsl_btn_ns);
- fprintf(MSG_OUT,"fosl_btnn %d\n", hl_gi->fosl_btnn);
- fprintf(MSG_OUT,"foac_btnn %d\n", hl_gi->foac_btnn);
+ fprintf(MSG_OUT,"libdvdnav: btn_ns %d\n", hl_gi->btn_ns);
+ fprintf(MSG_OUT,"libdvdnav: nsl_btn_ns %d\n", hl_gi->nsl_btn_ns);
+ fprintf(MSG_OUT,"libdvdnav: fosl_btnn %d\n", hl_gi->fosl_btnn);
+ fprintf(MSG_OUT,"libdvdnav: foac_btnn %d\n", hl_gi->foac_btnn);
}
static void nav_print_BTN_COLIT(btn_colit_t *btn_colit) {
@@ -140,10 +142,10 @@ static void nav_print_BTN_COLIT(btn_colit_t *btn_colit) {
if(j == 0)
return;
- fprintf(MSG_OUT,"btn_colit:\n");
+ fprintf(MSG_OUT,"libdvdnav: btn_colit:\n");
for(i = 0; i < 3; i++)
for(j = 0; j < 2; j++)
- fprintf(MSG_OUT,"btn_cqoli %d %s_coli: %08x\n",
+ fprintf(MSG_OUT,"libdvdnav: btn_cqoli %d %s_coli: %08x\n",
i, (j == 0) ? "sl" : "ac",
btn_colit->btn_coli[i][j]);
}
@@ -151,9 +153,9 @@ static void nav_print_BTN_COLIT(btn_colit_t *btn_colit) {
static void nav_print_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) {
int i, j, k;
- fprintf(MSG_OUT,"btnit:\n");
- fprintf(MSG_OUT,"btngr_ns: %i\n", btngr_ns);
- fprintf(MSG_OUT,"btn_ns: %i\n", btn_ns);
+ fprintf(MSG_OUT,"libdvdnav: btnit:\n");
+ fprintf(MSG_OUT,"libdvdnav: btngr_ns: %i\n", btngr_ns);
+ fprintf(MSG_OUT,"libdvdnav: btn_ns: %i\n", btn_ns);
if(btngr_ns == 0)
return;
@@ -163,22 +165,22 @@ static void nav_print_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) {
if(j < btn_ns) {
btni_t *btni = &btni_table[(36 / btngr_ns) * i + j];
- fprintf(MSG_OUT,"group %d btni %d: ", i+1, j+1);
+ fprintf(MSG_OUT,"libdvdnav: group %d btni %d: ", i+1, j+1);
fprintf(MSG_OUT,"btn_coln %d, auto_action_mode %d\n",
btni->btn_coln, btni->auto_action_mode);
- fprintf(MSG_OUT,"coords (%d, %d) .. (%d, %d)\n",
+ fprintf(MSG_OUT,"libdvdnav: coords (%d, %d) .. (%d, %d)\n",
btni->x_start, btni->y_start, btni->x_end, btni->y_end);
- fprintf(MSG_OUT,"up %d, ", btni->up);
+ fprintf(MSG_OUT,"libdvdnav: up %d, ", btni->up);
fprintf(MSG_OUT,"down %d, ", btni->down);
fprintf(MSG_OUT,"left %d, ", btni->left);
fprintf(MSG_OUT,"right %d\n", btni->right);
for(k = 0; k < 8; k++) {
- fprintf(MSG_OUT, "%02x ", btni->cmd.bytes[k]);
+ fprintf(MSG_OUT, "libdvdnav: %02x ", btni->cmd.bytes[k]);
}
fprintf(MSG_OUT, "| ");
vmPrint_mnemonic(&btni->cmd);
- fprintf(MSG_OUT, "\n\n");
+ fprintf(MSG_OUT, "\n");
}
}
}
@@ -187,29 +189,30 @@ static void nav_print_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns) {
static void nav_print_HLI(hli_t *hli) {
int btngr_ns = 0, btn_ns = 0;
- fprintf(MSG_OUT,"hli:\n");
+ fprintf(MSG_OUT,"libdvdnav: hli:\n");
nav_print_HL_GI(&hli->hl_gi, & btngr_ns, & btn_ns);
nav_print_BTN_COLIT(&hli->btn_colit);
nav_print_BTNIT(hli->btnit, btngr_ns, btn_ns);
}
void nav_print_PCI(pci_t *pci) {
- fprintf(MSG_OUT,"pci packet:\n");
+ fprintf(MSG_OUT,"libdvdnav: pci packet:\n");
nav_print_PCI_GI(&pci->pci_gi);
nav_print_NSML_AGLI(&pci->nsml_agli);
nav_print_HLI(&pci->hli);
}
-
#endif
-/* Highlighting API calls */
-
+/* Highlighting API calls */
-dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *this, int* button) {
- if(!this)
- return S_ERR;
+dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *this, int *button) {
+
+ if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
/* Simply return the appropriate value based on the SPRM */
(*button) = (this->vm->state.HL_BTNN_REG) >> 10;
@@ -217,7 +220,7 @@ dvdnav_status_t dvdnav_get_current_highlight(dvdnav_t *this, int* button) {
return S_OK;
}
-btni_t *__get_current_button(dvdnav_t *this, pci_t *pci) {
+static btni_t *get_current_button(dvdnav_t *this, pci_t *pci) {
int button = 0;
if(dvdnav_get_current_highlight(this, &button) != S_OK) {
@@ -231,36 +234,24 @@ btni_t *__get_current_button(dvdnav_t *this, pci_t *pci) {
return &(pci->hli.btnit[button-1]);
}
-dvdnav_status_t dvdnav_button_auto_action(dvdnav_t *this, pci_t *pci) {
- btni_t *button_ptr;
-
- if(!this)
- return S_ERR;
-
- if((button_ptr = __get_current_button(this, pci)) == NULL) {
- return S_ERR;
- }
- if (button_ptr->auto_action_mode == 1) {
- return S_OK;
- }
- return S_ERR;
+static dvdnav_status_t button_auto_action(dvdnav_t *this, pci_t *pci) {
+ if (get_current_button(this, pci)->auto_action_mode)
+ return dvdnav_button_activate(this, pci);
}
-
dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *this, pci_t *pci) {
btni_t *button_ptr;
- if(!this)
- return S_ERR;
-
- if((button_ptr = __get_current_button(this, pci)) == NULL) {
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
+ if(!(button_ptr = get_current_button(this, pci)))
+ return S_ERR;
+
dvdnav_button_select(this, pci, button_ptr->up);
- if (dvdnav_button_auto_action(this, pci) ) {
- dvdnav_button_activate(this, pci);
- }
+ button_auto_action(this, pci);
return S_OK;
}
@@ -268,17 +259,16 @@ dvdnav_status_t dvdnav_upper_button_select(dvdnav_t *this, pci_t *pci) {
dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *this, pci_t *pci) {
btni_t *button_ptr;
- if(!this)
- return S_ERR;
-
- if((button_ptr = __get_current_button(this, pci)) == NULL) {
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
+ if(!(button_ptr = get_current_button(this, pci)))
+ return S_ERR;
+
dvdnav_button_select(this, pci, button_ptr->down);
- if (dvdnav_button_auto_action(this, pci) ) {
- dvdnav_button_activate(this, pci);
- }
+ button_auto_action(this, pci);
return S_OK;
}
@@ -286,18 +276,16 @@ dvdnav_status_t dvdnav_lower_button_select(dvdnav_t *this, pci_t *pci) {
dvdnav_status_t dvdnav_right_button_select(dvdnav_t *this, pci_t *pci) {
btni_t *button_ptr;
- if(!this)
- return S_ERR;
-
- if((button_ptr = __get_current_button(this, pci)) == NULL) {
- printerr("Error fetching information on current button.");
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
+ if(!(button_ptr = get_current_button(this, pci)))
+ return S_ERR;
+
dvdnav_button_select(this, pci, button_ptr->right);
- if (dvdnav_button_auto_action(this, pci) ) {
- dvdnav_button_activate(this, pci);
- }
+ button_auto_action(this, pci);
return S_OK;
}
@@ -305,34 +293,31 @@ dvdnav_status_t dvdnav_right_button_select(dvdnav_t *this, pci_t *pci) {
dvdnav_status_t dvdnav_left_button_select(dvdnav_t *this, pci_t *pci) {
btni_t *button_ptr;
- if(!this)
- return S_ERR;
-
- if((button_ptr = __get_current_button(this, pci)) == NULL) {
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
+ if(!(button_ptr = get_current_button(this, pci)))
+ return S_ERR;
+
dvdnav_button_select(this, pci, button_ptr->left);
- if (dvdnav_button_auto_action(this, pci) ) {
- dvdnav_button_activate(this, pci);
- }
+ button_auto_action(this, pci);
return S_OK;
}
-dvdnav_status_t dvdnav_get_highlight_area(pci_t* nav_pci , int32_t button, int32_t mode,
- dvdnav_highlight_area_t* highlight) {
+dvdnav_status_t dvdnav_get_highlight_area(pci_t *nav_pci , int32_t button, int32_t mode,
+ dvdnav_highlight_area_t *highlight) {
btni_t *button_ptr;
+
#ifdef BUTTON_TESTING
fprintf(MSG_OUT, "libdvdnav: Button get_highlight_area %i\n", button);
#endif
- /* Set the highlight SPRM if the passed button was valid*/
- if((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns)) {
- fprintf(MSG_OUT, "libdvdnav: Unable to select button number %i as it doesn't exist\n",
- button);
+ if((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns))
return S_ERR;
- }
+
button_ptr = &nav_pci->hli.btnit[button-1];
highlight->sx = button_ptr->x_start;
@@ -347,7 +332,7 @@ dvdnav_status_t dvdnav_get_highlight_area(pci_t* nav_pci , int32_t button, int32
highlight->pts = nav_pci->hli.hl_gi.hli_s_ptm;
highlight->buttonN = button;
#ifdef BUTTON_TESTING
- fprintf(MSG_OUT, "libdvdnav: highlight.c:Highlight area is (%u,%u)-(%u,%u), display = %i, button = %u\n",
+ fprintf(MSG_OUT, "libdvdnav: highlight: Highlight area is (%u,%u)-(%u,%u), display = %i, button = %u\n",
button_ptr->x_start, button_ptr->y_start,
button_ptr->x_end, button_ptr->y_end,
1,
@@ -360,21 +345,20 @@ dvdnav_status_t dvdnav_get_highlight_area(pci_t* nav_pci , int32_t button, int32
dvdnav_status_t dvdnav_button_activate(dvdnav_t *this, pci_t *pci) {
int button;
btni_t *button_ptr = NULL;
-
- if(!this)
- return S_ERR;
+
+ if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
+
pthread_mutex_lock(&this->vm_lock);
- /* Precisely the same as selecting a button except we want
- * a different palette */
if(dvdnav_get_current_highlight(this, &button) != S_OK) {
- pthread_mutex_unlock(&this->vm_lock);
+ pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
-/* FIXME: dvdnav_button_select should really return a
- * special case for explicit NO-BUTTONS.
- */
- if(dvdnav_button_select(this, pci, button) != S_OK) {
+
+ if((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) {
/* Special code to handle still menus with no buttons.
* the navigation is expected to report to the appicatino that a STILL is
* underway. In turn, the application is supposed to report to the user
@@ -389,42 +373,46 @@ dvdnav_status_t dvdnav_button_activate(dvdnav_t *this, pci_t *pci) {
vm_get_next_cell(this->vm);
this->position_current.still = 0;
pthread_mutex_unlock(&this->vm_lock);
+ /* clear error message */
+ printerr("");
return S_OK;
}
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
- /* FIXME: The button command should really be passed in the API instead. */
- button_ptr = __get_current_button(this, pci);
- /* Finally, make the VM execute the appropriate code and
+
+ button_ptr = get_current_button(this, pci);
+ /* Finally, make the VM execute the appropriate code and probably
* scedule a jump */
#ifdef BUTTON_TESTING
fprintf(MSG_OUT, "libdvdnav: Evaluating Button Activation commands.\n");
#endif
- if(vm_eval_cmd(this->vm, &(button_ptr->cmd)) == 1) {
+ if(vm_exec_cmd(this->vm, &(button_ptr->cmd)) == 1) {
/* Command caused a jump */
this->vm->hop_channel++;
this->position_current.still = 0;
}
+
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *this, int32_t button, vm_cmd_t *cmd)
{
- if(!this || !this->vm)
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
- pthread_mutex_lock(&this->vm_lock);
- /* make the VM execute the appropriate code and
+ }
+
+ pthread_mutex_lock(&this->vm_lock);
+ /* make the VM execute the appropriate code and probably
* schedule a jump */
#ifdef BUTTON_TESTING
- fprintf(MSG_OUT, "libdvdnav:dvdnav_button_activate_cmd: Evaluating Button Activation commands.\n");
+ fprintf(MSG_OUT, "libdvdnav: dvdnav_button_activate_cmd: Evaluating Button Activation commands.\n");
#endif
if(button > 0) {
- printerrf("Select button number %i\n ",
- button);
this->vm->state.HL_BTNN_REG = (button << 10);
- if( (vm_eval_cmd(this->vm, cmd)) == 1) {
+ if(vm_exec_cmd(this->vm, cmd) == 1) {
/* Command caused a jump */
this->vm->hop_channel++;
}
@@ -438,26 +426,20 @@ dvdnav_status_t dvdnav_button_activate_cmd(dvdnav_t *this, int32_t button, vm_cm
dvdnav_status_t dvdnav_button_select(dvdnav_t *this, pci_t *pci, int button) {
if(!this) {
- printerrf("Unable to select button number %i as this state bad",
- button);
- return S_ERR;
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
}
#ifdef BUTTON_TESTING
fprintf(MSG_OUT, "libdvdnav: Button select %i\n", button);
#endif
- /* Set the highlight SPRM if the passed button was valid*/
- /* FIXME: this->pci should be provided by the application. */
if((button <= 0) || (button > pci->hli.hl_gi.btn_ns)) {
- printerrf("Unable to select button number %i as it doesn't exist",
- button);
+ printerr("Button does not exist.");
return S_ERR;
}
+
this->vm->state.HL_BTNN_REG = (button << 10);
-
- this->hli_state = 1; /* Selected */
-
this->position_current.button = -1; /* Force Highligh change */
return S_OK;
@@ -466,11 +448,8 @@ dvdnav_status_t dvdnav_button_select(dvdnav_t *this, pci_t *pci, int button) {
dvdnav_status_t dvdnav_button_select_and_activate(dvdnav_t *this, pci_t *pci,
int button) {
/* A trivial function */
- if(dvdnav_button_select(this, pci, button) != S_ERR) {
+ if(dvdnav_button_select(this, pci, button) != S_ERR)
return dvdnav_button_activate(this, pci);
- }
-
- /* Should never get here without an error */
return S_ERR;
}
@@ -479,55 +458,49 @@ dvdnav_status_t dvdnav_mouse_select(dvdnav_t *this, pci_t *pci, int x, int y) {
uint32_t best,dist;
int mx,my,dx,dy,d;
- /* FIXME: At the moment, the case of no button matchin (x,y) is
- * silently ignored, is this OK? */
- if(!this)
- return S_ERR;
-
- if(dvdnav_get_current_highlight(this, &cur_button) != S_OK) {
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
- best = 0;
+ if(dvdnav_get_current_highlight(this, &cur_button) != S_OK)
+ return S_ERR;
+
+ best = 0;
dist = 0x08000000; /* >> than (720*720)+(567*567); */
- /* Loop through each button */
- for(button=1; button <= pci->hli.hl_gi.btn_ns; button++) {
- btni_t *button_ptr = NULL;
- button_ptr = &(this->pci.hli.btnit[button-1]);
+ /* Loop through all buttons */
+ for(button = 1; button <= pci->hli.hl_gi.btn_ns; button++) {
+ btni_t *button_ptr = &(this->pci.hli.btnit[button-1]);
+
if((x >= button_ptr->x_start) && (x <= button_ptr->x_end) &&
(y >= button_ptr->y_start) && (y <= button_ptr->y_end)) {
mx = (button_ptr->x_start + button_ptr->x_end)/2;
- my = (button_ptr->y_start + button_ptr->y_end)/2;
+ my = (button_ptr->y_start + button_ptr->y_end)/2;
dx = mx - x;
dy = my - y;
d = (dx*dx) + (dy*dy);
/* If the mouse is within the button and the mouse is closer
* to the center of this button then it is the best choice. */
if(d < dist) {
- dist = d; best=button;
+ dist = d;
+ best = button;
}
}
}
-
- if (best!=0) {
- /* As an efficiency measure, only re-select the button
- * if it is different to the previously selected one. */
- if(best != cur_button) {
- dvdnav_button_select(this, pci, best);
- }
- }
-
- return S_OK;
+
+ /* As an efficiency measure, only re-select the button
+ * if it is different to the previously selected one. */
+ if (best != 0 && best != cur_button)
+ dvdnav_button_select(this, pci, best);
+
+ /* return S_OK only if we actually found a matching button */
+ return best ? S_OK : S_ERR;
}
dvdnav_status_t dvdnav_mouse_activate(dvdnav_t *this, pci_t *pci, int x, int y) {
/* A trivial function */
- if(dvdnav_mouse_select(this, pci, x,y) != S_ERR) {
+ if(dvdnav_mouse_select(this, pci, x,y) != S_ERR)
return dvdnav_button_activate(this, pci);
- }
-
- /* Should never get here without an error */
return S_ERR;
}
-
diff --git a/src/input/libdvdnav/navigation.c b/src/input/libdvdnav/navigation.c
index a3a26dd7d..28279c04a 100644
--- a/src/input/libdvdnav/navigation.c
+++ b/src/input/libdvdnav/navigation.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: navigation.c,v 1.3 2002/09/20 12:53:53 mroi Exp $
+ * $Id: navigation.c,v 1.4 2003/02/20 16:02:00 mroi Exp $
*
*/
@@ -25,7 +25,6 @@
#include "config.h"
#endif
-#include <dvdnav.h>
#include "dvdnav_internal.h"
#include "vm.h"
@@ -33,8 +32,10 @@
/* Navigation API calls */
dvdnav_status_t dvdnav_still_skip(dvdnav_t *this) {
- if(!this)
- return S_ERR;
+ if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
this->position_current.still = 0;
this->skip_still = 1;
@@ -43,11 +44,8 @@ dvdnav_status_t dvdnav_still_skip(dvdnav_t *this) {
}
dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *this, int *titles) {
- if(!this)
- return S_ERR;
-
- if(!titles) {
- printerr("Passed a NULL pointer");
+ if(!this || !titles) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
@@ -63,11 +61,8 @@ dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *this, int *titles) {
}
dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *this, int title, int *parts) {
- if(!this)
- return S_ERR;
-
- if(!parts) {
- printerr("Passed a NULL pointer");
+ if(!this || !parts) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
if(!this->started) {
@@ -75,81 +70,125 @@ dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *this, int title, int *parts
return S_ERR;
}
if ((title < 1) || (title > vm_get_vmgi(this->vm)->tt_srpt->nr_of_srpts) ) {
- printerr("Passed a title number out of range");
+ printerr("Passed a title number out of range.");
return S_ERR;
}
+
(*parts) = vm_get_vmgi(this->vm)->tt_srpt->title[title-1].nr_of_ptts;
+
return S_OK;
}
dvdnav_status_t dvdnav_current_title_info(dvdnav_t *this, int *title, int *part) {
- if(!this || !this->vm)
- return S_ERR;
-
- if(!title || !part) {
- printerr("Passed a NULL pointer");
+ int retval;
+
+ if(!this || !title || !part) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
-
- return vm_get_current_title_part(this->vm, title, part);
+
+ pthread_mutex_lock(&this->vm_lock);
+ if (!this->vm->vtsi || !this->vm->vmgi) {
+ printerr("Bad VM state.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ if (!this->vm->state.pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ if (this->vm->state.domain != VTS_DOMAIN) {
+ printerr("Not in VTS domain.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ retval = vm_get_current_title_part(this->vm, title, part);
+ pthread_mutex_unlock(&this->vm_lock);
+
+ return retval ? S_OK : S_ERR;
}
dvdnav_status_t dvdnav_title_play(dvdnav_t *this, int title) {
-
if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
}
-
return dvdnav_part_play(this, title, 1);
}
dvdnav_status_t dvdnav_part_play(dvdnav_t *this, int title, int part) {
+ int retval;
if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
+
+ pthread_mutex_lock(&this->vm_lock);
+ if (!this->vm->vtsi || !this->vm->vmgi) {
+ printerr("Bad VM state.");
+ pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
+ if (!this->vm->state.pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ if((title < 1) || (title > this->vm->vmgi->tt_srpt->nr_of_srpts)) {
+ printerr("Title out of range.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ retval = vm_jump_title_part(this->vm, title, part);
+ pthread_mutex_unlock(&this->vm_lock);
- return vm_jump_title_part(this->vm, title, part);
+ return retval ? S_OK : S_ERR;
}
dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *this, int title,
- int part, int parts_to_play) {
- /* Perform jump as per usual */
-
- return dvdnav_part_play(this, title, part);
-
- /* FIXME: Impement auto-stop */
-
- /* return S_OK;*/
+ int part, int parts_to_play) {
+ /* FIXME: Implement auto-stop */
+ if (dvdnav_part_play(this, title, part) == S_OK)
+ printerr("Not implemented yet.");
+ return S_ERR;
}
dvdnav_status_t dvdnav_time_play(dvdnav_t *this, int title,
- unsigned long int time) {
- /* FIXME: Implement */
+ unsigned long int time) {
+ if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
- return S_OK;
+ /* FIXME: Implement */
+ printerr("Not implemented yet.");
+ return S_ERR;
}
dvdnav_status_t dvdnav_stop(dvdnav_t *this) {
- if(!this)
- return S_ERR;
-
- /* Set the STOP flag */
-
- this->stop = 1;
+ if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
+ pthread_mutex_lock(&this->vm_lock);
+ vm_stop(this->vm);
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
dvdnav_status_t dvdnav_go_up(dvdnav_t *this) {
- if(!this)
- return S_ERR;
+ if(!this) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
/* A nice easy function... delegate to the VM */
- vm_go_up(this->vm);
+ pthread_mutex_lock(&this->vm_lock);
+ vm_jump_up(this->vm);
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
-
-
-
diff --git a/src/input/libdvdnav/read_cache.c b/src/input/libdvdnav/read_cache.c
index 751560206..f14d826ce 100644
--- a/src/input/libdvdnav/read_cache.c
+++ b/src/input/libdvdnav/read_cache.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: read_cache.c,v 1.6 2003/02/11 15:12:42 mroi Exp $
+ * $Id: read_cache.c,v 1.7 2003/02/20 16:02:00 mroi Exp $
*
*/
@@ -284,7 +284,7 @@ void dvdnav_pre_cache_blocks(read_cache_t *self, int sector, size_t block_count)
pthread_mutex_unlock(&self->cache_lock);
}
-/* This function will do the cache read once implemented */
+/* This function will do the cache read */
int dvdnav_read_cache_block( read_cache_t *self, int sector, size_t block_count, uint8_t **buf) {
int result, diff;
diff --git a/src/input/libdvdnav/remap.c b/src/input/libdvdnav/remap.c
index ca30287c6..154025528 100644
--- a/src/input/libdvdnav/remap.c
+++ b/src/input/libdvdnav/remap.c
@@ -1,3 +1,23 @@
+/*
+ * This file is part of libdvdnav, a DVD navigation library.
+ *
+ * libdvdnav 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.
+ *
+ * libdvdnav 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: remap.c,v 1.2 2003/02/20 16:02:00 mroi Exp $
+ */
+
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -5,6 +25,7 @@
#include <sys/fcntl.h>
#include <assert.h>
#include "remap.h"
+#include "dvdnav_internal.h"
struct block_s {
int domain;
@@ -164,15 +185,14 @@ remap_t* remap_loadmap( char *title) {
/* Build the map filename */
home = getenv("HOME"); assert(home);
strncpy(fname, home, sizeof(fname));
- strncat(fname, "/.xine/", sizeof(fname));
+ strncat(fname, "/.dvdnav/", sizeof(fname));
strncat(fname, title, sizeof(fname));
strncat(fname, ".map", sizeof(fname));
- printf("Loading %s.\n", fname);
/* Open the map file */
fp = fopen( fname, "r");
if (!fp) {
- printf("Unable to find map file '%s'\n", fname);
+ fprintf(MSG_OUT, "libdvdnav: Unable to find map file '%s'\n", fname);
return NULL;
}
@@ -186,7 +206,7 @@ remap_t* remap_loadmap( char *title) {
res = parseblock( buf,
&tmp.domain, &tmp.title, &tmp.program, &tmp.start_block, &tmp.end_block);
if (res != 5) {
- printf("Ignoring map line (%d): %s\n", res, buf);
+ fprintf(MSG_OUT, "libdvdnav: Ignoring map line (%d): %s\n", res, buf);
continue;
}
remap_add_node( map, tmp);
@@ -205,7 +225,7 @@ unsigned long remap_block(
block_t *b;
if (map->debug) {
- printf("%s: domain %d, title %d, program %d, start %lx, next %lx\n",
+ fprintf(MSG_OUT, "libdvdnav: %s: domain %d, title %d, program %d, start %lx, next %lx\n",
map->title, domain, title, program, cblock, cblock+offset);
}
@@ -217,7 +237,7 @@ unsigned long remap_block(
if (b) {
if (map->debug) {
- printf("Redirected to %lx\n", b->end_block);
+ fprintf(MSG_OUT, "libdvdnav: Redirected to %lx\n", b->end_block);
}
return b->end_block - cblock;
}
diff --git a/src/input/libdvdnav/remap.h b/src/input/libdvdnav/remap.h
index 841a24a51..5440843c8 100644
--- a/src/input/libdvdnav/remap.h
+++ b/src/input/libdvdnav/remap.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of libdvdnav, a DVD navigation library.
+ *
+ * libdvdnav 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.
+ *
+ * libdvdnav 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id: remap.h,v 1.2 2003/02/20 16:02:00 mroi Exp $
+ */
+
#ifndef __REMAP__H
#define __REMAP__H
typedef struct block_s block_t;
diff --git a/src/input/libdvdnav/searching.c b/src/input/libdvdnav/searching.c
index 77fc7394d..4cdb2348b 100644
--- a/src/input/libdvdnav/searching.c
+++ b/src/input/libdvdnav/searching.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: searching.c,v 1.7 2003/01/13 13:53:33 mroi Exp $
+ * $Id: searching.c,v 1.8 2003/02/20 16:02:00 mroi Exp $
*
*/
@@ -25,46 +25,52 @@
#include "config.h"
#endif
-#include "dvdnav.h"
+#include <assert.h>
+
#include "dvdnav_internal.h"
#include "vm.h"
#include "nav_types.h"
+/*
+#define LOG_DEBUG
+*/
+
/* Searching API calls */
dvdnav_status_t dvdnav_time_search(dvdnav_t *this,
unsigned long int time) {
-/* Time search the current PGC based on the xxx table */
+ /* FIXME: Time search the current PGC based on the xxx table */
return S_OK;
}
/* Scan the ADMAP for a particular block number. */
/* Return placed in vobu. */
/* Returns error status */
-
-dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, int32_t seekto_block, int32_t *vobu) {
- /* FIXME:Need to handle seeking outside current cell. */
+/* FIXME: Maybe need to handle seeking outside current cell. */
+static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, int32_t seekto_block, int32_t *vobu) {
vobu_admap_t *admap = NULL;
+
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block);
+#endif
*vobu = -1;
- fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n",
- seekto_block);
/* Search through the VOBU_ADMAP for the nearest VOBU
* to the target block */
switch(domain) {
- case FP_DOMAIN:
- case VMGM_DOMAIN:
- admap = this->vm->vmgi->menu_vobu_admap;
- break;
- case VTSM_DOMAIN:
- admap = this->vm->vtsi->menu_vobu_admap;
- break;
- case VTS_DOMAIN:
- admap = this->vm->vtsi->vts_vobu_admap;
- break;
- default:
- fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking seek.\n");
+ case FP_DOMAIN:
+ case VMGM_DOMAIN:
+ admap = this->vm->vmgi->menu_vobu_admap;
+ break;
+ case VTSM_DOMAIN:
+ admap = this->vm->vtsi->menu_vobu_admap;
+ break;
+ case VTS_DOMAIN:
+ admap = this->vm->vtsi->vts_vobu_admap;
+ break;
+ default:
+ fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n");
}
if(admap) {
int32_t address = 0;
@@ -85,7 +91,6 @@ dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, int32_t seekto
} else {
vobu_start = next_vobu;
}
-
address ++;
}
if(found) {
@@ -101,65 +106,67 @@ dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, int32_t seekto
}
dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
- unsigned long int offset, int origin) {
-/* FIXME: Implement */
-
+ unsigned long int offset, int origin) {
uint32_t target = 0;
uint32_t length = 0;
- uint32_t first_cell_nr, last_cell_nr, cell_nr, fnd_cell_nr;
+ uint32_t first_cell_nr, last_cell_nr, cell_nr;
int found;
- cell_playback_t *cell, *fnd_cell;
+ cell_playback_t *cell;
dvd_state_t *state;
dvdnav_status_t result;
- if((!this) || (!this->vm) || (!this->started))
- return -1;
+ if(this->position_current.still != 0) {
+ printerr("Cannot seek in a still frame.");
+ return S_ERR;
+ }
- state = &(this->vm->state);
- if((!state) || (!state->pgc) )
- return -1;
-
- if(this->position_current.still != 0)
- /* Cannot do seeking in a still frame. */
- return -1;
-
- pthread_mutex_lock(&this->vm_lock);
result = dvdnav_get_position(this, &target, &length);
- fprintf(MSG_OUT, "libdvdnav: FIXME: seeking to offset=%lu pos=%u length=%u\n", offset, target, length);
- fprintf(MSG_OUT, "libdvdnav: FIXME: Before cellN=%u blockN=%u\n" ,
- state->cellN,
- state->blockN);
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lu pos=%u length=%u\n", offset, target, length);
+ fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN);
+#endif
if(!result) {
- pthread_mutex_unlock(&this->vm_lock);
- return -1;
+ return S_ERR;
}
+ pthread_mutex_lock(&this->vm_lock);
+ state = &(this->vm->state);
+ if(!state->pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+
switch(origin) {
case SEEK_SET:
if(offset > length) {
+ printerr("Request to seek behind end.");
pthread_mutex_unlock(&this->vm_lock);
- return -1;
+ return S_ERR;
}
target = offset;
break;
case SEEK_CUR:
if(target + offset > length) {
+ printerr("Request to seek behind end.");
pthread_mutex_unlock(&this->vm_lock);
- return -1;
+ return S_ERR;
}
target += offset;
break;
case SEEK_END:
if(length - offset < 0) {
+ printerr("Request to seek before start.");
pthread_mutex_unlock(&this->vm_lock);
- return -1;
+ return S_ERR;
}
target = length - offset;
break;
default:
/* Error occured */
+ printerr("Illegal seek mode.");
pthread_mutex_unlock(&this->vm_lock);
- return -1;
+ return S_ERR;
}
/* First find closest cell number in program */
@@ -170,83 +177,89 @@ dvdnav_status_t dvdnav_sector_search(dvdnav_t *this,
last_cell_nr = state->pgc->nr_of_cells;
}
- found = 0; target += state->pgc->cell_playback[first_cell_nr-1].first_sector;
- fnd_cell_nr = last_cell_nr + 1;
+ 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)) {
+ found = 1;
state->cellN = cell_nr;
state->blockN = 0;
- state->cell_restart++;
- found = 1;
- fnd_cell_nr = cell_nr;
- fnd_cell = cell;
+ state->cell_restart++;
}
}
- if(fnd_cell_nr <= last_cell_nr) {
+ if(found) {
int32_t vobu, start;
- dvdnav_status_t status;
+#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n",
- fnd_cell_nr, first_cell_nr, last_cell_nr);
- status = dvdnav_scan_admap(this, state->domain, target, &vobu);
- /*
- * Clut does not actually change,
- * but as the decoders have been closed then opened,
- * A new clut has to be sent.
- */
- start =(state->pgc->cell_playback[state->cellN - 1].first_sector);
- fprintf(MSG_OUT, "libdvdnav: FIXME: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" ,
+ state->cellN, 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;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" ,
state->cellN,
state->blockN,
target,
vobu,
start);
- state->blockN = vobu - start;
- fprintf(MSG_OUT, "libdvdnav: FIXME: After vobu=%x start=%x blockN=%x\n" ,
+#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 target;
- } else {
- fprintf(MSG_OUT, "libdvdnav: Error when seeking, asked to seek outside program\n");
+ return S_OK;
}
-
+
+ fprintf(MSG_OUT, "libdvdnav: Error when seeking, asked to seek outside program\n");
fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target);
-
+ printerr("Error when seeking.");
pthread_mutex_unlock(&this->vm_lock);
- return -1;
+ return S_ERR;
}
dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int part) {
-
- if((!this) || (!this->vm) )
- return S_ERR;
-
- return S_OK;
+ int title, old_part;
+
+ if (dvdnav_current_title_info(this, &title, &old_part) == S_OK)
+ return dvdnav_part_play(this, title, part);
+ return S_ERR;
}
dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) {
- dvd_state_t *state;
- if((!this) || (!this->vm) )
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
-
- state = &(this->vm->state);
- if((!state) || (!state->pgc) )
+ }
+
+ pthread_mutex_lock(&this->vm_lock);
+ if(!this->vm->state.pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
+ }
- pthread_mutex_lock(&this->vm_lock);
+#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: previous chapter\n");
- if (!vm_prev_pg(this->vm)) {
- fprintf(MSG_OUT, "libdvdnav: prev chapter failed.\n");
+#endif
+ if (!vm_jump_prev_pg(this->vm)) {
+ fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n");
+ printerr("Skip to previous chapter failed.");
pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
this->position_current.still = 0;
this->vm->hop_channel++;
+#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: previous chapter done\n");
+#endif
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
@@ -254,70 +267,96 @@ dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) {
dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) {
- if((!this) || (!this->vm) )
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
+ }
- fprintf(MSG_OUT, "libdvdnav: top chapter. NOP.\n");
-
+ pthread_mutex_lock(&this->vm_lock);
+ if(!this->vm->state.pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: top chapter\n");
+#endif
+ if (!vm_jump_top_pg(this->vm)) {
+ fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n");
+ printerr("Skip to top chapter failed.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+ this->position_current.still = 0;
+ this->vm->hop_channel++;
+#ifdef LOG_DEBUG
+ fprintf(MSG_OUT, "libdvdnav: top chapter done\n");
+#endif
+ pthread_mutex_unlock(&this->vm_lock);
+
return S_OK;
}
dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) {
- dvd_state_t *state;
- if((!this) || (!this->vm) )
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
+ }
- state = &(this->vm->state);
- if((!state) || (!state->pgc) )
+ pthread_mutex_lock(&this->vm_lock);
+ if(!this->vm->state.pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
+ }
- pthread_mutex_lock(&this->vm_lock);
+#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: next chapter\n");
- if (!vm_next_pg(this->vm)) {
+#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;
}
this->position_current.still = 0;
this->vm->hop_channel++;
+#ifdef LOG_DEBUG
fprintf(MSG_OUT, "libdvdnav: next chapter done\n");
+#endif
pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) {
- dvd_state_t *state;
-
- if((!this) || (!this->vm) )
+
+ if(!this) {
+ printerr("Passed a NULL pointer.");
return S_ERR;
+ }
- pthread_mutex_lock(&this->vm_lock);
- state = &(this->vm->state);
- if (vm_menu_call(this->vm, menu, 0))
+ pthread_mutex_lock(&this->vm_lock);
+ if(!this->vm->state.pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
+ }
+
+ if (vm_jump_menu(this->vm, menu)) {
this->vm->hop_channel++;
- pthread_mutex_unlock(&this->vm_lock);
- return S_OK;
-}
-
-static char __title_str[] = "DVDNAV";
-
-dvdnav_status_t dvdnav_get_title_string(dvdnav_t *this, char **title_str) {
- if(!this)
- return S_ERR;
-
- if(!title_str) {
- printerr("Passed a NULL pointer");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_OK;
+ } else {
+ printerr("No such menu.");
+ pthread_mutex_unlock(&this->vm_lock);
return S_ERR;
}
-
- (*title_str) = __title_str;
-
- return S_OK;
}
-dvdnav_status_t dvdnav_get_position(dvdnav_t *this, unsigned int* pos,
+dvdnav_status_t dvdnav_get_position(dvdnav_t *this, unsigned int *pos,
unsigned int *len) {
uint32_t cur_sector;
uint32_t first_cell_nr;
@@ -325,24 +364,32 @@ dvdnav_status_t dvdnav_get_position(dvdnav_t *this, unsigned int* pos,
cell_playback_t *first_cell;
cell_playback_t *last_cell;
dvd_state_t *state;
- if((!this) || (!this->vm) )
- return 0;
-
+
+ if(!this || !pos || !len) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
+ if(!this->started) {
+ printerr("Virtual DVD machine not started.");
+ return S_ERR;
+ }
+
+ pthread_mutex_lock(&this->vm_lock);
state = &(this->vm->state);
- if((!state) || (!state->pgc) )
- return 0;
-
- /* Sanity check */
- if(state->pgN > state->pgc->nr_of_programs) {
- return 0;
+ if(!state->pgc) {
+ printerr("No current PGC.");
+ pthread_mutex_unlock(&this->vm_lock);
+ return S_ERR;
}
-
+
/* Get current sector */
cur_sector = this->vobu.vobu_start + this->vobu.blockN;
/* Find start cell of program. */
first_cell_nr = state->pgc->program_map[state->pgN-1];
first_cell = &(state->pgc->cell_playback[first_cell_nr-1]);
+
+ /* Find end cell of program */
if(state->pgN < state->pgc->nr_of_programs) {
last_cell_nr = state->pgc->program_map[state->pgN] - 1;
} else {
@@ -352,8 +399,7 @@ dvdnav_status_t dvdnav_get_position(dvdnav_t *this, unsigned int* pos,
*pos= cur_sector - first_cell->first_sector;
*len= last_cell->last_sector - first_cell->first_sector;
- /* fprintf(MSG_OUT, "libdvdnav: searching:current pos=%u length=%u\n",*pos,*len); */
-
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
@@ -367,18 +413,18 @@ dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this,
cell_playback_t *first_cell;
cell_playback_t *last_cell;
dvd_state_t *state;
- if((!this) || (!this->vm) )
- return S_ERR;
-
+
+ if(!this || !pos || !len) {
+ printerr("Passed a NULL pointer.");
+ return S_ERR;
+ }
+
state = &(this->vm->state);
- if((!state) || (!state->pgc) )
- return S_ERR;
-
- /* Sanity check */
- if(state->pgN > state->pgc->nr_of_programs) {
+ if(!state->pgc) {
+ printerr("No current PGC.");
return S_ERR;
}
-
+
/* Get current sector */
cur_sector = this->vobu.vobu_start + this->vobu.blockN;
@@ -393,5 +439,3 @@ dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this,
return S_OK;
}
-
-
diff --git a/src/input/libdvdnav/settings.c b/src/input/libdvdnav/settings.c
index c74eda500..bc5cc9e70 100644
--- a/src/input/libdvdnav/settings.c
+++ b/src/input/libdvdnav/settings.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: settings.c,v 1.2 2002/09/20 12:53:53 mroi Exp $
+ * $Id: settings.c,v 1.3 2003/02/20 16:02:01 mroi Exp $
*
*/
@@ -25,7 +25,6 @@
#include "config.h"
#endif
-#include <dvdnav.h>
#include "dvdnav_internal.h"
#include "vm.h"
@@ -33,57 +32,40 @@
/* Characteristics/setting API calls */
dvdnav_status_t dvdnav_get_region_mask(dvdnav_t *this, int *region) {
- if(!this) {
- printerr("Passed a NULL this pointer");
- return S_ERR;
- }
-
- if(!region) {
- printerr("Passed a NULL region pointer");
- return S_ERR;
- }
-
- if(!this->vm) {
- printerr("VM not yet initialised");
+ if(!this || !region) {
+ printerr("Passed a NULL this pointer.");
return S_ERR;
}
(*region) = this->vm->state.registers.SPRM[20];
-
return S_OK;
}
dvdnav_status_t dvdnav_set_region_mask(dvdnav_t *this, int mask) {
- if(!this)
- return S_ERR;
-
- if(!this->vm) {
- printerr("VM not yet initialised");
+ if(!this) {
+ printerr("Passed a NULL this pointer.");
return S_ERR;
}
+ pthread_mutex_lock(&this->vm_lock);
this->vm->state.registers.SPRM[20] = (mask & 0xff);
-
+ pthread_mutex_unlock(&this->vm_lock);
return S_OK;
}
dvdnav_status_t dvdnav_set_readahead_flag(dvdnav_t *this, int use_readahead) {
- if(!this)
- return S_ERR;
+ if(!this) {
+ printerr("Passed a NULL this pointer.");
+ return S_ERR;
+ }
this->use_read_ahead = use_readahead;
-
return S_OK;
}
-dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *this, int* flag) {
- if(!this) {
- printerr("Passed a NULL this pointer");
- return S_ERR;
- }
-
- if(!flag) {
- printerr("Passed a NULL flag pointer");
+dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *this, int *flag) {
+ if(!this || !flag) {
+ printerr("Passed a NULL this pointer.");
return S_ERR;
}
@@ -92,23 +74,13 @@ dvdnav_status_t dvdnav_get_readahead_flag(dvdnav_t *this, int* flag) {
}
static dvdnav_status_t set_language_register(dvdnav_t *this, char *code, int reg) {
- if(!this ) {
- printerr("Passed a NULL this pointer");
+ if(!this || !code) {
+ printerr("Passed a NULL this pointer.");
return S_ERR;
}
- if(!code) {
- printerr("Passed a NULL code pointer");
- return S_ERR;
- }
-
if(!code[0] || !code[1]) {
- printerr("Passed illegal language code");
- return S_ERR;
- }
-
- if(!this->vm) {
- printerr("VM not yet initialised");
+ printerr("Passed illegal language code.");
return S_ERR;
}
diff --git a/src/input/libdvdnav/vm.c b/src/input/libdvdnav/vm.c
index c39737773..740928be0 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.12 2003/02/11 16:28:47 heikos Exp $
+ * $Id: vm.c,v 1.13 2003/02/20 16:02:01 mroi Exp $
*
*/
@@ -45,52 +45,50 @@
#include "vm.h"
#include "dvdnav_internal.h"
-
+/*
#define STRICT
-
+*/
/* Local prototypes */
-static void saveRSMinfo(vm_t *vm,int cellN, int blockN);
+/* get_XYZ returns a value.
+ * set_XYZ sets state using passed parameters.
+ * returns success/failure.
+ */
+
+/* Play */
static link_t play_PGC(vm_t *vm);
static link_t play_PGC_PG(vm_t *vm, int pgN);
static link_t play_PGC_post(vm_t *vm);
static link_t play_PG(vm_t *vm);
static link_t play_Cell(vm_t *vm);
static link_t play_Cell_post(vm_t *vm);
-static link_t process_command(vm_t *vm,link_t link_values);
-
-static void ifoOpenNewVTSI(vm_t *vm,dvd_reader_t *dvd, int vtsN);
-static pgcit_t* get_PGCIT(vm_t *vm);
-
-/* get_XYZ returns a value.
- * ser_XYZ sets state using passed parameters.
- * returns success/failure.
- */
-/* Can only be called when in VTS_DOMAIN */
-static int set_FP_PGC(vm_t *vm); /* FP */
-static int set_TT(vm_t *vm,int tt);
-static int set_VTS_TT(vm_t *vm,int vtsN, int vts_ttn);
-static int set_VTS_PTT(vm_t *vm,int vtsN, int vts_ttn, int part);
+/* Process link - returns 1 if a hop has been performed */
+static int process_command(vm_t *vm,link_t link_values);
-static int set_MENU(vm_t *vm,int menu); /* VTSM & VMGM */
+/* Set */
+static int set_TT(vm_t *vm, int tt);
+static int set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn);
+static int set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part);
+static int set_FP_PGC(vm_t *vm);
+static int set_MENU(vm_t *vm, int menu);
+static int set_PGCN(vm_t *vm, int pgcN);
+static int set_PGN(vm_t *vm); /* Set PGN based on (vm->state).CellN */
+static void set_RSMinfo(vm_t *vm, int cellN, int blockN);
-/* Called in any domain */
+/* Get */
static int get_TT(vm_t *vm, int vtsN, int vts_ttn);
-static int get_ID(vm_t *vm,int id);
+static int get_ID(vm_t *vm, int id);
static int get_PGCN(vm_t *vm);
-static int set_PGN(vm_t *vm); /* Set PGN based on (vm->state).CellN */
-static int set_PGC(vm_t *vm,int pgcN);
-/* Initialisation */
+static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang);
+static pgcit_t* get_PGCIT(vm_t *vm);
-vm_t* vm_new_vm() {
- vm_t *vm = (vm_t*)calloc(sizeof(vm_t), sizeof(char));
- return vm;
-}
+/* Helper functions */
+#ifdef TRACE
static void vm_print_current_domain_state(vm_t *vm) {
switch((vm->state).domain) {
case VTS_DOMAIN:
@@ -123,60 +121,9 @@ static void vm_print_current_domain_state(vm_t *vm) {
(vm->state).TTN_REG,
(vm->state).TT_PGCN_REG);
}
+#endif
-void vm_stop(vm_t *vm) {
- if(!vm)
- return;
-
- if(vm->vmgi) {
- ifoClose(vm->vmgi);
- vm->vmgi=NULL;
- }
-
- if(vm->vtsi) {
- ifoClose(vm->vtsi);
- vm->vmgi=NULL;
- }
-
- if(vm->dvd) {
- DVDClose(vm->dvd);
- vm->dvd=NULL;
- }
-}
-
-void vm_free_vm(vm_t *vm) {
- if(vm) {
- vm_stop(vm);
- free(vm);
- }
-}
-
-/* IFO Access */
-
-ifo_handle_t *vm_get_vmgi(vm_t *vm) {
- if(!vm)
- return NULL;
-
- return vm->vmgi;
-}
-
-ifo_handle_t *vm_get_vtsi(vm_t *vm) {
- if(!vm)
- return NULL;
-
- return vm->vtsi;
-}
-
-/* Reader Access */
-
-dvd_reader_t *vm_get_dvd_reader(vm_t *vm) {
- if(!vm)
- return NULL;
-
- return vm->dvd;
-}
-
-void dvd_read_name( vm_t *this, char *devname) {
+void dvd_read_name( vm_t *this, const char *devname) {
int fd, i;
#ifndef __FreeBSD__
off64_t off;
@@ -193,88 +140,173 @@ void dvd_read_name( vm_t *this, char *devname) {
off = read( fd, data, DVD_VIDEO_LB_LEN );
close(fd);
if (off == ( (int64_t) DVD_VIDEO_LB_LEN )) {
- fprintf( stderr, "VM DVD Title: ");
+ fprintf(MSG_OUT, "libdvdnav: DVD Title: ");
for(i=25; i < 73; i++ ) {
if((data[i] == 0)) break;
if((data[i] > 32) && (data[i] < 127)) {
- fprintf(stderr, "%c", data[i]);
+ fprintf(MSG_OUT, "%c", data[i]);
} else {
- fprintf(stderr, " ");
+ fprintf(MSG_OUT, " ");
}
}
strncpy(&this->dvd_name[0], &data[25], 48);
- /* fprintf(stderr, "TITLE:%s\n",&this->dvd_name[0]); */
this->dvd_name[48]=0;
- this->dvd_name_length=strlen(&this->dvd_name[0]);
- fprintf( stderr, "\nVM DVD Serial Number: ");
+ fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: ");
for(i=73; i < 89; i++ ) {
if((data[i] == 0)) break;
if((data[i] > 32) && (data[i] < 127)) {
- fprintf(stderr, "%c", data[i]);
+ fprintf(MSG_OUT, "%c", data[i]);
} else {
- fprintf(stderr, " ");
+ fprintf(MSG_OUT, " ");
}
}
- fprintf( stderr, "\nVM DVD Title (Alternative): ");
+ fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): ");
for(i=89; i < 128; i++ ) {
if((data[i] == 0)) break;
if((data[i] > 32) && (data[i] < 127)) {
- fprintf(stderr, "%c", data[i]);
+ fprintf(MSG_OUT, "%c", data[i]);
} else {
- fprintf(stderr, " ");
+ fprintf(MSG_OUT, " ");
}
}
- fprintf( stderr, "\n");
+ fprintf(MSG_OUT, "\n");
} else {
- fprintf( stderr, "libdvdread: Can't read name block. Probably not a DVD-ROM device.\n");
+ fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a DVD-ROM device.\n");
}
} else {
- fprintf( stderr, "libdvdread: Can't seek to block %u\n", 32 );
+ fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 );
}
close(fd);
} else {
- fprintf(stderr,"NAME OPEN FAILED\n");
- }
+ fprintf(MSG_OUT, "NAME OPEN FAILED\n");
+ }
+}
+
+static void ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) {
+ if((vm->state).vtsN == vtsN) {
+ return; /* We alread have it */
+ }
+
+ if(vm->vtsi != NULL)
+ ifoClose(vm->vtsi);
+
+ vm->vtsi = ifoOpenVTSI(dvd, vtsN);
+ if(vm->vtsi == NULL) {
+ fprintf(MSG_OUT, "libdvdnav: ifoOpenVTSI failed - CRASHING!!!\n");
+ assert(0);
+ }
+ if(!ifoRead_VTS_PTT_SRPT(vm->vtsi)) {
+ fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_PTT_SRPT failed - CRASHING!!!\n");
+ assert(0);
+ }
+ if(!ifoRead_PGCIT(vm->vtsi)) {
+ fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCIT failed - CRASHING!!!\n");
+ assert(0);
+ }
+ if(!ifoRead_PGCI_UT(vm->vtsi)) {
+ fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCI_UT failed - CRASHING!!!\n");
+ assert(0);
+ }
+ if(!ifoRead_VOBU_ADMAP(vm->vtsi)) {
+ fprintf(MSG_OUT, "libdvdnav: ifoRead_VOBU_ADMAP vtsi failed - CRASHING\n");
+ assert(0);
+ }
+ if(!ifoRead_TITLE_VOBU_ADMAP(vm->vtsi)) {
+ fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed - CRASHING\n");
+ assert(0);
+ }
+ (vm->state).vtsN = vtsN;
+}
+
+
+/* Initialisation & Destruction */
+
+vm_t* vm_new_vm() {
+ return (vm_t*)calloc(sizeof(vm_t), sizeof(char));
+}
+
+void vm_free_vm(vm_t *vm) {
+ vm_stop(vm);
+ free(vm);
+}
+
+
+/* IFO Access */
+
+ifo_handle_t *vm_get_vmgi(vm_t *vm) {
+ return vm->vmgi;
}
-int vm_reset(vm_t *vm, char *dvdroot) /* , register_t regs) */ {
+ifo_handle_t *vm_get_vtsi(vm_t *vm) {
+ return vm->vtsi;
+}
+
+
+/* Reader Access */
+
+dvd_reader_t *vm_get_dvd_reader(vm_t *vm) {
+ return vm->dvd;
+}
+
+
+/* Basic Handling */
+
+void vm_start(vm_t *vm)
+{
+ /* Set pgc to FP (First Play) pgc */
+ set_FP_PGC(vm);
+ process_command(vm, play_PGC(vm));
+}
+
+void vm_stop(vm_t *vm) {
+ if(vm->vmgi) {
+ ifoClose(vm->vmgi);
+ vm->vmgi=NULL;
+ }
+ if(vm->vtsi) {
+ ifoClose(vm->vtsi);
+ vm->vmgi=NULL;
+ }
+ if(vm->dvd) {
+ DVDClose(vm->dvd);
+ vm->dvd=NULL;
+ }
+ vm->stopped = 1;
+}
+
+int vm_reset(vm_t *vm, const char *dvdroot) {
/* Setup State */
- memset((vm->state).registers.SPRM, 0, sizeof(uint16_t)*24);
+ memset((vm->state).registers.SPRM, 0, sizeof((vm->state).registers.SPRM));
memset((vm->state).registers.GPRM, 0, sizeof((vm->state).registers.GPRM));
memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode));
memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode));
memset((vm->state).registers.GPRM_time, 0, sizeof((vm->state).registers.GPRM_time));
- (vm->state).registers.SPRM[0] = ('e'<<8)|'n'; /* Player Menu Languange code */
- (vm->state).AST_REG = 15; /* 15 why? */
- (vm->state).SPST_REG = 62; /* 62 why? */
- (vm->state).AGL_REG = 1;
- (vm->state).TTN_REG = 1;
- (vm->state).VTS_TTN_REG = 1;
- /* (vm->state).TT_PGCN_REG = 0 */
- (vm->state).PTTN_REG = 1;
- (vm->state).HL_BTNN_REG = 1 << 10;
-
- (vm->state).PTL_REG = 15; /* Parental Level */
- (vm->state).registers.SPRM[12] = ('U'<<8)|'S'; /* Parental Management Country Code */
- (vm->state).registers.SPRM[16] = ('e'<<8)|'n'; /* Initial Language Code for Audio */
- (vm->state).registers.SPRM[18] = ('e'<<8)|'n'; /* Initial Language Code for Spu */
- /* Player Regional Code Mask.
- * bit0 = Region 1
- * bit1 = Region 2
- */
- (vm->state).registers.SPRM[20] = 0x1; /* Player Regional Code Mask. Region free! */
- (vm->state).registers.SPRM[14] = 0x100; /* Try Pan&Scan */
+ (vm->state).registers.SPRM[0] = ('e'<<8)|'n'; /* Player Menu Languange code */
+ (vm->state).AST_REG = 15; /* 15 why? */
+ (vm->state).SPST_REG = 62; /* 62 why? */
+ (vm->state).AGL_REG = 1;
+ (vm->state).TTN_REG = 1;
+ (vm->state).VTS_TTN_REG = 1;
+ /* (vm->state).TT_PGCN_REG = 0 */
+ (vm->state).PTTN_REG = 1;
+ (vm->state).HL_BTNN_REG = 1 << 10;
+ (vm->state).PTL_REG = 15; /* Parental Level */
+ (vm->state).registers.SPRM[12] = ('U'<<8)|'S'; /* Parental Management Country Code */
+ (vm->state).registers.SPRM[16] = ('e'<<8)|'n'; /* Initial Language Code for Audio */
+ (vm->state).registers.SPRM[18] = ('e'<<8)|'n'; /* Initial Language Code for Spu */
+ (vm->state).registers.SPRM[20] = 0x1; /* Player Regional Code Mask. Region free! */
+ (vm->state).registers.SPRM[14] = 0x100; /* Try Pan&Scan */
- (vm->state).pgN = 0;
- (vm->state).cellN = 0;
- (vm->state).cell_restart = 0;
+ (vm->state).pgN = 0;
+ (vm->state).cellN = 0;
+ (vm->state).cell_restart = 0;
- (vm->state).domain = FP_DOMAIN;
- (vm->state).rsm_vtsN = 0;
- (vm->state).rsm_cellN = 0;
- (vm->state).rsm_blockN = 0;
+ (vm->state).domain = FP_DOMAIN;
+ (vm->state).rsm_vtsN = 0;
+ (vm->state).rsm_cellN = 0;
+ (vm->state).rsm_blockN = 0;
- (vm->state).vtsN = -1;
+ (vm->state).vtsN = -1;
if (vm->dvd && dvdroot) {
/* a new dvd device has been requested */
@@ -284,92 +316,77 @@ int vm_reset(vm_t *vm, char *dvdroot) /* , register_t regs) */ {
vm->dvd = DVDOpen(dvdroot);
if(!vm->dvd) {
fprintf(MSG_OUT, "libdvdnav: vm: faild to open/read the DVD\n");
- return -1;
+ return 0;
}
dvd_read_name(vm, dvdroot);
- vm->map = remap_loadmap( vm->dvd_name);
-
+ vm->map = remap_loadmap(vm->dvd_name);
vm->vmgi = ifoOpenVMGI(vm->dvd);
if(!vm->vmgi) {
fprintf(MSG_OUT, "libdvdnav: vm: faild to read VIDEO_TS.IFO\n");
- return -1;
+ return 0;
}
if(!ifoRead_FP_PGC(vm->vmgi)) {
fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_FP_PGC failed\n");
- return -1;
+ return 0;
}
if(!ifoRead_TT_SRPT(vm->vmgi)) {
fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_TT_SRPT failed\n");
- return -1;
+ return 0;
}
if(!ifoRead_PGCI_UT(vm->vmgi)) {
fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PGCI_UT failed\n");
- return -1;
+ return 0;
}
if(!ifoRead_PTL_MAIT(vm->vmgi)) {
fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_PTL_MAIT failed\n");
- ; /* return -1; Not really used for now.. */
+ /* return 0; Not really used for now.. */
}
if(!ifoRead_VTS_ATRT(vm->vmgi)) {
fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VTS_ATRT failed\n");
- ; /* return -1; Not really used for now.. */
+ /* return 0; Not really used for now.. */
}
if(!ifoRead_VOBU_ADMAP(vm->vmgi)) {
fprintf(MSG_OUT, "libdvdnav: vm: ifoRead_VOBU_ADMAP vgmi failed\n");
- ; /* return -1; Not really used for now.. */
+ /* return 0; Not really used for now.. */
}
/* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */
}
- else fprintf(MSG_OUT, "libdvdnav: vm: reset\n");
if (vm->vmgi) {
- fprintf(MSG_OUT, "libdvdnav: DVD disk reports itself with Region mask 0x%08x. Maybe region %u.\n",
- vm->vmgi->vmgi_mat->vmg_category,
- (((vm->vmgi->vmgi_mat->vmg_category >> 16) ^ 0xff) & 0xff) );
+ int i, mask;
+ fprintf(MSG_OUT, "libdvdnav: DVD disk reports itself with Region mask 0x%08x. Regions:",
+ vm->vmgi->vmgi_mat->vmg_category);
+ for (i = 1, mask = 1; i <= 8; i++, mask <<= 1)
+ if (((vm->vmgi->vmgi_mat->vmg_category >> 16) & mask) == 0)
+ fprintf(MSG_OUT, " %d", i);
+ fprintf(MSG_OUT, "\n");
}
- return 0;
+ return 1;
}
-/* FIXME TODO XXX $$$ Handle error condition too... */
-int vm_start(vm_t *vm)
-{
- link_t link_values;
-
- /* Set pgc to FP(First Play) pgc */
- set_FP_PGC(vm);
- link_values = play_PGC(vm);
- link_values = process_command(vm,link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_start: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
+/* regular playback */
- return 0; /* ?? */
-}
-
-int vm_position_get(vm_t *vm, vm_position_t *position) {
+void vm_position_get(vm_t *vm, vm_position_t *position) {
position->button = (vm->state).HL_BTNN_REG >> 10;
+ position->vts = (vm->state).vtsN;
+ position->domain = (vm->state).domain;
position->spu_channel = (vm->state).SPST_REG;
position->audio_channel = (vm->state).AST_REG;
position->angle_channel = (vm->state).AGL_REG;
position->hop_channel = vm->hop_channel; /* Increases by one on each hop */
- position->vts = (vm->state).vtsN;
- position->domain = (vm->state).domain;
position->cell = (vm->state).cellN;
position->cell_restart = (vm->state).cell_restart;
+ position->cell_start = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector;
position->still = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].still_time;
- position->vobu_start = (vm->state).pgc->cell_playback[(vm->state).cellN - 1].first_sector;
- position->vobu_next = (vm->state).blockN;
+ position->block = (vm->state).blockN;
/* still already detrmined or not at PGC end */
if (position->still || (vm->state).cellN < (vm->state).pgc->nr_of_cells)
- return 1;
+ return;
/* handle PGC stills */
if ((vm->state).pgc->still_time) {
position->still = (vm->state).pgc->still_time;
- return 1;
+ return;
}
/* This is a rough fix for some strange still situations on some strange DVDs.
* There are discs (like the German "Back to the Future" RC2) where the only
@@ -393,312 +410,95 @@ int vm_position_get(vm_t *vm, vm_position_t *position) {
if (time > 0xff) time = 0xff;
position->still = time;
}
-
- return 1;
-}
-
-int vm_position_print(vm_t *vm, vm_position_t *position) {
- fprintf(MSG_OUT, "libdvdnav: But=%x Spu=%x Aud=%x Ang=%x Hop=%x vts=%x dom=%x cell=%x cell_restart=%x still=%x start=%x next=%x\n",
- position->button,
- position->spu_channel,
- position->audio_channel,
- position->angle_channel,
- position->hop_channel,
- position->vts,
- position->domain,
- position->cell,
- position->cell_restart,
- position->still,
- position->vobu_start,
- position->vobu_next);
- return 1;
}
-
-int vm_start_title(vm_t *vm, int tt) {
- link_t link_values;
-
- set_TT(vm, tt);
- link_values = play_PGC(vm);
- link_values = process_command(vm, link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_start_title: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
-
- return 0; /* ?? */
+void vm_get_next_cell(vm_t *vm) {
+ process_command(vm, play_Cell_post(vm));
}
-int vm_jump_prog(vm_t *vm, int pr) {
- link_t link_values;
+/* Jumping */
- set_PGC(vm, get_PGCN(vm));
- (vm->state).pgN = pr; /* ?? set_PGC() clobbers pgN */
- link_values = play_PG(vm);
- link_values = process_command(vm, link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_jump_prog: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
-
- return 0; /* ?? */
+int vm_jump_pg(vm_t *vm, int pg) {
+ (vm->state).pgN = pg;
+ process_command(vm, play_PG(vm));
+ return 1;
}
-int vm_eval_cmd(vm_t *vm, vm_cmd_t *cmd)
-{
- link_t link_values;
-
- if(vmEval_CMD(cmd, 1, &(vm->state).registers, &link_values)) {
- link_values = process_command(vm, link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_eval_cmd: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- return link_values.data2; /* return if there acutally was a jump */
- } else {
- return 0; /* It updated some state thats all... */
- }
-}
+int vm_jump_title_part(vm_t *vm, int title, int part) {
+ int vtsN;
-int vm_get_next_cell(vm_t *vm)
-{
- link_t link_values;
- link_values = play_Cell_post(vm);
- link_values = process_command(vm,link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_get_next_cell: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
-
- return 0; /* ?? */
-}
+ vtsN = vm->vmgi->tt_srpt->title[title - 1].title_set_nr;
-int vm_top_pg(vm_t *vm)
-{
- link_t link_values;
- link_values = play_PG(vm);
- link_values = process_command(vm,link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_top_pg: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
-
- return 1; /* Jump */
+ if(!set_VTS_PTT(vm, vtsN, title, part))
+ return 0;
+ process_command(vm, play_PGC_PG(vm, (vm->state).pgN));
+ vm->hop_channel++;
+ return 1;
}
-int vm_go_up(vm_t *vm)
-{
- link_t link_values;
-
- if(set_PGC(vm, (vm->state).pgc->goup_pgc_nr))
- assert(0);
-
- link_values = play_PGC(vm);
- link_values = process_command(vm,link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_go_up: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
-
- return 1; /* Jump */
+int vm_jump_top_pg(vm_t *vm) {
+ process_command(vm, play_PG(vm));
+ return 1;
}
-int vm_next_pg(vm_t *vm)
-{
+int vm_jump_next_pg(vm_t *vm) {
if((vm->state).pgN >= (vm->state).pgc->nr_of_programs) {
- /* last program -> move to first program of next PGC */
- if ((vm->state).pgc->next_pgc_nr != 0 && set_PGC(vm, (vm->state).pgc->next_pgc_nr) == 0) {
- vm_jump_prog(vm, 1);
- return 1;
- }
- /* something failed, try to move to the cell after the last */
- (vm->state).cellN = (vm->state).pgc->nr_of_cells;
- vm_get_next_cell(vm);
+ /* last program -> move to TailPGC */
+ process_command(vm, play_PGC_post(vm));
return 1;
} else {
- vm_jump_prog(vm, (vm->state).pgN + 1);
+ vm_jump_pg(vm, (vm->state).pgN + 1);
return 1;
}
}
-int vm_prev_pg(vm_t *vm)
-{
+int vm_jump_prev_pg(vm_t *vm) {
if ((vm->state).pgN <= 1) {
/* first program -> move to last program of previous PGC */
- if ((vm->state).pgc->prev_pgc_nr != 0 && set_PGC(vm, (vm->state).pgc->prev_pgc_nr) == 0) {
- vm_jump_prog(vm, (vm->state).pgc->nr_of_programs);
+ if ((vm->state).pgc->prev_pgc_nr && set_PGCN(vm, (vm->state).pgc->prev_pgc_nr)) {
+ process_command(vm, play_PGC(vm));
return 1;
}
return 0;
} else {
- vm_jump_prog(vm, (vm->state).pgN - 1);
+ vm_jump_pg(vm, (vm->state).pgN - 1);
return 1;
}
}
-/* 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, ttn=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(ttn=0;( (ttn < vts_ptt_srpt->nr_of_srpts) && (found == 0) );ttn++) {
- for(part=0;((part < vts_ptt_srpt->title[ttn].nr_of_ptts) && (found == 0));part++) {
- if ( (vts_ptt_srpt->title[ttn].ptt[part].pgcn == pgcN) &&
- (vts_ptt_srpt->title[ttn].ptt[part].pgn == pgN ) ) {
- found = 1;
- break;
- }
- }
- if (found != 0) break;
- }
- ttn++;
- part++;
- for(title=0; title < vm->vmgi->tt_srpt->nr_of_srpts; title++){
- if( (vm->vmgi->tt_srpt->title[title].vts_ttn == ttn) &&
- (vm->vmgi->tt_srpt->title[title].title_set_nr == vm->state.vtsN)){
- found = 1;
- break;
- }
- }
- title++;
-
- if (found == 1) {
- 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");
- 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)
-{
- domain_t result = VTSM_DOMAIN; /* Really shouldn't have to.. */
-
- switch(menuid) {
- case DVD_MENU_Title:
- result = VMGM_DOMAIN;
- break;
- case DVD_MENU_Root:
- case DVD_MENU_Subpicture:
- case DVD_MENU_Audio:
- case DVD_MENU_Angle:
- case DVD_MENU_Part:
- result = VTSM_DOMAIN;
- break;
+int vm_jump_up(vm_t *vm) {
+ if((vm->state).pgc->goup_pgc_nr && set_PGCN(vm, (vm->state).pgc->goup_pgc_nr)) {
+ process_command(vm, play_PGC(vm));
+ return 1;
}
-
- return result;
+ return 0;
}
-int vm_menu_call(vm_t *vm, DVDMenuID_t menuid, int block)
-{
- domain_t old_domain;
- link_t link_values;
+int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid) {
+ domain_t old_domain = (vm->state).domain;
- /* Should check if we are allowed/can acces this menu */
-
-
- /* FIXME XXX $$$ How much state needs to be restored
- * when we fail to find a menu? */
-
- old_domain = (vm->state).domain;
-
- switch((vm->state).domain) {
+ switch ((vm->state).domain) {
case VTS_DOMAIN:
- saveRSMinfo(vm, 0, block);
+ set_RSMinfo(vm, 0, (vm->state).blockN);
/* FALL THROUGH */
case VTSM_DOMAIN:
case VMGM_DOMAIN:
- (vm->state).domain = menuid2domain(menuid);
- if(get_PGCIT(vm) != NULL && set_MENU(vm, menuid) != -1) {
- link_values = play_PGC(vm);
- link_values = process_command(vm, link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_menu_call: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
- return 1; /* Jump */
+ switch(menuid) {
+ case DVD_MENU_Title:
+ (vm->state).domain = VMGM_DOMAIN;
+ break;
+ case DVD_MENU_Root:
+ case DVD_MENU_Subpicture:
+ case DVD_MENU_Audio:
+ case DVD_MENU_Angle:
+ case DVD_MENU_Part:
+ (vm->state).domain = VTSM_DOMAIN;
+ break;
+ }
+ if(get_PGCIT(vm) && set_MENU(vm, menuid)) {
+ process_command(vm, play_PGC(vm));
+ return 1; /* Jump */
} else {
(vm->state).domain = old_domain;
}
@@ -710,72 +510,74 @@ int vm_menu_call(vm_t *vm, DVDMenuID_t menuid, int block)
return 0;
}
-
-int vm_resume(vm_t *vm)
-{
- int i;
+int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd) {
link_t link_values;
- /* Check and see if there is any rsm info!! */
- if((vm->state).rsm_vtsN == 0) {
- return 0;
+ if(vmEval_CMD(cmd, 1, &(vm->state).registers, &link_values))
+ return process_command(vm, link_values);
+ else
+ return 0; /* It updated some state thats all... */
+}
+
+
+/* getting information */
+
+int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result) {
+ vts_ptt_srpt_t *vts_ptt_srpt;
+ int title, part = 0, vts_ttn;
+ int found;
+ int16_t pgcN, pgN;
+
+ vts_ptt_srpt = vm->vtsi->vts_ptt_srpt;
+ pgcN = get_PGCN(vm);
+ pgN = vm->state.pgN;
+
+ 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 (found) break;
}
+ vts_ttn++;
+ part++;
- (vm->state).domain = VTS_DOMAIN;
- ifoOpenNewVTSI(vm, vm->dvd, (vm->state).rsm_vtsN);
- set_PGC(vm, (vm->state).rsm_pgcN);
-
- /* These should never be set in SystemSpace and/or MenuSpace */
- /* (vm->state).TTN_REG = (vm->state).rsm_tt; */
- /* (vm->state).TT_PGCN_REG = (vm->state).rsm_pgcN; */
- /* (vm->state).HL_BTNN_REG = (vm->state).rsm_btnn; */
- for(i = 0; i < 5; i++) {
- (vm->state).registers.SPRM[4 + i] = (vm->state).rsm_regs[i];
- }
+ title = get_TT(vm, vm->state.vtsN, vts_ttn);
- if((vm->state).rsm_cellN == 0) {
- assert((vm->state).cellN); /* Checking if this ever happens */
- (vm->state).pgN = 1;
- link_values = play_PG(vm);
- link_values = process_command(vm, link_values);
- assert(link_values.command == PlayThis);
- (vm->state).blockN = link_values.data1;
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_resume1: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- assert( (vm->state).blockN == 0 );
- } else {
- (vm->state).cellN = (vm->state).rsm_cellN;
- (vm->state).blockN = (vm->state).rsm_blockN;
#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: vm_resume2: blockN set to 0x%x\n", (vm->state).blockN);
-#endif
- /* (vm->state).pgN = ?? does this gets the righ value in play_Cell, no! */
- if(set_PGN(vm)) {
- /* Were at or past the end of the PGC, should not happen for a RSM */
- assert(0);
- play_PGC_post(vm);
- }
+ if (title) {
+ 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");
}
-
- return 1; /* Jump */
+#endif
+ if (!title)
+ return 0;
+ *title_result = title;
+ *part_result = part;
+ return 1;
}
-/**
- * Return the substream id for 'logical' audio stream audioN.
- * 0 <= audioN < 8
+/* Return the substream id for 'logical' audio stream audioN.
+ * 0 <= audioN < 8
*/
-int vm_get_audio_stream(vm_t *vm, int audioN)
-{
+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 == VTSM_DOMAIN
- || (vm->state).domain == VMGM_DOMAIN
- || (vm->state).domain == FP_DOMAIN) {
+
+ if((vm->state).domain != VTS_DOMAIN)
audioN = 0;
- }
if(audioN < 8) {
/* Is there any contol info for this logical stream */
@@ -784,35 +586,26 @@ int vm_get_audio_stream(vm_t *vm, int audioN)
}
}
- if((vm->state).domain == VTSM_DOMAIN
- || (vm->state).domain == VMGM_DOMAIN
- || (vm->state).domain == FP_DOMAIN) {
- if(streamN == -1)
- streamN = 0;
- }
+ if((vm->state).domain != VTS_DOMAIN && streamN == -1)
+ streamN = 0;
- /* Should also check in vtsi/vmgi status that what kind of stream
+ /* FIXME: Should also check in vtsi/vmgi status what kind of stream
* it is (ac3/lpcm/dts/sdds...) to find the right (sub)stream id */
return streamN;
}
-/**
- * Return the substream id for 'logical' subpicture stream subpN and given mode.
+/* Return the substream id for 'logical' subpicture stream subpN and given mode.
* 0 <= subpN < 32
* mode == 0 - widescreen
* mode == 1 - letterbox
* mode == 2 - pan&scan
*/
-int vm_get_subp_stream(vm_t *vm, int subpN, int mode)
-{
+int vm_get_subp_stream(vm_t *vm, int subpN, int mode) {
int streamN = -1;
int source_aspect = vm_get_video_aspect(vm);
- if((vm->state).domain == VTSM_DOMAIN
- || (vm->state).domain == VMGM_DOMAIN
- || (vm->state).domain == FP_DOMAIN) {
+ if((vm->state).domain != VTS_DOMAIN)
subpN = 0;
- }
if(subpN < 32) { /* a valid logical stream */
/* Is this logical stream present */
@@ -833,76 +626,62 @@ int vm_get_subp_stream(vm_t *vm, int subpN, int mode)
}
}
- /* Paranoia.. if no stream select 0 anyway */
-/* I am not paranoid */
-/* if((vm->state).domain == VTSM_DOMAIN
- || (vm->state).domain == VMGM_DOMAIN
- || (vm->state).domain == FP_DOMAIN) {
- if(streamN == -1)
- streamN = 0;
- }
-*/
- /* Should also check in vtsi/vmgi status that what kind of stream it is. */
+ if((vm->state).domain != VTS_DOMAIN && streamN == -1)
+ streamN = 0;
+
+ /* FIXME: Should also check in vtsi/vmgi status what kind of stream it is. */
return streamN;
}
-int vm_get_subp_active_stream(vm_t *vm, int mode)
-{
- int subpN;
+int vm_get_audio_active_stream(vm_t *vm) {
+ int audioN;
int streamN;
- subpN = (vm->state).SPST_REG & ~0x40;
- streamN = vm_get_subp_stream(vm, subpN, mode);
+ audioN = (vm->state).AST_REG ;
+ streamN = vm_get_audio_stream(vm, audioN);
/* If no such stream, then select the first one that exists. */
if(streamN == -1) {
- for(subpN = 0; subpN < 32; subpN++) {
- if((vm->state).pgc->subp_control[subpN] & (1<<31)) {
-
- streamN = vm_get_subp_stream(vm, subpN, mode);
- break;
+ for(audioN = 0; audioN < 8; audioN++) {
+ if((vm->state).pgc->audio_control[audioN] & (1<<15)) {
+ if ((streamN = vm_get_audio_stream(vm, audioN)) >= 0)
+ break;
}
}
- }
-
- /* We should instead send the on/off status to the spudecoder / mixer */
- /* If we are in the title domain see if the spu mixing is on */
- if((vm->state).domain == VTS_DOMAIN && !((vm->state).SPST_REG & 0x40)) {
- /* Bit 7 set means hide, and only let Forced display show */
- return (streamN | 0x80);
- } else {
- return streamN;
}
+
+ return streamN;
}
-int vm_get_audio_active_stream(vm_t *vm)
-{
- int audioN;
+int vm_get_subp_active_stream(vm_t *vm, int mode) {
+ int subpN;
int streamN;
- audioN = (vm->state).AST_REG ;
- streamN = vm_get_audio_stream(vm, audioN);
+ subpN = (vm->state).SPST_REG & ~0x40;
+ streamN = vm_get_subp_stream(vm, subpN, mode);
/* If no such stream, then select the first one that exists. */
if(streamN == -1) {
- for(audioN = 0; audioN < 8; audioN++) {
- if((vm->state).pgc->audio_control[audioN] & (1<<15)) {
- streamN = vm_get_audio_stream(vm, audioN);
- break;
+ for(subpN = 0; subpN < 32; subpN++) {
+ if((vm->state).pgc->subp_control[subpN] & (1<<31)) {
+ if ((streamN = vm_get_subp_stream(vm, subpN, mode)) >= 0)
+ break;
}
}
- }
-
- return streamN;
-}
+ }
+ if((vm->state).domain == VTS_DOMAIN && !((vm->state).SPST_REG & 0x40))
+ /* Bit 7 set means hide, and only let Forced display show */
+ return (streamN | 0x80);
+ else
+ return streamN;
+}
-void vm_get_angle_info(vm_t *vm, int *num_avail, int *current)
-{
+void vm_get_angle_info(vm_t *vm, int *current, int *num_avail) {
*num_avail = 1;
*current = 1;
if((vm->state).domain == VTS_DOMAIN) {
- /* TTN_REG does not allways point to the correct title.. */
title_info_t *title;
+ /* TTN_REG does not allways point to the correct title.. */
if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts)
return;
title = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1];
@@ -911,87 +690,51 @@ void vm_get_angle_info(vm_t *vm, int *num_avail, int *current)
return;
*num_avail = title->nr_of_angles;
*current = (vm->state).AGL_REG;
- if(*current > *num_avail) /* Is this really a good idea? */
- *current = *num_avail;
}
}
-
-void vm_get_audio_info(vm_t *vm, int *num_avail, int *current)
-{
- if((vm->state).domain == VTS_DOMAIN) {
+#if 0
+/* currently unused */
+void vm_get_audio_info(vm_t *vm, int *current, int *num_avail) {
+ switch ((vm->state).domain) {
+ case VTS_DOMAIN:
*num_avail = vm->vtsi->vtsi_mat->nr_of_vts_audio_streams;
*current = (vm->state).AST_REG;
- } else if((vm->state).domain == VTSM_DOMAIN) {
+ break;
+ case VTSM_DOMAIN:
*num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_audio_streams; /* 1 */
*current = 1;
- } else if((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN) {
+ break;
+ case VMGM_DOMAIN:
+ case FP_DOMAIN:
*num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_audio_streams; /* 1 */
*current = 1;
+ break;
}
}
-void vm_get_subp_info(vm_t *vm, int *num_avail, int *current)
-{
- if((vm->state).domain == VTS_DOMAIN) {
+/* currently unused */
+void vm_get_subp_info(vm_t *vm, int *current, int *num_avail) {
+ switch ((vm->state).domain) {
+ case VTS_DOMAIN:
*num_avail = vm->vtsi->vtsi_mat->nr_of_vts_subp_streams;
*current = (vm->state).SPST_REG;
- } else if((vm->state).domain == VTSM_DOMAIN) {
+ break;
+ case VTSM_DOMAIN:
*num_avail = vm->vtsi->vtsi_mat->nr_of_vtsm_subp_streams; /* 1 */
*current = 0x41;
- } else if((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN) {
+ break;
+ case VMGM_DOMAIN:
+ case FP_DOMAIN:
*num_avail = vm->vmgi->vmgi_mat->nr_of_vmgm_subp_streams; /* 1 */
*current = 0x41;
+ break;
}
}
-subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN)
-{
- subp_attr_t attr;
-
- if((vm->state).domain == VTS_DOMAIN) {
- attr = vm->vtsi->vtsi_mat->vts_subp_attr[streamN];
- } else if((vm->state).domain == VTSM_DOMAIN) {
- attr = vm->vtsi->vtsi_mat->vtsm_subp_attr;
- } else if((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN) {
- attr = vm->vmgi->vmgi_mat->vmgm_subp_attr;
- }
- return attr;
-}
-
-audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN)
-{
- audio_attr_t attr;
-
- if((vm->state).domain == VTS_DOMAIN) {
- attr = vm->vtsi->vtsi_mat->vts_audio_attr[streamN];
- } else if((vm->state).domain == VTSM_DOMAIN) {
- attr = vm->vtsi->vtsi_mat->vtsm_audio_attr;
- } else if((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN) {
- attr = vm->vmgi->vmgi_mat->vmgm_audio_attr;
- }
- return attr;
-}
-
-video_attr_t vm_get_video_attr(vm_t *vm)
-{
- video_attr_t attr;
-
- if((vm->state).domain == VTS_DOMAIN) {
- attr = vm->vtsi->vtsi_mat->vts_video_attr;
- } else if((vm->state).domain == VTSM_DOMAIN) {
- attr = vm->vtsi->vtsi_mat->vtsm_video_attr;
- } else if((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN) {
- attr = vm->vmgi->vmgi_mat->vmgm_video_attr;
- }
- return attr;
-}
-
-void vm_get_video_res(vm_t *vm, int *width, int *height)
-{
- video_attr_t attr;
-
- attr = vm_get_video_attr(vm);
+/* currently unused */
+void vm_get_video_res(vm_t *vm, int *width, int *height) {
+ video_attr_t attr = vm_get_video_attr(vm);
if(attr.video_format != 0)
*height = 576;
@@ -1013,70 +756,65 @@ void vm_get_video_res(vm_t *vm, int *width, int *height)
break;
}
}
+#endif
-/* Must be called before domain is changed (get_PGCN()) */
-static void saveRSMinfo(vm_t *vm, int cellN, int blockN)
-{
- int i;
+int vm_get_video_aspect(vm_t *vm) {
+ int aspect = vm_get_video_attr(vm).display_aspect_ratio;
- if(cellN != 0) {
- (vm->state).rsm_cellN = cellN;
- (vm->state).rsm_blockN = 0;
- } else {
- (vm->state).rsm_cellN = (vm->state).cellN;
- (vm->state).rsm_blockN = blockN;
- }
- (vm->state).rsm_vtsN = (vm->state).vtsN;
- (vm->state).rsm_pgcN = get_PGCN(vm);
-
- /* assert((vm->state).rsm_pgcN == (vm->state).TT_PGCN_REG); for VTS_DOMAIN */
+ assert(aspect == 0 || aspect == 3);
+ (vm->state).registers.SPRM[14] &= ~(0x3 << 10);
+ (vm->state).registers.SPRM[14] |= aspect << 10;
- for(i = 0; i < 5; i++) {
- (vm->state).rsm_regs[i] = (vm->state).registers.SPRM[4 + i];
- }
+ return aspect;
}
+int vm_get_video_scale_permission(vm_t *vm) {
+ return vm_get_video_attr(vm).permitted_df;
+}
+video_attr_t vm_get_video_attr(vm_t *vm) {
+ switch ((vm->state).domain) {
+ case VTS_DOMAIN:
+ return vm->vtsi->vtsi_mat->vts_video_attr;
+ case VTSM_DOMAIN:
+ return vm->vtsi->vtsi_mat->vtsm_video_attr;
+ case VMGM_DOMAIN:
+ case FP_DOMAIN:
+ return vm->vmgi->vmgi_mat->vmgm_video_attr;
+ }
+ assert(0);
+}
-/* Figure out the correct pgN from the cell and update (vm->state). */
-static int set_PGN(vm_t *vm) {
- int new_pgN = 0;
-
- while(new_pgN < (vm->state).pgc->nr_of_programs
- && (vm->state).cellN >= (vm->state).pgc->program_map[new_pgN])
- new_pgN++;
-
- if(new_pgN == (vm->state).pgc->nr_of_programs) /* We are at the last program */
- if((vm->state).cellN > (vm->state).pgc->nr_of_cells)
- return 1; /* We are past the last cell */
-
- (vm->state).pgN = new_pgN;
-
- if((vm->state).domain == VTS_DOMAIN) {
- playback_type_t *pb_ty;
- if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts)
- 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) {
-#if 0 /* TTN_REG can't be trusted to have a correct value here... */
- vts_ptt_srpt_t *ptt_srpt = vtsi->vts_ptt_srpt;
- assert((vm->state).VTS_TTN_REG <= ptt_srpt->nr_of_srpts);
- 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->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");
- }
-
+audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN) {
+ switch ((vm->state).domain) {
+ case VTS_DOMAIN:
+ return vm->vtsi->vtsi_mat->vts_audio_attr[streamN];
+ case VTSM_DOMAIN:
+ return vm->vtsi->vtsi_mat->vtsm_audio_attr;
+ case VMGM_DOMAIN:
+ case FP_DOMAIN:
+ return vm->vmgi->vmgi_mat->vmgm_audio_attr;
}
-
- return 0;
+ assert(0);
+}
+
+subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN) {
+ switch ((vm->state).domain) {
+ case VTS_DOMAIN:
+ return vm->vtsi->vtsi_mat->vts_subp_attr[streamN];
+ case VTSM_DOMAIN:
+ return vm->vtsi->vtsi_mat->vtsm_subp_attr;
+ case VMGM_DOMAIN:
+ case FP_DOMAIN:
+ return vm->vmgi->vmgi_mat->vmgm_subp_attr;
+ }
+ assert(0);
}
-static link_t play_PGC(vm_t *vm)
-{
+
+/* Playback control */
+
+static link_t play_PGC(vm_t *vm) {
link_t link_values;
#ifdef TRACE
@@ -1088,18 +826,19 @@ static link_t play_PGC(vm_t *vm)
}
#endif
- /* This must be set before the pre-commands are executed because they */
- /* might contain a CallSS that will save resume state */
+ /* This must be set before the pre-commands are executed because they
+ * might contain a CallSS that will save resume state */
/* FIXME: This may be only a temporary fix for something... */
(vm->state).pgN = 1;
(vm->state).cellN = 0;
+ (vm->state).blockN = 0;
/* eval -> updates the state and returns either
- some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN)
- just play video i.e first PG
(This is what happens if you fall of the end of the pre_cmds)
- - or a error (are there more cases?) */
+ - or an error (are there more cases?) */
if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_pre) {
if(vmEval_CMD((vm->state).pgc->command_tbl->pre_cmds,
(vm->state).pgc->command_tbl->nr_of_pre,
@@ -1115,8 +854,7 @@ static link_t play_PGC(vm_t *vm)
return play_PG(vm);
}
-static link_t play_PGC_PG(vm_t *vm, int pgN)
-{
+static link_t play_PGC_PG(vm_t *vm, int pgN) {
link_t link_values;
#ifdef TRACE
@@ -1128,18 +866,19 @@ static link_t play_PGC_PG(vm_t *vm, int pgN)
}
#endif
- /* This must be set before the pre-commands are executed because they */
- /* might contain a CallSS that will save resume state */
+ /* This must be set before the pre-commands are executed because they
+ * might contain a CallSS that will save resume state */
/* FIXME: This may be only a temporary fix for something... */
(vm->state).pgN = pgN;
(vm->state).cellN = 0;
+ (vm->state).blockN = 0;
/* eval -> updates the state and returns either
- some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN)
- just play video i.e first PG
(This is what happens if you fall of the end of the pre_cmds)
- - or a error (are there more cases?) */
+ - or an error (are there more cases?) */
if((vm->state).pgc->command_tbl && (vm->state).pgc->command_tbl->nr_of_pre) {
if(vmEval_CMD((vm->state).pgc->command_tbl->pre_cmds,
(vm->state).pgc->command_tbl->nr_of_pre,
@@ -1155,8 +894,39 @@ static link_t play_PGC_PG(vm_t *vm, int pgN)
return play_PG(vm);
}
-static link_t play_PG(vm_t *vm)
-{
+static link_t play_PGC_post(vm_t *vm) {
+ link_t link_values;
+
+#ifdef TRACE
+ fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n");
+#endif
+
+ /* 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)
+ - 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 &&
+ vmEval_CMD((vm->state).pgc->command_tbl->post_cmds,
+ (vm->state).pgc->command_tbl->nr_of_post,
+ &(vm->state).registers, &link_values)) {
+ return link_values;
+ }
+
+#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);
+ return play_PGC(vm);
+}
+
+static link_t play_PG(vm_t *vm) {
#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: play_PG: (vm->state).pgN (%i)\n", (vm->state).pgN);
#endif
@@ -1176,9 +946,9 @@ static link_t play_PG(vm_t *vm)
return play_Cell(vm);
}
+static link_t play_Cell(vm_t *vm) {
+ static const link_t play_this = {PlayThis, /* Block in Cell */ 0, 0, 0};
-static link_t play_Cell(vm_t *vm)
-{
#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: play_Cell: (vm->state).cellN (%i)\n", (vm->state).cellN);
#endif
@@ -1193,7 +963,6 @@ static link_t play_Cell(vm_t *vm)
return play_PGC_post(vm);
}
-
/* Multi angle/Interleaved */
switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode) {
case 0: /* Normal */
@@ -1204,19 +973,20 @@ static link_t play_Cell(vm_t *vm)
case 0: /* Not part of a block */
assert(0);
case 1: /* Angle block */
- /* Loop and check each cell instead? So we don't get outsid the block. */
+ /* Loop and check each cell instead? So we don't get outside the block? */
(vm->state).cellN += (vm->state).AGL_REG - 1;
#ifdef STRICT
assert((vm->state).cellN <= (vm->state).pgc->nr_of_cells);
assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0);
assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1);
-#endif
+#else
if (!((vm->state).cellN <= (vm->state).pgc->nr_of_cells) ||
!((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode != 0) ||
!((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type == 1)) {
fprintf(MSG_OUT, "libdvdnav: Invalid angle block\n");
(vm->state).cellN -= (vm->state).AGL_REG - 1;
}
+#endif
break;
case 2: /* ?? */
case 3: /* ?? */
@@ -1224,33 +994,31 @@ static link_t play_Cell(vm_t *vm)
fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n",
(vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode,
(vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type);
+ assert(0);
}
break;
case 2: /* Cell in the block */
case 3: /* Last cell in the block */
- /* These might perhaps happen for RSM or LinkC commands? */
+ /* These might perhaps happen for RSM or LinkC commands? */
default:
fprintf(MSG_OUT, "libdvdnav: Cell is in block but did not enter at first cell!\n");
}
/* Updates (vm->state).pgN and PTTN_REG */
- if(set_PGN(vm)) {
+ if(!set_PGN(vm)) {
/* Should not happen */
- link_t tmp = {LinkTailPGC, /* No Button */ 0, 0, 0};
assert(0);
- return tmp;
+ return play_PGC_post(vm);
}
- (vm->state).cell_restart++;
+ (vm->state).cell_restart++;
+ (vm->state).blockN = 0;
+#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: Cell should restart here\n");
- {
- link_t tmp = {PlayThis, /* Block in Cell */ 0, 0, 0};
- return tmp;
- }
-
+#endif
+ return play_this;
}
-static link_t play_Cell_post(vm_t *vm)
-{
+static link_t play_Cell_post(vm_t *vm) {
cell_playback_t *cell;
#ifdef TRACE
@@ -1283,16 +1051,17 @@ static link_t play_Cell_post(vm_t *vm)
&(vm->state).registers, &link_values)) {
return link_values;
} else {
+#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: Cell command didn't do a Jump, Link or Call\n");
- /* Error ?? goto tail? goto next PG? or what? just continue? */
+#endif
}
} else {
+#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: Invalid Cell command\n");
-
+#endif
}
}
-
/* Where to continue after playing the cell... */
/* Multi angle/Interleaved */
switch((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode) {
@@ -1310,8 +1079,8 @@ static link_t play_Cell_post(vm_t *vm)
case 1: /* Angle block */
/* Skip the 'other' angles */
(vm->state).cellN++;
- while((vm->state).cellN <= (vm->state).pgc->nr_of_cells
- && (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode >= 2) {
+ while((vm->state).cellN <= (vm->state).pgc->nr_of_cells &&
+ (vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode >= 2) {
(vm->state).cellN++;
}
break;
@@ -1321,89 +1090,47 @@ static link_t play_Cell_post(vm_t *vm)
fprintf(MSG_OUT, "libdvdnav: Invalid? Cell block_mode (%d), block_type (%d)\n",
(vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode,
(vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type);
+ assert(0);
}
break;
}
-
/* Figure out the correct pgN for the new cell */
- if(set_PGN(vm)) {
+ if(!set_PGN(vm)) {
#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: last cell in this PGC\n");
#endif
return play_PGC_post(vm);
}
-
return play_Cell(vm);
}
-static link_t play_PGC_post(vm_t *vm)
-{
- link_t link_values;
-
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n");
-#endif
-
- /* FIXME Implement PGC Stills. Currently only Cell stills work */
- assert((vm->state).pgc->still_time == 0);
+/* link processing */
- /* eval -> updates the state and returns either
- - some kind of jump (Jump(TT/SS/VTS_TTN/CallSS/link C/PG/PGC/PTTN)
- - or a error (are there more cases?)
- - if you got to the end of the post_cmds, then what ?? */
- if((vm->state).pgc->command_tbl &&
- vmEval_CMD((vm->state).pgc->command_tbl->post_cmds,
- (vm->state).pgc->command_tbl->nr_of_post,
- &(vm->state).registers, &link_values)) {
- return link_values;
- }
+static int process_command(vm_t *vm, link_t link_values) {
- /* Or perhaps handle it here? */
- {
- link_t link_next_pgc = {LinkNextPGC, 0, 0, 0};
- fprintf(MSG_OUT, "libdvdnav: ** Fell of the end of the pgc, continuing in NextPGC\n");
- assert((vm->state).pgc->next_pgc_nr != 0);
- /* Should end up in the STOP_DOMAIN if next_pgc is 0. */
- return link_next_pgc;
- }
-}
-
-
-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: **** 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);
-
vm_print_current_domain_state(vm);
fprintf(MSG_OUT, "libdvdnav: Before printout ends.\n");
#endif
switch(link_values.command) {
case LinkNoLink:
- /* No Link => PlayThis */
/* BUTTON number:data1 */
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
- link_values.command = PlayThis;
- link_values.data1 = (vm->state).blockN;
- link_values.data2 = 0; /* no actual jump */
- return link_values;
-
+ return 0; /* no actual jump */
+
case LinkTopC:
/* Restart playing from the beginning of the current Cell. */
/* BUTTON number:data1 */
- fprintf(MSG_OUT, "libdvdnav: FIXME: LinkTopC. Replay current Cell\n");
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
link_values = play_Cell(vm);
@@ -1413,7 +1140,8 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* BUTTON number:data1 */
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
- (vm->state).cellN += 1; /* if cellN becomes > nr_of_cells? it is handled in play_Cell() */
+ assert((vm->state).cellN > 1);
+ (vm->state).cellN += 1;
link_values = play_Cell(vm);
break;
case LinkPrevC:
@@ -1421,17 +1149,16 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* BUTTON number:data1 */
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
- (vm->state).cellN -= 1; /* If cellN becomes < 1? it is handled in play_Cell() */
+ (vm->state).cellN -= 1;
link_values = play_Cell(vm);
break;
case LinkTopPG:
- /* Link to Top Program */
+ /* Link to Top of Program */
/* BUTTON number:data1 */
fprintf(MSG_OUT, "libdvdnav: FIXME: LinkTopPG. This should start the current PG again.\n");
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
- /* Does pgN always contain the current value? */
link_values = play_PG(vm);
break;
case LinkNextPG:
@@ -1439,8 +1166,7 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* BUTTON number:data1 */
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
- /* Does pgN always contain the current value? */
- (vm->state).pgN += 1; /* FIXME: What if pgN becomes > pgc.nr_of_programs? */
+ (vm->state).pgN += 1;
link_values = play_PG(vm);
break;
case LinkPrevPG:
@@ -1448,16 +1174,14 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* BUTTON number:data1 */
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
- /* Does pgN always contain the current value? */
assert((vm->state).pgN > 1);
- (vm->state).pgN -= 1; /* FIXME: What if pgN becomes < 1? */
+ (vm->state).pgN -= 1;
link_values = play_PG(vm);
break;
-
+
case LinkTopPGC:
/* Restart playing from beginning of current Program Chain */
/* BUTTON number:data1 */
- fprintf(MSG_OUT, "libdvdnav: FIXME: LinkTopPGC. Restart from beginning of current Program Chain\n");
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
link_values = play_PGC(vm);
@@ -1468,7 +1192,7 @@ static link_t process_command(vm_t *vm, link_t link_values)
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
assert((vm->state).pgc->next_pgc_nr != 0);
- if(set_PGC(vm, (vm->state).pgc->next_pgc_nr))
+ if(!set_PGCN(vm, (vm->state).pgc->next_pgc_nr))
assert(0);
link_values = play_PGC(vm);
break;
@@ -1478,37 +1202,38 @@ static link_t process_command(vm_t *vm, link_t link_values)
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
assert((vm->state).pgc->prev_pgc_nr != 0);
- if(set_PGC(vm, (vm->state).pgc->prev_pgc_nr))
+ if(!set_PGCN(vm, (vm->state).pgc->prev_pgc_nr))
assert(0);
link_values = play_PGC(vm);
break;
case LinkGoUpPGC:
- /* Link to GoUp??? Program Chain */
+ /* Link to GoUp Program Chain */
/* BUTTON number:data1 */
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
assert((vm->state).pgc->goup_pgc_nr != 0);
- if(set_PGC(vm, (vm->state).pgc->goup_pgc_nr))
+ if(!set_PGCN(vm, (vm->state).pgc->goup_pgc_nr))
assert(0);
link_values = play_PGC(vm);
break;
case LinkTailPGC:
- /* Link to Tail??? Program Chain */
+ /* Link to Tail of Program Chain */
/* BUTTON number:data1 */
- /* fprintf(MSG_OUT, "libdvdnav: FIXME: LinkTailPGC. What is LinkTailPGC?\n"); */
if(link_values.data1 != 0)
(vm->state).HL_BTNN_REG = link_values.data1 << 10;
link_values = play_PGC_post(vm);
break;
-
+
case LinkRSM:
{
- /* Link to Resume */
+ /* Link to Resume point */
int i;
+
/* Check and see if there is any rsm info!! */
+ assert((vm->state).rsm_vtsN);
(vm->state).domain = VTS_DOMAIN;
ifoOpenNewVTSI(vm, vm->dvd, (vm->state).rsm_vtsN);
- set_PGC(vm, (vm->state).rsm_pgcN);
+ set_PGCN(vm, (vm->state).rsm_pgcN);
/* These should never be set in SystemSpace and/or MenuSpace */
/* (vm->state).TTN_REG = rsm_tt; ?? */
@@ -1522,17 +1247,14 @@ static link_t process_command(vm_t *vm, link_t link_values)
if((vm->state).rsm_cellN == 0) {
assert((vm->state).cellN); /* Checking if this ever happens */
- /* assert( time/block/vobu is 0 ); */
(vm->state).pgN = 1;
link_values = play_PG(vm);
} else {
- /* assert( time/block/vobu is _not_ 0 ); */
- /* play_Cell_at_time */
- /* (vm->state).pgN = ?? this gets the righ value in play_Cell */
+ /* (vm->state).pgN = ?? this gets the righ value in set_PGN() below */
(vm->state).cellN = (vm->state).rsm_cellN;
link_values.command = PlayThis;
link_values.data1 = (vm->state).rsm_blockN;
- if(set_PGN(vm)) {
+ if(!set_PGN(vm)) {
/* Were at the end of the PGC, should not happen for a RSM */
assert(0);
link_values.command = LinkTailPGC;
@@ -1543,17 +1265,17 @@ static link_t process_command(vm_t *vm, link_t link_values)
break;
case LinkPGCN:
/* Link to Program Chain Number:data1 */
- if(set_PGC(vm, link_values.data1))
+ if(!set_PGCN(vm, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
case LinkPTTN:
- /* Link to Part of this Title Number:data1 */
+ /* Link to Part of current Title Number:data1 */
/* BUTTON number:data2 */
assert((vm->state).domain == VTS_DOMAIN);
if(link_values.data2 != 0)
(vm->state).HL_BTNN_REG = link_values.data2 << 10;
- if(set_VTS_PTT(vm, (vm->state).vtsN, (vm->state).VTS_TTN_REG, link_values.data1) == -1)
+ if(!set_VTS_PTT(vm, (vm->state).vtsN, (vm->state).VTS_TTN_REG, link_values.data1))
assert(0);
link_values = play_PG(vm);
break;
@@ -1585,7 +1307,7 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* Only allowed from the First Play domain(PGC) */
/* or the Video Manager domain (VMG) */
assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */
- if(set_TT(vm,link_values.data1) == -1)
+ if(!set_TT(vm, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
@@ -1594,8 +1316,7 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* Only allowed from the VTS Menu Domain(VTSM) */
/* or the Video Title Set Domain(VTS) */
assert((vm->state).domain == VTSM_DOMAIN || (vm->state).domain == VTS_DOMAIN); /* ?? */
- fprintf(MSG_OUT, "libdvdnav: FIXME: Should be able to use get_VTS_PTT here.\n");
- if(set_VTS_TT(vm,(vm->state).vtsN, link_values.data1) == -1)
+ if(!set_VTS_TT(vm, (vm->state).vtsN, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
@@ -1604,9 +1325,9 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* Only allowed from the VTS Menu Domain(VTSM) */
/* or the Video Title Set Domain(VTS) */
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)
+ if(!set_VTS_PTT(vm, (vm->state).vtsN, link_values.data1, link_values.data2))
assert(0);
- link_values = play_PGC_PG( vm, (vm->state).pgN );
+ link_values = play_PGC_PG(vm, (vm->state).pgN);
break;
case JumpSS_FP:
@@ -1614,17 +1335,16 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* Only allowed from the VTS Menu Domain(VTSM) */
/* or the Video Manager domain (VMG) */
assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == VTSM_DOMAIN); /* ?? */
- set_FP_PGC(vm);
+ if (!set_FP_PGC(vm))
+ assert(0);
link_values = play_PGC(vm);
break;
case JumpSS_VMGM_MENU:
/* Jump to Video Manger domain - Title Menu:data1 or any PGC in VMG */
/* Allowed from anywhere except the VTS Title domain */
- assert((vm->state).domain == VMGM_DOMAIN ||
- (vm->state).domain == VTSM_DOMAIN ||
- (vm->state).domain == FP_DOMAIN); /* ?? */
+ assert((vm->state).domain != VTS_DOMAIN); /* ?? */
(vm->state).domain = VMGM_DOMAIN;
- if(set_MENU(vm,link_values.data1) == -1)
+ if(!set_MENU(vm, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
@@ -1645,7 +1365,7 @@ static link_t process_command(vm_t *vm, link_t link_values)
fprintf(MSG_OUT, "libdvdnav: *******************************************************************\n");
#endif
- if(link_values.data1 !=0) {
+ if(link_values.data1 != 0) {
assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == FP_DOMAIN); /* ?? */
(vm->state).domain = VTSM_DOMAIN;
ifoOpenNewVTSI(vm, vm->dvd, link_values.data1); /* Also sets (vm->state).vtsN */
@@ -1657,59 +1377,57 @@ static link_t process_command(vm_t *vm, link_t link_values)
/* Alien or Aliens has this != 1, I think. */
/* assert(link_values.data2 == 1); */
(vm->state).VTS_TTN_REG = link_values.data2;
- if(set_MENU(vm, link_values.data3) == -1)
+ if(!set_MENU(vm, link_values.data3))
assert(0);
link_values = play_PGC(vm);
break;
case JumpSS_VMGM_PGC:
- /* get_PGC:data1 */
- assert((vm->state).domain == VMGM_DOMAIN ||
- (vm->state).domain == VTSM_DOMAIN ||
- (vm->state).domain == FP_DOMAIN); /* ?? */
+ /* set_PGCN:data1 */
+ assert((vm->state).domain != VTS_DOMAIN); /* ?? */
(vm->state).domain = VMGM_DOMAIN;
- if(set_PGC(vm,link_values.data1) == -1)
+ if(!set_PGCN(vm, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
case CallSS_FP:
- /* saveRSMinfo:data1 */
- assert((vm->state).domain == VTS_DOMAIN); /* ?? */
- /* Must be called before domain is changed */
- saveRSMinfo(vm, link_values.data1, /* We dont have block info */ 0);
+ /* set_RSMinfo:data1 */
+ assert((vm->state).domain == VTS_DOMAIN); /* ?? */
+ /* Must be called before domain is changed */
+ set_RSMinfo(vm, link_values.data1, /* We dont have block info */ 0);
set_FP_PGC(vm);
link_values = play_PGC(vm);
break;
case CallSS_VMGM_MENU:
- /* get_MENU:data1 */
- /* saveRSMinfo:data2 */
- assert((vm->state).domain == VTS_DOMAIN); /* ?? */
- /* Must be called before domain is changed */
- saveRSMinfo(vm,link_values.data2, /* We dont have block info */ 0);
+ /* set_MENU:data1 */
+ /* set_RSMinfo:data2 */
+ assert((vm->state).domain == VTS_DOMAIN); /* ?? */
+ /* Must be called before domain is changed */
+ set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0);
(vm->state).domain = VMGM_DOMAIN;
- if(set_MENU(vm,link_values.data1) == -1)
+ if(!set_MENU(vm, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
case CallSS_VTSM:
- /* get_MENU:data1 */
- /* saveRSMinfo:data2 */
- assert((vm->state).domain == VTS_DOMAIN); /* ?? */
- /* Must be called before domain is changed */
- saveRSMinfo(vm,link_values.data2, /* We dont have block info */ 0);
+ /* set_MENU:data1 */
+ /* set_RSMinfo:data2 */
+ assert((vm->state).domain == VTS_DOMAIN); /* ?? */
+ /* Must be called before domain is changed */
+ set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0);
(vm->state).domain = VTSM_DOMAIN;
- if(set_MENU(vm,link_values.data1) == -1)
+ if(!set_MENU(vm, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
case CallSS_VMGM_PGC:
- /* get_PGC:data1 */
- /* saveRSMinfo:data2 */
- assert((vm->state).domain == VTS_DOMAIN); /* ?? */
- /* Must be called before domain is changed */
- saveRSMinfo(vm,link_values.data2, /* We dont have block info */ 0);
+ /* set_PGC:data1 */
+ /* set_RSMinfo:data2 */
+ assert((vm->state).domain == VTS_DOMAIN); /* ?? */
+ /* Must be called before domain is changed */
+ set_RSMinfo(vm, link_values.data2, /* We dont have block info */ 0);
(vm->state).domain = VMGM_DOMAIN;
- if(set_PGC(vm,link_values.data1) == -1)
+ if(!set_PGCN(vm, link_values.data1))
assert(0);
link_values = play_PGC(vm);
break;
@@ -1720,134 +1438,201 @@ static link_t process_command(vm_t *vm, link_t link_values)
}
#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: After printout starts:\n");
- vm_print_current_domain_state(vm);
- fprintf(MSG_OUT, "libdvdnav: After printout ends.\n");
+ fprintf(MSG_OUT, "libdvdnav: After printout starts:\n");
+ vm_print_current_domain_state(vm);
+ fprintf(MSG_OUT, "libdvdnav: After printout ends.\n");
#endif
}
- link_values.data2 = 1; /* there was actually a jump */
- vm->badness_counter--;
- return link_values;
+ (vm->state).blockN = link_values.data1;
+ return 1;
}
-/* Searches the TT tables, to find the current TT.
- * returns the current TT.
- * returns 0 if not found.
- */
-static int get_TT(vm_t *vm, int vtsN, int vts_ttn) {
- int i;
- int tt=0;
- for(i = 1; i <= vm->vmgi->tt_srpt->nr_of_srpts; i++) {
- if( vm->vmgi->tt_srpt->title[i - 1].title_set_nr == vtsN &&
- vm->vmgi->tt_srpt->title[i - 1].vts_ttn == vts_ttn) {
- tt=i;
- break;
- }
- }
- return tt;
-}
-static int set_TT(vm_t *vm, int tt)
-{
+/* Set functions */
+
+static int set_TT(vm_t *vm, int tt) {
assert(tt <= vm->vmgi->tt_srpt->nr_of_srpts);
-
(vm->state).TTN_REG = tt;
-
return set_VTS_TT(vm, vm->vmgi->tt_srpt->title[tt - 1].title_set_nr,
vm->vmgi->tt_srpt->title[tt - 1].vts_ttn);
}
-
-static int set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn)
-{
- fprintf(MSG_OUT, "libdvdnav: get_VTS_TT called, testing!!! vtsN=%d, vts_ttn=%d\n", vtsN, vts_ttn);
+static int set_VTS_TT(vm_t *vm, int vtsN, int vts_ttn) {
return set_VTS_PTT(vm, vtsN, vts_ttn, 1);
- /* pgcN = get_ID(vm, vts_ttn); This might return -1 */
- /*
- assert(pgcN != -1);
-
- (vm->state).TTN_REG = get_TT(*vm, vtsN, vts_ttn);
- (vm->state).VTS_TTN_REG = vts_ttn;
- (vm->state).vtsN =
- */
- /* Any other registers? */
-
- /* return set_PGC(vm, pgcN); */
}
-
-static int set_VTS_PTT(vm_t *vm, int vtsN, int /* is this really */ vts_ttn, int part)
-{
+static int set_VTS_PTT(vm_t *vm, int vtsN, int vts_ttn, int part) {
int pgcN, pgN, res;
(vm->state).domain = VTS_DOMAIN;
+
if(vtsN != (vm->state).vtsN)
- ifoOpenNewVTSI(vm, vm->dvd, vtsN); /* Also sets (vm->state).vtsN */
+ ifoOpenNewVTSI(vm, vm->dvd, vtsN); /* Also sets (vm->state).vtsN */
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;
+ return 0;
}
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;
(vm->state).TT_PGCN_REG = pgcN;
- (vm->state).PTTN_REG = pgN;
-
- (vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn);
+ (vm->state).PTTN_REG = pgN;
+ (vm->state).TTN_REG = get_TT(vm, vtsN, vts_ttn);
assert( (vm->state.TTN_REG) != 0 );
(vm->state).VTS_TTN_REG = vts_ttn;
- (vm->state).vtsN = vtsN; /* Not sure about this one. We can get to it easily from TTN_REG */
+ (vm->state).vtsN = vtsN; /* Not sure about this one. We can get to it easily from TTN_REG */
/* Any other registers? */
- res = set_PGC(vm, pgcN); /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */
- (vm->state).pgN = pgN; /* Part?? */
+ res = set_PGCN(vm, pgcN); /* This clobber's state.pgN (sets it to 1), but we don't want clobbering here. */
+ (vm->state).pgN = pgN;
return res;
}
+static int set_FP_PGC(vm_t *vm) {
+ (vm->state).domain = FP_DOMAIN;
+ (vm->state).pgc = vm->vmgi->first_play_pgc;
+ return 1;
+}
-static int set_FP_PGC(vm_t *vm)
-{
- (vm->state).domain = FP_DOMAIN;
+static int set_MENU(vm_t *vm, int menu) {
+ assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == VTSM_DOMAIN);
+ return set_PGCN(vm, get_ID(vm, menu));
+}
- (vm->state).pgc = vm->vmgi->first_play_pgc;
+static int set_PGCN(vm_t *vm, int pgcN) {
+ pgcit_t *pgcit;
- return 0;
+ pgcit = get_PGCIT(vm);
+ assert(pgcit != NULL); /* ?? Make this return -1 instead */
+
+ if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) {
+#ifdef TRACE
+ fprintf(MSG_OUT, "libdvdnav: ** No such pgcN = %d\n", pgcN);
+#endif
+ return 0;
+ }
+
+ (vm->state).pgc = pgcit->pgci_srp[pgcN - 1].pgc;
+ (vm->state).pgN = 1;
+
+ if((vm->state).domain == VTS_DOMAIN)
+ (vm->state).TT_PGCN_REG = pgcN;
+
+ return 1;
}
+/* Figure out the correct pgN from the cell and update (vm->state). */
+static int set_PGN(vm_t *vm) {
+ int new_pgN = 0;
+
+ while(new_pgN < (vm->state).pgc->nr_of_programs
+ && (vm->state).cellN >= (vm->state).pgc->program_map[new_pgN])
+ new_pgN++;
+
+ if(new_pgN == (vm->state).pgc->nr_of_programs) /* We are at the last program */
+ if((vm->state).cellN > (vm->state).pgc->nr_of_cells)
+ return 0; /* We are past the last cell */
+
+ (vm->state).pgN = new_pgN;
+
+ if((vm->state).domain == VTS_DOMAIN) {
+ playback_type_t *pb_ty;
+ if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts)
+ 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;
+#if 0
+ /* TTN_REG can't be trusted to have a correct value here... */
+ vts_ptt_srpt_t *ptt_srpt = vtsi->vts_ptt_srpt;
+ assert((vm->state).VTS_TTN_REG <= ptt_srpt->nr_of_srpts);
+ 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;
+ } else {
+ /* FIXME: Handle RANDOM or SHUFFLE titles. */
+ fprintf(MSG_OUT, "libdvdnav: RANDOM or SHUFFLE titles are NOT handled yet.\n");
+ }
+ }
+ return 1;
+}
-static int set_MENU(vm_t *vm, int menu)
-{
- assert((vm->state).domain == VMGM_DOMAIN || (vm->state).domain == VTSM_DOMAIN);
- return set_PGC(vm, get_ID(vm, menu));
+/* Must be called before domain is changed (set_PGCN()) */
+static void set_RSMinfo(vm_t *vm, int cellN, int blockN) {
+ int i;
+
+ if(cellN) {
+ (vm->state).rsm_cellN = cellN;
+ (vm->state).rsm_blockN = blockN;
+ } else {
+ (vm->state).rsm_cellN = (vm->state).cellN;
+ (vm->state).rsm_blockN = blockN;
+ }
+ (vm->state).rsm_vtsN = (vm->state).vtsN;
+ (vm->state).rsm_pgcN = get_PGCN(vm);
+
+ /* assert((vm->state).rsm_pgcN == (vm->state).TT_PGCN_REG); for VTS_DOMAIN */
+
+ for(i = 0; i < 5; i++) {
+ (vm->state).rsm_regs[i] = (vm->state).registers.SPRM[4 + i];
+ }
+}
+
+
+/* Get functions */
+
+/* Searches the TT tables, to find the current TT.
+ * returns the current TT.
+ * returns 0 if not found.
+ */
+static int get_TT(vm_t *vm, int vtsN, int vts_ttn) {
+ int i;
+ int tt=0;
+
+ for(i = 1; i <= vm->vmgi->tt_srpt->nr_of_srpts; i++) {
+ if( vm->vmgi->tt_srpt->title[i - 1].title_set_nr == vtsN &&
+ vm->vmgi->tt_srpt->title[i - 1].vts_ttn == vts_ttn) {
+ tt=i;
+ break;
+ }
+ }
+ return tt;
}
/* Search for entry_id match of the PGC Category in the current VTS PGCIT table.
* Return pgcN based on entry_id match.
*/
-static int get_ID(vm_t *vm, int id)
-{
+static int get_ID(vm_t *vm, int id) {
int pgcN, i;
pgcit_t *pgcit;
/* Relies on state to get the correct pgcit. */
pgcit = get_PGCIT(vm);
assert(pgcit != NULL);
+#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: ** Searching for menu (0x%x) entry PGC\n", id);
+#endif
/* 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) == id) {
pgcN = i + 1;
+#ifdef TRACE
fprintf(MSG_OUT, "libdvdnav: Found menu.\n");
+#endif
return pgcN;
}
}
+#ifdef TRACE
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++) {
if ( (pgcit->pgci_srp[i].entry_id & 0x80) == 0x80) {
@@ -1855,42 +1640,15 @@ static int get_ID(vm_t *vm, int id)
pgcit->pgci_srp[i].entry_id & 0x7f);
}
}
- return -1; /* error */
-}
-
-/* Set the vm->state to pgcN.
- * Returns success/failure.
- */
-static int set_PGC(vm_t *vm, int pgcN)
-{
- /* FIXME: Keep this up to date with the ogle people */
- pgcit_t *pgcit;
-
- pgcit = get_PGCIT(vm);
-
- 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);
- return -1; /* error */
- }
-
- /* (vm->state).pgcN = pgcN; */
- (vm->state).pgc = pgcit->pgci_srp[pgcN - 1].pgc;
- (vm->state).pgN = 1;
-
- if((vm->state).domain == VTS_DOMAIN)
- (vm->state).TT_PGCN_REG = pgcN;
-
- return 0;
+#endif
+ return 0; /* error */
}
-static int get_PGCN(vm_t *vm)
-{
+static int get_PGCN(vm_t *vm) {
pgcit_t *pgcit;
int pgcN = 1;
pgcit = get_PGCIT(vm);
-
assert(pgcit != NULL);
while(pgcN <= pgcit->nr_of_pgci_srp) {
@@ -1898,99 +1656,13 @@ static int get_PGCN(vm_t *vm)
return pgcN;
pgcN++;
}
- fprintf(MSG_OUT, "libdvdnav: get_PGCN failed. Trying to find pgcN in domain %d \n",
+ fprintf(MSG_OUT, "libdvdnav: get_PGCN failed. Was trying to find pgcN in domain %d\n",
(vm->state).domain);
/* assert(0);*/
- return -1; /* error */
-}
-
-int vm_get_video_aspect(vm_t *vm)
-{
- int aspect = 0;
-
- switch ((vm->state).domain) {
- case VTS_DOMAIN:
- aspect = vm->vtsi->vtsi_mat->vts_video_attr.display_aspect_ratio;
- break;
- case VTSM_DOMAIN:
- aspect = vm->vtsi->vtsi_mat->vtsm_video_attr.display_aspect_ratio;
- break;
- case VMGM_DOMAIN:
- aspect = vm->vmgi->vmgi_mat->vmgm_video_attr.display_aspect_ratio;
- break;
- default:
- fprintf(MSG_OUT, "libdvdnav: vm_get_video_aspect failed. Unknown domain %d\n",
- (vm->state).domain);
- assert(0);
- break;
- }
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: get_video_aspect:aspect=%d\n",aspect);
-#endif
- assert(aspect == 0 || aspect == 3);
- (vm->state).registers.SPRM[14] &= ~(0x3 << 10);
- (vm->state).registers.SPRM[14] |= aspect << 10;
-
- return aspect;
-}
-
-int vm_get_video_scale_permission(vm_t *vm)
-{
- int permission = 0;
-
- if((vm->state).domain == VTS_DOMAIN) {
- permission = vm->vtsi->vtsi_mat->vts_video_attr.permitted_df;
- } else if((vm->state).domain == VTSM_DOMAIN) {
- permission = vm->vtsi->vtsi_mat->vtsm_video_attr.permitted_df;
- } else if((vm->state).domain == VMGM_DOMAIN) {
- permission = vm->vmgi->vmgi_mat->vmgm_video_attr.permitted_df;
- }
-#ifdef TRACE
- fprintf(MSG_OUT, "libdvdnav: get_video_scale_permission:permission=%d\n",permission);
-#endif
-
- return permission;
-}
-
-static void ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN)
-{
- if((vm->state).vtsN == vtsN) {
- return; /* We alread have it */
- }
-
- if(vm->vtsi != NULL)
- ifoClose(vm->vtsi);
-
- vm->vtsi = ifoOpenVTSI(dvd, vtsN);
- if(vm->vtsi == NULL) {
- fprintf(MSG_OUT, "libdvdnav: ifoOpenVTSI failed - CRASHING!!!\n");
- assert(0);
- }
- if(!ifoRead_VTS_PTT_SRPT(vm->vtsi)) {
- fprintf(MSG_OUT, "libdvdnav: ifoRead_VTS_PTT_SRPT failed - CRASHING!!!\n");
- assert(0);
- }
- if(!ifoRead_PGCIT(vm->vtsi)) {
- fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCIT failed - CRASHING!!!\n");
- assert(0);
- }
- if(!ifoRead_PGCI_UT(vm->vtsi)) {
- fprintf(MSG_OUT, "libdvdnav: ifoRead_PGCI_UT failed - CRASHING!!!\n");
- assert(0);
- }
- if(!ifoRead_VOBU_ADMAP(vm->vtsi)) {
- fprintf(MSG_OUT, "libdvdnav: ifoRead_VOBU_ADMAP vtsi failed - CRASHING\n");
- assert(0);
- }
- if(!ifoRead_TITLE_VOBU_ADMAP(vm->vtsi)) {
- fprintf(MSG_OUT, "libdvdnav: ifoRead_TITLE_VOBU_ADMAP vtsi failed - CRASHING\n");
- assert(0);
- }
- (vm->state).vtsN = vtsN;
+ return 0; /* error */
}
-static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang)
-{
+static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang) {
int i;
if(h == NULL || h->pgci_ut == NULL) {
@@ -2008,13 +1680,12 @@ static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang)
(char)(h->pgci_ut->lu[0].lang_code >> 8),
(char)(h->pgci_ut->lu[0].lang_code & 0xff));
fprintf(MSG_OUT, "libdvdnav: Menu Languages available: ");
- for(i=0;i< h->pgci_ut->nr_of_lus;i++) {
+ for(i = 0; i < h->pgci_ut->nr_of_lus; i++) {
fprintf(MSG_OUT, "%c%c ",
- (char)(h->pgci_ut->lu[0].lang_code >> 8),
- (char)(h->pgci_ut->lu[0].lang_code & 0xff));
+ (char)(h->pgci_ut->lu[i].lang_code >> 8),
+ (char)(h->pgci_ut->lu[i].lang_code & 0xff));
}
fprintf(MSG_OUT, "\n");
-
i = 0; /* error? */
}
@@ -2047,8 +1718,40 @@ static pgcit_t* get_PGCIT(vm_t *vm) {
return pgcit;
}
+
+/* Debug functions */
+
+#ifdef TRACE
+void vm_position_print(vm_t *vm, vm_position_t *position) {
+ fprintf(MSG_OUT, "libdvdnav: But=%x Spu=%x Aud=%x Ang=%x Hop=%x vts=%x dom=%x cell=%x cell_restart=%x cell_start=%x still=%x block=%x\n",
+ position->button,
+ position->spu_channel,
+ position->audio_channel,
+ position->angle_channel,
+ position->hop_channel,
+ position->vts,
+ position->domain,
+ position->cell,
+ position->cell_restart,
+ position->cell_start,
+ position->still,
+ position->block);
+}
+#endif
+
+
/*
* $Log: vm.c,v $
+ * Revision 1.13 2003/02/20 16:02:01 mroi
+ * syncing to libdvdnav 0.1.5 and modifying input plugin accordingly
+ * quoting the ChangeLog:
+ * * some bugfixes
+ * * code cleanup
+ * * build process polishing
+ * * more sensible event order in get_next_block to ensure useful event delivery
+ * * VOBU level resume
+ * * fixed: seeking in a multiangle feature briefly showed the wrong angle
+ *
* Revision 1.12 2003/02/11 16:28:47 heikos
* freebsd compile fix
*
diff --git a/src/input/libdvdnav/vm.h b/src/input/libdvdnav/vm.h
index e4c6f1863..9b1f0cfc8 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.3 2002/09/20 12:53:53 mroi Exp $
+ * $Id: vm.h,v 1.4 2003/02/20 16:02:01 mroi Exp $
*
*/
@@ -33,8 +33,8 @@
/* DOMAIN enum */
typedef enum {
- FP_DOMAIN = 1,
- VTS_DOMAIN = 2,
+ FP_DOMAIN = 1,
+ VTS_DOMAIN = 2,
VMGM_DOMAIN = 4,
VTSM_DOMAIN = 8
} domain_t;
@@ -45,40 +45,37 @@ typedef enum {
typedef struct {
registers_t registers;
- pgc_t *pgc; /* either this or *pgc is enough? */
-
- domain_t domain;
- int vtsN; /* 0 is vmgm? */
- /* int pgcN; // either this or *pgc is enough. Which to use? */
- int pgN; /* is this needed? can allways fid pgN from cellN? */
- int cellN;
- int32_t cell_restart; /* get cell to restart */
- int blockN;
+ domain_t domain;
+ int vtsN; /* 0 is vmgm? */
+ pgc_t *pgc; /* either this or 'int pgcN' is enough? */
+ int pgN; /* is this needed? can allways fid pgN from cellN? */
+ int cellN;
+ int32_t cell_restart; /* get cell to restart */
+ int blockN;
/* Resume info */
- int rsm_vtsN;
- int rsm_blockN; /* of nav_packet */
- uint16_t rsm_regs[5]; /* system registers 4-8 */
- int rsm_pgcN;
- int rsm_cellN;
+ int rsm_vtsN;
+ int rsm_blockN; /* of nav_packet */
+ uint16_t rsm_regs[5]; /* system registers 4-8 */
+ int rsm_pgcN;
+ int rsm_cellN;
} dvd_state_t;
typedef struct vm_position_s {
- int16_t button; /* Button highlighted */
- uint32_t clut; /* CLUT to use, not needed in this struct */
- int32_t vts; /* vts number to use */
- int32_t domain; /* domain to use */
- int32_t spu_channel; /* spu channel to use */
- int32_t angle_channel; /* angle channel to use */
- int32_t audio_channel; /* audio channel to use */
- int32_t hop_channel; /* channel hopping. E.g menu button pressed */
- int32_t title; /* title number */
- int32_t chapter; /* chapter number */
- int32_t cell; /* cell number */
- int32_t cell_restart; /* get cell to restart */
- int32_t still; /* is cell still */
- int32_t vobu_start; /* block number of start of current VOBU in use */
- int32_t vobu_next; /* block number within VOBU in use */
+ int16_t button; /* Button highlighted */
+ int32_t vts; /* vts number to use */
+ int32_t domain; /* domain to use */
+ int32_t spu_channel; /* spu channel to use */
+ int32_t angle_channel; /* angle channel to use */
+ int32_t audio_channel; /* audio channel to use */
+ int32_t hop_channel; /* channel hopping. E.g menu button pressed */
+ int32_t title; /* title number */
+ int32_t chapter; /* chapter number */
+ int32_t cell; /* cell number */
+ int32_t cell_restart; /* get cell to restart */
+ int32_t cell_start; /* sector number of start of current cell in use */
+ int32_t still; /* is cell still */
+ int32_t block; /* block number within cell in use */
} vm_position_t;
typedef struct {
@@ -86,13 +83,15 @@ typedef struct {
ifo_handle_t *vmgi;
ifo_handle_t *vtsi;
dvd_state_t state;
- int badness_counter;
- int32_t hop_channel;
- char dvd_name[50];
- int dvd_name_length;
- remap_t *map;
+ int32_t hop_channel;
+ char dvd_name[50];
+ remap_t *map;
+ int stopped;
} vm_t;
+/* magic number for seeking hops */
+#define HOP_SEEK 0x1000
+
/* Audio stream number */
#define AST_REG registers.SPRM[1]
@@ -115,7 +114,7 @@ typedef struct {
/* Initialisation & destruction */
vm_t* vm_new_vm();
-void vm_free_vm(vm_t *vm);
+void vm_free_vm(vm_t *vm);
/* IFO access */
ifo_handle_t *vm_get_vmgi(vm_t *vm);
@@ -124,38 +123,48 @@ ifo_handle_t *vm_get_vtsi(vm_t *vm);
/* Reader Access */
dvd_reader_t *vm_get_dvd_reader(vm_t *vm);
-/* Jumping */
-int vm_start_title(vm_t *vm, int tt);
-int vm_jump_prog(vm_t *vm, int pr);
-int vm_jump_title_part(vm_t *vm, int title, int part);
+/* Basic Handling */
+void vm_start(vm_t *vm);
+void vm_stop(vm_t *vm);
+int vm_reset(vm_t *vm, const char *dvdroot);
+
+/* regular playback */
+void vm_position_get(vm_t *vm, vm_position_t *position);
+void vm_get_next_cell(vm_t *vm);
-/* Other calls */
-int vm_reset(vm_t *vm, char *dvdroot); /* , register_t regs); */
-int vm_start(vm_t *vm);
-int vm_position_get(vm_t *vm, vm_position_t *position);
-int vm_position_print(vm_t *vm, vm_position_t *position);
-int vm_eval_cmd(vm_t *vm, vm_cmd_t *cmd);
-int vm_get_next_cell(vm_t *vm);
-int vm_menu_call(vm_t *vm, DVDMenuID_t menuid, int block);
-int vm_resume(vm_t *vm);
-int vm_go_up(vm_t *vm);
-int vm_top_pg(vm_t *vm);
-int vm_next_pg(vm_t *vm);
-int vm_prev_pg(vm_t *vm);
+/* Jumping - all these return 1, if a hop has been performed */
+int vm_jump_pg(vm_t *vm, int pg);
+int vm_jump_title_part(vm_t *vm, int title, int part);
+int vm_jump_top_pg(vm_t *vm);
+int vm_jump_next_pg(vm_t *vm);
+int vm_jump_prev_pg(vm_t *vm);
+int vm_jump_up(vm_t *vm);
+int vm_jump_menu(vm_t *vm, DVDMenuID_t menuid);
+int vm_exec_cmd(vm_t *vm, vm_cmd_t *cmd);
+
+/* getting information */
+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 vm_get_audio_active_stream(vm_t *vm);
int vm_get_subp_stream(vm_t *vm, int subpN, int mode);
+int vm_get_audio_active_stream(vm_t *vm);
int vm_get_subp_active_stream(vm_t *vm, int mode);
-void vm_get_angle_info(vm_t *vm, int *num_avail, int *current);
-void vm_get_audio_info(vm_t *vm, int *num_avail, int *current);
-void vm_get_subp_info(vm_t *vm, int *num_avail, int *current);
-int vm_get_current_title_part(vm_t *vm, int *title_result, int *part_result);
-
-subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN);
-audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN);
+void vm_get_angle_info(vm_t *vm, int *current, int *num_avail);
+#if 0
+/* currently unused */
+void vm_get_audio_info(vm_t *vm, int *current, int *num_avail);
+void vm_get_subp_info(vm_t *vm, int *current, int *num_avail);
void vm_get_video_res(vm_t *vm, int *width, int *height);
-int vm_get_video_aspect(vm_t *vm);
-int vm_get_video_scale_permission(vm_t *vm);
+#endif
+int vm_get_video_aspect(vm_t *vm);
+int vm_get_video_scale_permission(vm_t *vm);
+video_attr_t vm_get_video_attr(vm_t *vm);
+audio_attr_t vm_get_audio_attr(vm_t *vm, int streamN);
+subp_attr_t vm_get_subp_attr(vm_t *vm, int streamN);
+
+#ifdef TRACE
+/* Debug */
+void vm_position_print(vm_t *vm, vm_position_t *position);
+#endif
-#endif /* VM_HV_INCLUDED */
+#endif /* VM_HV_INCLUDED */
diff --git a/src/input/libdvdnav/vmcmd.c b/src/input/libdvdnav/vmcmd.c
index 28b2c5ab3..7dd98fc20 100644
--- a/src/input/libdvdnav/vmcmd.c
+++ b/src/input/libdvdnav/vmcmd.c
@@ -18,7 +18,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: vmcmd.c,v 1.2 2002/08/27 19:24:33 mroi Exp $
+ * $Id: vmcmd.c,v 1.3 2003/02/20 16:02:01 mroi Exp $
*
*/
@@ -35,6 +35,8 @@
#include "dvdnav_internal.h"
+#ifdef TRACE
+
/* freebsd compatibility */
#ifndef PRIu8
#define PRIu8 "d"
@@ -486,4 +488,4 @@ void vmPrint_CMD(int row, vm_cmd_t *vm_command) {
fprintf(MSG_OUT, "\n");
}
-
+#endif
diff --git a/src/input/libdvdnav/vmcmd.h b/src/input/libdvdnav/vmcmd.h
index 662cf0b46..eb862d421 100644
--- a/src/input/libdvdnav/vmcmd.h
+++ b/src/input/libdvdnav/vmcmd.h
@@ -18,7 +18,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: vmcmd.h,v 1.3 2002/08/09 22:52:14 mroi Exp $
+ * $Id: vmcmd.h,v 1.4 2003/02/20 16:02:01 mroi Exp $
*
*/
@@ -29,7 +29,9 @@
#include "ifo_types.h" /* Only for vm_cmd_t */
#include "decoder.h"
+#ifdef TRACE
void vmPrint_mnemonic(vm_cmd_t *command);
void vmPrint_CMD(int row, vm_cmd_t *command);
+#endif
#endif /* VMCMD_H_INCLUDED */