--- a/src/navigation.c
+++ b/src/navigation.c
@@ -1,196 +1,170 @@
-/*
+/* 
  * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net>
- *
+ * 
  * 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
  *
- * You should have received a copy of the GNU General Public License along
- * with libdvdnav; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * $Id$
+ *
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
-#include <inttypes.h>
-#include <limits.h>
-#include <string.h>
-#include <sys/time.h>
-#include "dvdnav/dvdnav.h"
-#include <dvdread/nav_types.h>
-#include <dvdread/ifo_types.h>
-#include "remap.h"
-#include "vm/decoder.h"
-#include "vm/vm.h"
+#include <dvdnav.h>
 #include "dvdnav_internal.h"
+
+#include "vm.h"
 
 /* Navigation API calls */
 
-dvdnav_status_t dvdnav_still_skip(dvdnav_t *this) {
-  pthread_mutex_lock(&this->vm_lock);
-  this->position_current.still = 0;
-  pthread_mutex_unlock(&this->vm_lock);
-  this->skip_still = 1;
-  this->sync_wait = 0;
-  this->sync_wait_skip = 1;
+/* Common things we do everytime we do a jump */
+void dvdnav_do_post_jump(dvdnav_t *self) {
+  dvd_state_t *state = &(self->vm->state);
+  cell_playback_t *cell = &(state->pgc->cell_playback[state->cellN - 1]);
 
-  return DVDNAV_STATUS_OK;
+  self->jmp_blockN = 0; /* FIXME: Should this be different? */
+  self->jmp_vobu_start = cell->first_sector;
+  self->jumping = 1;
+  self->still_frame = -1;
 }
 
-dvdnav_status_t dvdnav_wait_skip(dvdnav_t *this) {
-  this->sync_wait = 0;
-  this->sync_wait_skip = 1;
+dvdnav_status_t dvdnav_still_skip(dvdnav_t *self) {
+  if(!self)
+   return S_ERR;
 
-  return DVDNAV_STATUS_OK;
+  self->still_frame = -1;
+
+  return S_OK;
 }
 
-dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *this, int32_t *titles) {
-  if (!this->vm->vmgi) {
-    printerr("Bad VM state.");
-    return DVDNAV_STATUS_ERR;
+dvdnav_status_t dvdnav_get_number_of_titles(dvdnav_t *self, int *titles) {
+  if(!self)
+   return S_ERR;
+
+  if(!titles) {
+    printerr("Passed a NULL pointer");
+    return S_ERR;
   }
 
-  (*titles) = vm_get_vmgi(this->vm)->tt_srpt->nr_of_srpts;
+  (*titles) = vm_get_vmgi(self->vm)->tt_srpt->nr_of_srpts;
 
-  return DVDNAV_STATUS_OK;
+  return S_OK;
 }
 
-dvdnav_status_t dvdnav_get_number_of_parts(dvdnav_t *this, int32_t title, int32_t *parts) {
-  if (!this->vm->vmgi) {
-    printerr("Bad VM state.");
-    return DVDNAV_STATUS_ERR;
-  }
-  if ((title < 1) || (title > vm_get_vmgi(this->vm)->tt_srpt->nr_of_srpts) ) {
-    printerr("Passed a title number out of range.");
-    return DVDNAV_STATUS_ERR;
+dvdnav_status_t dvdnav_title_play(dvdnav_t *self, int title) {
+  int num_titles;
+
+  if(!self) {
+    return S_ERR;
   }
 
-  (*parts) = vm_get_vmgi(this->vm)->tt_srpt->title[title-1].nr_of_ptts;
+  /* Check number of titles */
+  dvdnav_get_number_of_titles(self, &num_titles);
+  if((title > num_titles) || (title <= 0)) {
+    printerrf("Invalid title passed (%i, maximum %i)", title,
+	      num_titles);
+    return S_ERR;
+  }
+  
+  vm_start_title(self->vm, title);
 
-  return DVDNAV_STATUS_OK;
+  /* self->expecting_nav_packet = 1; */
+
+  dvdnav_do_post_jump(self);
+
+  return S_OK;
 }
 
-dvdnav_status_t dvdnav_current_title_info(dvdnav_t *this, int32_t *title, int32_t *part) {
-  int32_t retval;
+dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int title, int part) {
+  int num_titles, num_progs;
 
-  pthread_mutex_lock(&this->vm_lock);
-  if (!this->vm->vtsi || !this->vm->vmgi) {
-    printerr("Bad VM state.");
-    pthread_mutex_unlock(&this->vm_lock);
-    return DVDNAV_STATUS_ERR;
+  if(!self) {
+    return S_ERR;
   }
-  if (!this->started) {
-    printerr("Virtual DVD machine not started.");
-    pthread_mutex_unlock(&this->vm_lock);
-    return DVDNAV_STATUS_ERR;
+
+  /* Check number of titles */
+  dvdnav_get_number_of_titles(self, &num_titles);
+  if((title > num_titles) || (title <= 0)) {
+    printerrf("Invalid title passed (%i, maximum %i)", title,
+	      num_titles);
+    return S_ERR;
   }
-  if (!this->vm->state.pgc) {
-    printerr("No current PGC.");
-    pthread_mutex_unlock(&this->vm_lock);
-    return DVDNAV_STATUS_ERR;
+ 
+  vm_start_title(self->vm, title);
+
+
+  /* Check number of parts */
+  num_progs = self->vm->state.pgc->nr_of_programs;
+  if((part > num_progs) || (part <= 0)) {
+    printerrf("Invalid program passed (%i, maximum %i)", part,
+	      num_progs);
+    return S_ERR;
   }
-  if ( (this->vm->state.domain == VTSM_DOMAIN)
-      || (this->vm->state.domain == VMGM_DOMAIN) ) {
-    /* Get current Menu ID: into *part. */
-    if(! vm_get_current_menu(this->vm, part)) {
-      pthread_mutex_unlock(&this->vm_lock);
-      return DVDNAV_STATUS_ERR;
-    }
-    if (*part > -1) {
-      *title = 0;
-      pthread_mutex_unlock(&this->vm_lock);
-      return DVDNAV_STATUS_OK;
-    }
-  }
-  if (this->vm->state.domain == VTS_DOMAIN) {
-    retval = vm_get_current_title_part(this->vm, title, part);
-    pthread_mutex_unlock(&this->vm_lock);
-    return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR;
-  }
-  printerr("Not in a title or menu.");
-  pthread_mutex_unlock(&this->vm_lock);
-  return DVDNAV_STATUS_ERR;
+   
+  vm_jump_prog(self->vm, part);
+  
+   /* self->expecting_nav_packet = 1; */
+
+  dvdnav_do_post_jump(self);
+
+  return S_OK;
 }
 
-dvdnav_status_t dvdnav_title_play(dvdnav_t *this, int32_t title) {
-  return dvdnav_part_play(this, title, 1);
+dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *self, int title,
+					  int part, int parts_to_play) {
+  /* Perform jump as per usual */
+
+  return dvdnav_part_play(self, title, part);
+  
+  /* FIXME: Impement auto-stop */
+  
+  /* return S_OK;*/ 
 }
 
-dvdnav_status_t dvdnav_part_play(dvdnav_t *this, int32_t title, int32_t part) {
-  int32_t retval;
-
-  pthread_mutex_lock(&this->vm_lock);
-  if (!this->vm->vmgi) {
-    printerr("Bad VM state.");
-    pthread_mutex_unlock(&this->vm_lock);
-    return DVDNAV_STATUS_ERR;
-  }
-  if (!this->started) {
-    /* don't report an error but be nice */
-    vm_start(this->vm);
-    this->started = 1;
-  }
-  if (!this->vm->state.pgc) {
-    printerr("No current PGC.");
-    pthread_mutex_unlock(&this->vm_lock);
-    return DVDNAV_STATUS_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 DVDNAV_STATUS_ERR;
-  }
-  if((part < 1) || (part > this->vm->vmgi->tt_srpt->title[title-1].nr_of_ptts)) {
-    printerr("Part out of range.");
-    pthread_mutex_unlock(&this->vm_lock);
-    return DVDNAV_STATUS_ERR;
-  }
-
-  retval = vm_jump_title_part(this->vm, title, part);
-  if (retval)
-    this->vm->hop_channel++;
-  pthread_mutex_unlock(&this->vm_lock);
-
-  return retval ? DVDNAV_STATUS_OK : DVDNAV_STATUS_ERR;
+dvdnav_status_t dvdnav_time_play(dvdnav_t *self, int title,
+				unsigned long int time) {
+  /* FIXME: Implement */
+  
+  return S_OK;
 }
 
-dvdnav_status_t dvdnav_part_play_auto_stop(dvdnav_t *this, int32_t title,
-					   int32_t part, int32_t parts_to_play) {
-  /* FIXME: Implement auto-stop */
- if (dvdnav_part_play(this, title, part) == DVDNAV_STATUS_OK)
-   printerr("Not implemented yet.");
- return DVDNAV_STATUS_ERR;
+dvdnav_status_t dvdnav_stop(dvdnav_t *self) {
+  if(!self)
+   return S_ERR;
+
+  /* Set the STOP flag */
+  
+  self->stop = 1;
+  
+  return S_OK;
 }
 
-dvdnav_status_t dvdnav_time_play(dvdnav_t *this, int32_t title,
-				 uint64_t time) {
-  /* FIXME: Implement */
-  printerr("Not implemented yet.");
-  return DVDNAV_STATUS_ERR;
+dvdnav_status_t dvdnav_go_up(dvdnav_t *self) {
+  if(!self)
+   return S_ERR;
+
+  /* A nice easy function... delegate to the VM */
+  vm_go_up(self->vm);
+
+  dvdnav_do_post_jump(self);
+
+  return S_OK;
 }
 
-dvdnav_status_t dvdnav_stop(dvdnav_t *this) {
-  pthread_mutex_lock(&this->vm_lock);
-  this->vm->stopped = 1;
-  pthread_mutex_unlock(&this->vm_lock);
-  return DVDNAV_STATUS_OK;
-}
 
-dvdnav_status_t dvdnav_go_up(dvdnav_t *this) {
-  /* A nice easy function... delegate to the VM */
-  pthread_mutex_lock(&this->vm_lock);
-  vm_jump_up(this->vm);
-  pthread_mutex_unlock(&this->vm_lock);
 
-  return DVDNAV_STATUS_OK;
-}