--- gstteletextdec.h.org	2011-12-05 15:32:35.000000000 +0100
+++ gstteletextdec.h	2011-12-15 13:03:02.772491508 +0100
@@ -49,6 +49,15 @@
   GST_TELETEXTDEC_OUTPUT_FORMAT_PANGO
 };
 
+enum _GstTeletextNavigation
+{
+	GST_TELETEXTDEC_NAVIGATE_PAGE_NEXT,
+	GST_TELETEXTDEC_NAVIGATE_PAGE_PREV,
+
+	GST_TELETEXTDEC_NAVIGATE_SUBPAGE_NEXT,
+	GST_TELETEXTDEC_NAVIGATE_SUBPAGE_PREV
+};
+
 typedef void (*GstTeletextProcessBufferFunc) (GstTeletextDec *
     teletext, GstBuffer * buf);
 
@@ -67,6 +76,7 @@
   /* Props */
   gint pageno;
   gint subno;
+  gint subact;
   gboolean subtitles_mode;
   gchar *subtitles_template;
   gchar *font_description;

--- gstteletextdec.c.org	2011-12-05 15:32:35.000000000 +0100
+++ gstteletextdec.c	2011-12-15 13:07:32.745833539 +0100
@@ -63,7 +63,8 @@
   PROP_SUBNO,
   PROP_SUBTITLES_MODE,
   PROP_SUBS_TEMPLATE,
-  PROP_FONT_DESCRIPTION
+  PROP_FONT_DESCRIPTION,
+  PROP_NAVIGATE
 };
 
 enum
@@ -182,6 +183,9 @@
 static void gst_teletextdec_zvbi_init (GstTeletextDec * teletext);
 static void gst_teletextdec_zvbi_clear (GstTeletextDec * teletext);
 
+static void gst_teletextdec_update (GstTeletextDec * teletext);
+static void gst_teletextdec_navigate (GstTeletextDec * teletext, int mode);
+
 /* GObject vmethod implementations */
 
 static void
@@ -244,6 +248,11 @@
           "Font description used for the pango output.",
           DEFAULT_FONT_DESCRIPTION,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_NAVIGATE,
+      g_param_spec_int ("navigate", "page navigation",
+          "Navigate through the page cache.\n\n\t\t\t\t0: show next cached page\n\t\t\t\t1: show prev cached page\n\t\t\t\t2: show next cached subpage\n\t\t\t\t3: show prev cached subpage\n",
+          GST_TELETEXTDEC_NAVIGATE_PAGE_NEXT, GST_TELETEXTDEC_NAVIGATE_SUBPAGE_PREV, GST_TELETEXTDEC_NAVIGATE_PAGE_NEXT, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
 }
 
 /* initialize the new element
@@ -366,9 +375,14 @@
   switch (prop_id) {
     case PROP_PAGENO:
       teletext->pageno = (gint) vbi_bin2bcd (g_value_get_int (value));
+      teletext->subno = -1;
+      // fixme: how to force a instant (gst_teletextdec_update takes 3 seconds!?) page update here
+      gst_teletextdec_update (teletext);
       break;
     case PROP_SUBNO:
       teletext->subno = g_value_get_int (value);
+      // fixme: how to force a instant (gst_teletextdec_update takes 3 seconds!?) page update here
+      gst_teletextdec_update (teletext);
       break;
     case PROP_SUBTITLES_MODE:
       teletext->subtitles_mode = g_value_get_boolean (value);
@@ -379,6 +393,9 @@
     case PROP_FONT_DESCRIPTION:
       teletext->font_description = g_value_dup_string (value);
       break;
+    case PROP_NAVIGATE:
+      gst_teletextdec_navigate (teletext, g_value_get_int (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -694,6 +711,8 @@
       pi->pgno = pgno;
       pi->subno = subno;
 
+      teletext->subact = subno & 0xFF;
+
       g_mutex_lock (teletext->queue_lock);
       g_queue_push_tail (teletext->queue, pi);
       g_mutex_unlock (teletext->queue_lock);
@@ -1237,3 +1256,136 @@
   }
   return VBI_SUCCESS;
 }
+
+/* page navigation functions */
+
+void gst_teletextdec_update (GstTeletextDec * teletext)
+{
+	GstFlowReturn ret = GST_FLOW_OK;
+	GstBuffer *buf;
+	vbi_page page;
+
+	if (vbi_fetch_vt_page (teletext->decoder, &page, teletext->pageno, teletext->subno == -1 ? VBI_ANY_SUBNO : teletext->subno, VBI_WST_LEVEL_3p5, 25, FALSE))
+	{
+		switch (teletext->output_format)
+		{
+			case GST_TELETEXTDEC_OUTPUT_FORMAT_TEXT:
+				ret = gst_teletextdec_export_text_page (teletext, &page, &buf);
+				break;
+
+			case GST_TELETEXTDEC_OUTPUT_FORMAT_HTML:
+				ret = gst_teletextdec_export_html_page (teletext, &page, &buf);
+				break;
+
+			case GST_TELETEXTDEC_OUTPUT_FORMAT_RGBA:
+				ret = gst_teletextdec_export_rgba_page (teletext, &page, &buf);
+				break;
+
+			case GST_TELETEXTDEC_OUTPUT_FORMAT_PANGO:
+				ret = gst_teletextdec_export_pango_page (teletext, &page, &buf);
+				break;
+
+			default:
+				return;
+		}
+
+		teletext->subact = page.subno & 0xFF;
+
+		GST_INFO_OBJECT (teletext, "update page: %.3x.%.2x", page.pgno, page.subno & 0xFF);
+
+		vbi_unref_page (&page);
+
+		if (ret == GST_FLOW_OK)
+		{
+			GST_BUFFER_TIMESTAMP (buf) = teletext->in_timestamp;
+			GST_BUFFER_DURATION (buf) = teletext->in_duration;
+
+			gst_pad_push (teletext->srcpad, buf);
+		}
+	}
+	else
+	{
+		GST_INFO_OBJECT (teletext, "update page: %.3x.%.2x not cached", teletext->pageno, teletext->subno == -1 ? 0 : teletext->subno);
+	}
+}
+
+void gst_teletextdec_navigate (GstTeletextDec * teletext, int mode)
+{
+	int scan;
+
+	switch(mode)
+	{
+		case GST_TELETEXTDEC_NAVIGATE_PAGE_NEXT:
+		case GST_TELETEXTDEC_NAVIGATE_PAGE_PREV:
+
+			scan = teletext->pageno;
+
+			do
+			{
+				(mode == GST_TELETEXTDEC_NAVIGATE_PAGE_NEXT) ? (scan == 0x899 ? scan = 0x100 : scan++) : (scan == 0x100 ? scan = 0x899 : scan--);
+
+				if (vbi_is_bcd(scan))
+				{
+					if (vbi_is_cached(teletext->decoder, scan, VBI_ANY_SUBNO))
+					{
+						break;
+					}
+				}
+
+			}while (scan != teletext->pageno);
+
+			if (teletext->pageno == scan)
+			{
+				GST_INFO_OBJECT (teletext, "navigate (%s page): nothing cached", mode == GST_TELETEXTDEC_NAVIGATE_PAGE_PREV ? "prev" : "next");
+				return;
+			}
+			else
+			{
+				teletext->pageno = scan;
+				teletext->subno = -1;//VBI_ANY_SUBNO;
+
+				GST_INFO_OBJECT (teletext, "navigate (%s page): %.3x", mode == GST_TELETEXTDEC_NAVIGATE_PAGE_PREV ? "prev" : "next", teletext->pageno);
+			}
+
+			break;
+
+		case GST_TELETEXTDEC_NAVIGATE_SUBPAGE_NEXT:
+		case GST_TELETEXTDEC_NAVIGATE_SUBPAGE_PREV:
+
+			if (!teletext->subact)
+			{
+				GST_INFO_OBJECT (teletext, "navigate (%s subpage): no subpages for page %.3x", mode == GST_TELETEXTDEC_NAVIGATE_SUBPAGE_PREV ? "prev" : "next", teletext->pageno);
+				return;
+			}
+
+			scan = teletext->subact;
+
+			do
+			{
+				(mode == GST_TELETEXTDEC_NAVIGATE_SUBPAGE_NEXT) ? (scan == 0x01 ? scan = 0x99 : scan--) : (scan == 0x99 ? scan = 0x01 : scan++);
+
+				if (vbi_is_cached(teletext->decoder, teletext->pageno, scan))
+				{
+					break;
+				}
+
+			}while(scan != teletext->subact);
+
+			if (teletext->subact == scan)
+			{
+				GST_INFO_OBJECT (teletext, "navigate (%s subpage): no other subpages for page %.3x", mode == GST_TELETEXTDEC_NAVIGATE_SUBPAGE_PREV ? "prev" : "next", teletext->pageno);
+				return;
+			}
+			else
+			{
+				teletext->subno = scan;
+
+				GST_INFO_OBJECT (teletext, "navigate (%s subpage): %.3x.%.2x", mode == GST_TELETEXTDEC_NAVIGATE_SUBPAGE_PREV ? "prev" : "next", teletext->pageno, teletext->subno);
+			}
+
+			break;
+	}
+
+	// fixme: how to force a instant (gst_teletextdec_update takes 3 seconds!?) page update here
+	gst_teletextdec_update (teletext);
+}
