[SCM] libbluray/master: Fix bad merge.

ceros-guest at users.alioth.debian.org ceros-guest at users.alioth.debian.org
Mon Jul 18 01:13:19 UTC 2011


The following commit has been merged in the master branch:
commit 927a9577a87a9a49488a88e1db9b050986cabfb8
Author: Andres Mejia <mcitadel at gmail.com>
Date:   Sun Jul 17 21:09:40 2011 -0400

    Fix bad merge.

diff --git a/build-aux/config.guess b/build-aux/config.guess
index c2246a4..40eaed4 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-#   Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011 Free Software Foundation, Inc.
 
-timestamp='2009-12-30'
+timestamp='2011-05-11'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -57,7 +57,7 @@ GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
 Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -181,7 +181,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		fi
 		;;
 	    *)
-	        os=netbsd
+		os=netbsd
 		;;
 	esac
 	# The OS release
@@ -224,7 +224,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
 		;;
 	*5.*)
-	        UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
 		;;
 	esac
 	# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -270,7 +270,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	# A Xn.n version is an unreleased experimental baselevel.
 	# 1.2 uses "1.2" for uname -r.
 	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-	exit ;;
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
     Alpha\ *:Windows_NT*:*)
 	# How do we know it's Interix rather than the generic POSIX subsystem?
 	# Should we change UNAME_MACHINE based on the output of uname instead
@@ -296,7 +299,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	echo s390-ibm-zvmoe
 	exit ;;
     *:OS400:*:*)
-        echo powerpc-ibm-os400
+	echo powerpc-ibm-os400
 	exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
 	echo arm-acorn-riscix${UNAME_RELEASE}
@@ -395,23 +398,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
 	echo m68k-atari-mint${UNAME_RELEASE}
-        exit ;;
+	exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-        echo m68k-atari-mint${UNAME_RELEASE}
+	echo m68k-atari-mint${UNAME_RELEASE}
 	exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-        echo m68k-milan-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-        echo m68k-hades-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-        echo m68k-unknown-mint${UNAME_RELEASE}
-        exit ;;
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
     m68k:machten:*:*)
 	echo m68k-apple-machten${UNAME_RELEASE}
 	exit ;;
@@ -481,8 +484,8 @@ EOF
 	echo m88k-motorola-sysv3
 	exit ;;
     AViiON:dgux:*:*)
-        # DG/UX returns AViiON for all architectures
-        UNAME_PROCESSOR=`/usr/bin/uname -p`
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
 	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
 	then
 	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -495,7 +498,7 @@ EOF
 	else
 	    echo i586-dg-dgux${UNAME_RELEASE}
 	fi
- 	exit ;;
+	exit ;;
     M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
 	echo m88k-dolphin-sysv3
 	exit ;;
@@ -552,7 +555,7 @@ EOF
 		echo rs6000-ibm-aix3.2
 	fi
 	exit ;;
-    *:AIX:*:[456])
+    *:AIX:*:[4567])
 	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
 	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
 		IBM_ARCH=rs6000
@@ -595,52 +598,52 @@ EOF
 	    9000/[678][0-9][0-9])
 		if [ -x /usr/bin/getconf ]; then
 		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
-                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-                    case "${sc_cpu_version}" in
-                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
-                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
-                      532)                      # CPU_PA_RISC2_0
-                        case "${sc_kernel_bits}" in
-                          32) HP_ARCH="hppa2.0n" ;;
-                          64) HP_ARCH="hppa2.0w" ;;
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH="hppa2.0n" ;;
+			  64) HP_ARCH="hppa2.0w" ;;
 			  '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
-                        esac ;;
-                    esac
+			esac ;;
+		    esac
 		fi
 		if [ "${HP_ARCH}" = "" ]; then
 		    eval $set_cc_for_build
-		    sed 's/^              //' << EOF >$dummy.c
+		    sed 's/^		//' << EOF >$dummy.c
 
-              #define _HPUX_SOURCE
-              #include <stdlib.h>
-              #include <unistd.h>
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
 
-              int main ()
-              {
-              #if defined(_SC_KERNEL_BITS)
-                  long bits = sysconf(_SC_KERNEL_BITS);
-              #endif
-                  long cpu  = sysconf (_SC_CPU_VERSION);
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
 
-                  switch (cpu)
-              	{
-              	case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-              	case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-              	case CPU_PA_RISC2_0:
-              #if defined(_SC_KERNEL_BITS)
-              	    switch (bits)
-              		{
-              		case 64: puts ("hppa2.0w"); break;
-              		case 32: puts ("hppa2.0n"); break;
-              		default: puts ("hppa2.0"); break;
-              		} break;
-              #else  /* !defined(_SC_KERNEL_BITS) */
-              	    puts ("hppa2.0"); break;
-              #endif
-              	default: puts ("hppa1.0"); break;
-              	}
-                  exit (0);
-              }
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
 EOF
 		    (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
 		    test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -731,22 +734,22 @@ EOF
 	exit ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
 	echo c1-convex-bsd
-        exit ;;
+	exit ;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
 	if getsysinfo -f scalar_acc
 	then echo c32-convex-bsd
 	else echo c2-convex-bsd
 	fi
-        exit ;;
+	exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
 	echo c34-convex-bsd
-        exit ;;
+	exit ;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
 	echo c38-convex-bsd
-        exit ;;
+	exit ;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
 	echo c4-convex-bsd
-        exit ;;
+	exit ;;
     CRAY*Y-MP:*:*:*)
 	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
 	exit ;;
@@ -770,14 +773,14 @@ EOF
 	exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
 	FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
-        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit ;;
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
     5000:UNIX_System_V:4.*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
 	exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
 	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -805,14 +808,14 @@ EOF
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
     i*:windows32*:*)
-    	# uname -m includes "-pc" on this system.
-    	echo ${UNAME_MACHINE}-mingw32
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
 	exit ;;
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
     *:Interix*:*)
-    	case ${UNAME_MACHINE} in
+	case ${UNAME_MACHINE} in
 	    x86)
 		echo i586-pc-interix${UNAME_RELEASE}
 		exit ;;
@@ -867,7 +870,7 @@ EOF
 	  EV6)   UNAME_MACHINE=alphaev6 ;;
 	  EV67)  UNAME_MACHINE=alphaev67 ;;
 	  EV68*) UNAME_MACHINE=alphaev68 ;;
-        esac
+	esac
 	objdump --private-headers /bin/sh | grep -q ld.so.1
 	if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
 	echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
@@ -879,7 +882,13 @@ EOF
 	then
 	    echo ${UNAME_MACHINE}-unknown-linux-gnu
 	else
-	    echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+	    fi
 	fi
 	exit ;;
     avr32*:Linux:*:*)
@@ -892,7 +901,7 @@ EOF
 	echo crisv32-axis-linux-gnu
 	exit ;;
     frv:Linux:*:*)
-    	echo frv-unknown-linux-gnu
+	echo frv-unknown-linux-gnu
 	exit ;;
     i*86:Linux:*:*)
 	LIBC=gnu
@@ -960,7 +969,7 @@ EOF
 	echo ${UNAME_MACHINE}-ibm-linux
 	exit ;;
     sh64*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
     sh*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -968,6 +977,9 @@ EOF
     sparc:Linux:*:* | sparc64:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-tilera-linux-gnu
+	exit ;;
     vax:Linux:*:*)
 	echo ${UNAME_MACHINE}-dec-linux-gnu
 	exit ;;
@@ -975,7 +987,7 @@ EOF
 	echo x86_64-unknown-linux-gnu
 	exit ;;
     xtensa*:Linux:*:*)
-    	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
     i*86:DYNIX/ptx:4*:*)
 	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -984,11 +996,11 @@ EOF
 	echo i386-sequent-sysv4
 	exit ;;
     i*86:UNIX_SV:4.2MP:2.*)
-        # Unixware is an offshoot of SVR4, but it has its own version
-        # number series starting with 2...
-        # I am not positive that other SVR4 systems won't match this,
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
 	# I just have to hope.  -- rms.
-        # Use sysv4.2uw... so that sysv4* matches it.
+	# Use sysv4.2uw... so that sysv4* matches it.
 	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
 	exit ;;
     i*86:OS/2:*:*)
@@ -1020,7 +1032,7 @@ EOF
 	fi
 	exit ;;
     i*86:*:5:[678]*)
-    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
 	case `/bin/uname -X | grep "^Machine"` in
 	    *486*)	     UNAME_MACHINE=i486 ;;
 	    *Pentium)	     UNAME_MACHINE=i586 ;;
@@ -1048,13 +1060,13 @@ EOF
 	exit ;;
     pc:*:*:*)
 	# Left here for compatibility:
-        # uname -m prints for DJGPP always 'pc', but it prints nothing about
-        # the processor, so we play safe by assuming i586.
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
 	# Note: whatever this is, it MUST be the same as what config.sub
 	# prints for the "djgpp" host, or else GDB configury will decide that
 	# this is a cross-build.
 	echo i586-pc-msdosdjgpp
-        exit ;;
+	exit ;;
     Intel:Mach:3*:*)
 	echo i386-pc-mach3
 	exit ;;
@@ -1089,8 +1101,8 @@ EOF
 	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
 	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && { echo i486-ncr-sysv4; exit; } ;;
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
     NCR*:*:4.2:* | MPRAS*:*:4.2:*)
 	OS_REL='.3'
 	test -r /etc/.relid \
@@ -1133,10 +1145,10 @@ EOF
 		echo ns32k-sni-sysv
 	fi
 	exit ;;
-    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-                      # says <Richard.M.Bartel at ccMail.Census.GOV>
-        echo i586-unisys-sysv4
-        exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel at ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
     *:UNIX_System_V:4*:FTX*)
 	# From Gerald Hewes <hewes at openmarket.com>.
 	# How about differentiating between stratus architectures? -djm
@@ -1162,11 +1174,11 @@ EOF
 	exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
 	if [ -d /usr/nec ]; then
-	        echo mips-nec-sysv${UNAME_RELEASE}
+		echo mips-nec-sysv${UNAME_RELEASE}
 	else
-	        echo mips-unknown-sysv${UNAME_RELEASE}
+		echo mips-unknown-sysv${UNAME_RELEASE}
 	fi
-        exit ;;
+	exit ;;
     BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
 	echo powerpc-be-beos
 	exit ;;
@@ -1231,6 +1243,9 @@ EOF
     *:QNX:*:4*)
 	echo i386-pc-qnx
 	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
     NSE-?:NONSTOP_KERNEL:*:*)
 	echo nse-tandem-nsk${UNAME_RELEASE}
 	exit ;;
@@ -1276,13 +1291,13 @@ EOF
 	echo pdp10-unknown-its
 	exit ;;
     SEI:*:*:SEIUX)
-        echo mips-sei-seiux${UNAME_RELEASE}
+	echo mips-sei-seiux${UNAME_RELEASE}
 	exit ;;
     *:DragonFly:*:*)
 	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
 	exit ;;
     *:*VMS:*:*)
-    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
 	case "${UNAME_MACHINE}" in
 	    A*) echo alpha-dec-vms ; exit ;;
 	    I*) echo ia64-dec-vms ; exit ;;
@@ -1322,11 +1337,11 @@ main ()
 #include <sys/param.h>
   printf ("m68k-sony-newsos%s\n",
 #ifdef NEWSOS4
-          "4"
+	"4"
 #else
-	  ""
+	""
 #endif
-         ); exit (0);
+	); exit (0);
 #endif
 #endif
 
diff --git a/build-aux/config.sub b/build-aux/config.sub
index c2d1257..30fdca8 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,10 +1,10 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-#   Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+#   2011 Free Software Foundation, Inc.
 
-timestamp='2010-01-22'
+timestamp='2011-03-23'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -76,7 +76,7 @@ version="\
 GNU config.sub ($timestamp)
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
 Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -124,8 +124,9 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
-  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | \
   kopensolaris*-gnu* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
@@ -157,8 +158,8 @@ case $os in
 		os=
 		basic_machine=$1
 		;;
-        -bluegene*)
-	        os=-cnk
+	-bluegene*)
+		os=-cnk
 		;;
 	-sim | -cisco | -oki | -wec | -winbond)
 		os=
@@ -174,10 +175,10 @@ case $os in
 		os=-chorusos
 		basic_machine=$1
 		;;
- 	-chorusrdb)
- 		os=-chorusrdb
+	-chorusrdb)
+		os=-chorusrdb
 		basic_machine=$1
- 		;;
+		;;
 	-hiux*)
 		os=-hiuxwe2
 		;;
@@ -282,11 +283,13 @@ case $basic_machine in
 	| moxie \
 	| mt \
 	| msp430 \
+	| nds32 | nds32le | nds32be \
 	| nios | nios2 \
 	| ns16k | ns32k \
+	| open8 \
 	| or32 \
 	| pdp10 | pdp11 | pj | pjl \
-	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
 	| pyramid \
 	| rx \
 	| score \
@@ -294,15 +297,24 @@ case $basic_machine in
 	| sh64 | sh64le \
 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
-	| spu | strongarm \
-	| tahoe | thumb | tic4x | tic80 | tron \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
 	| ubicom32 \
 	| v850 | v850e \
 	| we32k \
-	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| x86 | xc16x | xstormy16 | xtensa \
 	| z8k | z80)
 		basic_machine=$basic_machine-unknown
 		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
 	m6811 | m68hc11 | m6812 | m68hc12 | picochip)
 		# Motorola 68HC11/12.
 		basic_machine=$basic_machine-unknown
@@ -314,6 +326,18 @@ case $basic_machine in
 		basic_machine=mt-unknown
 		;;
 
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
 	# We use `pc' rather than `unknown'
 	# because (1) that's what they normally are, and
 	# (2) the word "unknown" tends to confuse beginning users.
@@ -334,7 +358,7 @@ case $basic_machine in
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
 	| avr-* | avr32-* \
 	| bfin-* | bs2000-* \
-	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
 	| clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
 	| elxsi-* \
@@ -368,26 +392,28 @@ case $basic_machine in
 	| mmix-* \
 	| mt-* \
 	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
 	| nios-* | nios2-* \
 	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
 	| orion-* \
 	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
-	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
 	| pyramid-* \
 	| romp-* | rs6000-* | rx-* \
 	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
-	| tahoe-* | thumb-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+	| tahoe-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
 	| tile-* | tilegx-* \
 	| tron-* \
 	| ubicom32-* \
 	| v850-* | v850e-* | vax-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
 	| xstormy16-* | xtensa*-* \
 	| ymp-* \
 	| z8k-* | z80-*)
@@ -412,7 +438,7 @@ case $basic_machine in
 		basic_machine=a29k-amd
 		os=-udi
 		;;
-    	abacus)
+	abacus)
 		basic_machine=abacus-unknown
 		;;
 	adobe68k)
@@ -482,11 +508,20 @@ case $basic_machine in
 		basic_machine=powerpc-ibm
 		os=-cnk
 		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	c90)
 		basic_machine=c90-cray
 		os=-unicos
 		;;
-        cegcc)
+	cegcc)
 		basic_machine=arm-unknown
 		os=-cegcc
 		;;
@@ -518,7 +553,7 @@ case $basic_machine in
 		basic_machine=craynv-cray
 		os=-unicosmp
 		;;
-	cr16)
+	cr16 | cr16-*)
 		basic_machine=cr16-unknown
 		os=-elf
 		;;
@@ -734,7 +769,7 @@ case $basic_machine in
 		basic_machine=ns32k-utek
 		os=-sysv
 		;;
-        microblaze)
+	microblaze)
 		basic_machine=microblaze-xilinx
 		;;
 	mingw32)
@@ -841,6 +876,12 @@ case $basic_machine in
 	np1)
 		basic_machine=np1-gould
 		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
 	nsr-tandem)
 		basic_machine=nsr-tandem
 		;;
@@ -923,9 +964,10 @@ case $basic_machine in
 		;;
 	power)	basic_machine=power-ibm
 		;;
-	ppc)	basic_machine=powerpc-unknown
+	ppc | ppcbe)	basic_machine=powerpc-unknown
 		;;
-	ppc-*)	basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
 		;;
 	ppcle | powerpclittle | ppc-le | powerpc-little)
 		basic_machine=powerpcle-unknown
@@ -1019,6 +1061,9 @@ case $basic_machine in
 		basic_machine=i860-stratus
 		os=-sysv4
 		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
 	sun2)
 		basic_machine=m68000-sun
 		;;
@@ -1075,20 +1120,8 @@ case $basic_machine in
 		basic_machine=t90-cray
 		os=-unicos
 		;;
-	tic54x | c54x*)
-		basic_machine=tic54x-unknown
-		os=-coff
-		;;
-	tic55x | c55x*)
-		basic_machine=tic55x-unknown
-		os=-coff
-		;;
-	tic6x | c6x*)
-		basic_machine=tic6x-unknown
-		os=-coff
-		;;
-        # This must be matched before tile*.
-        tilegx*)
+	# This must be matched before tile*.
+	tilegx*)
 		basic_machine=tilegx-unknown
 		os=-linux-gnu
 		;;
@@ -1163,6 +1196,9 @@ case $basic_machine in
 	xps | xps100)
 		basic_machine=xps100-honeywell
 		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
 	ymp)
 		basic_machine=ymp-cray
 		os=-unicos
@@ -1260,11 +1296,11 @@ esac
 if [ x"$os" != x"" ]
 then
 case $os in
-        # First match some system type aliases
-        # that might get confused with valid system types.
+	# First match some system type aliases
+	# that might get confused with valid system types.
 	# -solaris* is a basic system type, with this one exception.
-        -auroraux)
-	        os=-auroraux
+	-auroraux)
+		os=-auroraux
 		;;
 	-solaris1 | -solaris1.*)
 		os=`echo $os | sed -e 's|solaris1|sunos4|'`
@@ -1301,7 +1337,8 @@ case $os in
 	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
 	      | -chorusos* | -chorusrdb* | -cegcc* \
 	      | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-	      | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+	      | -mingw32* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-uclibc* \
 	      | -uxpv* | -beos* | -mpeix* | -udk* \
 	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
 	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1348,7 +1385,7 @@ case $os in
 	-opened*)
 		os=-openedition
 		;;
-        -os400*)
+	-os400*)
 		os=-os400
 		;;
 	-wince*)
@@ -1397,7 +1434,7 @@ case $os in
 	-sinix*)
 		os=-sysv4
 		;;
-        -tpf*)
+	-tpf*)
 		os=-tpf
 		;;
 	-triton*)
@@ -1442,8 +1479,8 @@ case $os in
 	-dicos*)
 		os=-dicos
 		;;
-        -nacl*)
-	        ;;
+	-nacl*)
+		;;
 	-none)
 		;;
 	*)
@@ -1466,10 +1503,10 @@ else
 # system, and we'll never get to this point.
 
 case $basic_machine in
-        score-*)
+	score-*)
 		os=-elf
 		;;
-        spu-*)
+	spu-*)
 		os=-elf
 		;;
 	*-acorn)
@@ -1481,8 +1518,17 @@ case $basic_machine in
 	arm*-semi)
 		os=-aout
 		;;
-        c4x-* | tic4x-*)
-        	os=-coff
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
 		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
@@ -1509,7 +1555,7 @@ case $basic_machine in
 	m68*-cisco)
 		os=-aout
 		;;
-        mep-*)
+	mep-*)
 		os=-elf
 		;;
 	mips*-cisco)
@@ -1536,7 +1582,7 @@ case $basic_machine in
 	*-ibm)
 		os=-aix
 		;;
-    	*-knuth)
+	*-knuth)
 		os=-mmixware
 		;;
 	*-wec)
diff --git a/configure b/configure
index 7ec2c45..98d4581 100755
--- a/configure
+++ b/configure
@@ -11585,7 +11585,7 @@ fi
 
 done
 
-for ac_header in stdlib.h mntent.h linux/cdrom.h inttypes.h
+for ac_header in stdlib.h mntent.h linux/cdrom.h inttypes.h strings.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
diff --git a/configure.ac b/configure.ac
index 525a31d..316ad47 100644
--- a/configure.ac
+++ b/configure.ac
@@ -97,7 +97,7 @@ AC_TYPE_SIGNAL
 
 # required headers
 AC_CHECK_HEADERS([stdarg.h sys/types.h dirent.h errno.h libgen.h malloc.h])
-AC_CHECK_HEADERS([stdlib.h mntent.h linux/cdrom.h inttypes.h])
+AC_CHECK_HEADERS([stdlib.h mntent.h linux/cdrom.h inttypes.h strings.h])
 AC_CHECK_HEADERS([sys/time.h time.h])
 if test "${SYS}" != "mingw32" ; then
     AC_CHECK_HEADERS(pthread.h,, [AC_MSG_ERROR([pthread.h required])])
diff --git a/player_wrappers/xine/input_bluray.c b/player_wrappers/xine/input_bluray.c
index 9e13cfc..21f5009 100644
--- a/player_wrappers/xine/input_bluray.c
+++ b/player_wrappers/xine/input_bluray.c
@@ -38,6 +38,7 @@
 #include <string.h>
 #include <errno.h>
 #include <dlfcn.h>
+#include <pthread.h>
 
 #include <libbluray/bluray.h>
 #include <libbluray/keys.h>
@@ -51,7 +52,7 @@
 
 #define LOGMSG(x...)  xine_log (this->stream->xine, XINE_LOG_MSG, "input_bluray: " x);
 
-#define XINE_ENGINE_INTERNAL
+#define XINE_ENGINE_INTERNAL  // stream->demux_plugin
 
 #ifdef HAVE_CONFIG_H
 # include "xine_internal.h"
@@ -168,8 +169,6 @@ static void close_overlay(bluray_input_plugin_t *this, int plane)
 static void overlay_proc(void *this_gen, const BD_OVERLAY * const ov)
 {
   bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-  uint32_t color[256];
-  uint8_t  trans[256];
   unsigned i;
 
   if (!this) {
@@ -194,23 +193,35 @@ static void overlay_proc(void *this_gen, const BD_OVERLAY * const ov)
   xine_osd_t *osd = this->osd[ov->plane];
   if (!this->pg_enable) {
     _x_select_spu_channel(this->stream, -1);
+  }
 
   /* convert and set palette */
+  if (ov->palette) {
+    uint32_t color[256];
+    uint8_t  trans[256];
+    for(i = 0; i < 256; i++) {
+      trans[i] = ov->palette[i].T;
+      color[i] = (ov->palette[i].Y << 16) | (ov->palette[i].Cr << 8) | ov->palette[i].Cb;
+    }
 
     xine_osd_set_palette(osd, color, trans);
   }
 
-  xine_osd_set_palette(this->osd, color, trans);
+  /* uncompress and draw bitmap */
+  if (ov->img) {
+    const BD_PG_RLE_ELEM *rlep = ov->img;
+    uint8_t *img = malloc(ov->w * ov->h);
+    unsigned pixels = ov->w * ov->h;
+
+    for (i = 0; i < pixels; i += rlep->len, rlep++) {
+      memset(img + i, rlep->color, rlep->len);
+    }
 
     xine_osd_draw_bitmap(osd, img, ov->x, ov->y, ov->w, ov->h, NULL);
 
-  const BD_PG_RLE_ELEM *rlep = ov->img;
-  uint8_t *img = malloc(ov->w * ov->h);
-  unsigned pixels = ov->w * ov->h;
+    free(img);
 
-  for (i = 0; i < pixels; i += rlep->len, rlep++) {
-    memset(img + i, rlep->color, rlep->len);
-  }
+  } else {
 
     if (ov->x == 0 && ov->y == 0 && ov->w == 1920 && ov->h == 1080) {
       /* Nothing to display, close OSD */
@@ -234,13 +245,14 @@ static void overlay_proc(void *this_gen, const BD_OVERLAY * const ov)
 
 static void update_stream_info(bluray_input_plugin_t *this)
 {
-  /* set stream info */
-
-  _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_COUNT,    this->title_info->angle_count);
-  _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER,   bd_get_current_angle(this->bdh));
-  _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_CHAPTERS,       this->title_info->chapter_count > 0);
-  _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_COUNT,  this->title_info->chapter_count);
-  _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, bd_get_current_chapter(this->bdh) + 1);
+  if (this->title_info) {
+    /* set stream info */
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_COUNT,    this->title_info->angle_count);
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_ANGLE_NUMBER,   bd_get_current_angle(this->bdh));
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_CHAPTERS,       this->title_info->chapter_count > 0);
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_COUNT,  this->title_info->chapter_count);
+    _x_stream_info_set(this->stream, XINE_STREAM_INFO_DVD_CHAPTER_NUMBER, bd_get_current_chapter(this->bdh) + 1);
+  }
 }
 
 static void update_title_name(bluray_input_plugin_t *this)
@@ -381,7 +393,7 @@ static void stream_reset(bluray_input_plugin_t *this)
 
   this->cap_seekable = 0;
 
-  xine_set_param(this->stream, XINE_PARAM_FINE_SPEED, XINE_FINE_SPEED_NORMAL);
+  _x_set_fine_speed(this->stream, XINE_FINE_SPEED_NORMAL);
   this->stream->demux_plugin->seek(this->stream->demux_plugin, 0, 0, 1);
   _x_demux_control_start(this->stream);
 
@@ -770,7 +782,7 @@ static off_t bluray_plugin_read (input_plugin_t *this_gen, char *buf, off_t len)
       if (result == 0) {
         handle_events(this);
         if (ev.event == BD_EVENT_NONE) {
-          if (this->stream->demux_action_pending) {
+          if (_x_action_pending(this->stream)) {
             break;
           }
         }
@@ -846,7 +858,7 @@ static off_t bluray_plugin_seek_time (input_plugin_t *this_gen, int time_offset,
 {
   bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
 
-  if (!this || !this->bdh || !this->title_info)
+  if (!this || !this->bdh)
     return -1;
 
   if (this->still_end_time)
@@ -858,11 +870,21 @@ static off_t bluray_plugin_seek_time (input_plugin_t *this_gen, int time_offset,
     time_offset += this_gen->get_current_time(this_gen);
   }
   else if (origin == SEEK_END) {
+
+    pthread_mutex_lock(&this->title_info_mutex);
+
+    if (!this->title_info) {
+      pthread_mutex_unlock(&this->title_info_mutex);
+      return -1;
+    }
+
     int duration = this->title_info->duration / 90;
     if (time_offset < duration)
       time_offset = duration - time_offset;
     else
       time_offset = 0;
+
+    pthread_mutex_unlock(&this->title_info_mutex);
   }
 
   lprintf("bluray_plugin_seek_time() seeking to %d.%03ds\n", time_offset / 1000, time_offset % 1000);
@@ -905,12 +927,9 @@ static const char* bluray_plugin_get_mrl (input_plugin_t *this_gen)
   return this->mrl;
 }
 
-static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type)
+static int get_optional_data_impl (bluray_input_plugin_t *this, void *data, int data_type)
 {
-  bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
-
-  if (!this || !this->stream || !data)
-    return INPUT_OPTIONAL_UNSUPPORTED;
+  unsigned int current_clip = this->current_clip;
 
   switch (data_type) {
     case INPUT_OPTIONAL_DATA_DEMUXER:
@@ -922,9 +941,9 @@ static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data
      * - channel number can be mpeg-ts PID (0x1100 ... 0x11ff)
      */
     case INPUT_OPTIONAL_DATA_AUDIOLANG:
-      if (this->title_info) {
+      if (this->title_info && this->title_info->clip_count < current_clip) {
         int               channel = *((int *)data);
-        BLURAY_CLIP_INFO *clip    = &this->title_info->clips[this->current_clip];
+        BLURAY_CLIP_INFO *clip    = &this->title_info->clips[current_clip];
 
         if (channel >= 0 && channel < clip->audio_stream_count) {
           memcpy(data, clip->audio_streams[channel].lang, 4);
@@ -952,9 +971,9 @@ static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data
      * - channel number can be mpeg-ts PID (0x1200 ... 0x12ff)
      */
     case INPUT_OPTIONAL_DATA_SPULANG:
-      if (this->title_info) {
+      if (this->title_info && this->title_info->clip_count < current_clip) {
         int               channel = *((int *)data);
-        BLURAY_CLIP_INFO *clip    = &this->title_info->clips[this->current_clip];
+        BLURAY_CLIP_INFO *clip    = &this->title_info->clips[current_clip];
 
         if (channel >= 0 && channel < clip->pg_stream_count) {
           memcpy(data, clip->pg_streams[channel].lang, 4);
@@ -984,6 +1003,20 @@ static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data
   return INPUT_OPTIONAL_UNSUPPORTED;
 }
 
+static int bluray_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type)
+{
+  bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
+  int r = INPUT_OPTIONAL_UNSUPPORTED;
+
+  if (this && this->stream && data) {
+    pthread_mutex_lock(&this->title_info_mutex);
+    r = get_optional_data_impl(this, data, data_type);
+    pthread_mutex_unlock(&this->title_info_mutex);
+  }
+
+  return r;
+}
+
 static void bluray_plugin_dispose (input_plugin_t *this_gen)
 {
   bluray_input_plugin_t *this = (bluray_input_plugin_t *) this_gen;
@@ -996,8 +1029,13 @@ static void bluray_plugin_dispose (input_plugin_t *this_gen)
   if (this->event_queue)
     xine_event_dispose_queue(this->event_queue);
 
+  pthread_mutex_lock(&this->title_info_mutex);
   if (this->title_info)
     bd_free_title_info(this->title_info);
+  this->title_info = NULL;
+  pthread_mutex_unlock(&this->title_info_mutex);
+
+  pthread_mutex_destroy(&this->title_info_mutex);
 
   if (this->bdh)
     bd_close(this->bdh);
@@ -1169,7 +1207,7 @@ static int bluray_plugin_open (input_plugin_t *this_gen)
     uint64_t duration = 0;
     int i, playlist = 99999;
     for (i = 0; i < this->num_title_idx; i++) {
-      BLURAY_TITLE_INFO *info = bd_get_title_info(this->bdh, i);
+      BLURAY_TITLE_INFO *info = bd_get_title_info(this->bdh, i, 0);
       if (info->duration > duration) {
         title    = i;
         duration = info->duration;
@@ -1277,6 +1315,8 @@ static input_plugin_t *bluray_class_get_instance (input_class_t *cls_gen, xine_s
 
   this->event_queue = xine_event_new_queue (this->stream);
 
+  pthread_mutex_init(&this->title_info_mutex, NULL);
+
   this->pg_stream = -1;
 
   return &this->input_plugin;
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am
index bc7c348..265bb31 100644
--- a/src/examples/Makefile.am
+++ b/src/examples/Makefile.am
@@ -14,7 +14,6 @@ noinst_PROGRAMS=bdsplice mpls_dump clpi_dump index_dump mobj_dump sound_dump \
     libbluray_test bd_info list_titles hdmv_test
 
 BLURAY_LIB = $(top_builddir)/src/libbluray.la
-BLURAY_LIB_STATIC = $(top_builddir)/src/.libs/libbluray.a
 
 if USING_BDJAVA
   AM_CFLAGS += @BDJAVA_CFLAGS@
@@ -26,29 +25,39 @@ bdsplice_SOURCES = \
 bdsplice_LDADD = $(BLURAY_LIB)
 
 mpls_dump_SOURCES = \
-	mpls_dump.c util.c util.h ../util/strutl.c
-
-mpls_dump_LDADD = $(BLURAY_LIB_STATIC)
+	mpls_dump.c util.c util.h \
+	../util/strutl.c \
+	../util/logging.c \
+	../file/file_posix.c \
+	../file/dir_posix.c \
+	../libbluray/bdnav/mpls_parse.c \
+	../libbluray/bdnav/clpi_parse.c \
+	../libbluray/bdnav/navigation.c
 
 clpi_dump_SOURCES = \
-	clpi_dump.c util.c util.h
-
-clpi_dump_LDADD = $(BLURAY_LIB_STATIC)
+	clpi_dump.c util.c util.h \
+	../util/logging.c \
+	../file/file_posix.c \
+	../libbluray/bdnav/clpi_parse.c
 
 sound_dump_SOURCES = \
-	sound_dump.c
-
-sound_dump_LDADD = $(BLURAY_LIB_STATIC)
+	sound_dump.c \
+	../util/logging.c \
+	../file/file_posix.c \
+	../libbluray/bdnav/sound_parse.c
 
 index_dump_SOURCES = \
-	index_dump.c
-
-index_dump_LDADD = $(BLURAY_LIB_STATIC)
+	index_dump.c \
+	../util/logging.c \
+	../file/file_posix.c \
+	../libbluray/bdnav/index_parse.c
 
 mobj_dump_SOURCES = \
-	mobj_dump.c
-
-mobj_dump_LDADD = $(BLURAY_LIB_STATIC)
+	mobj_dump.c \
+	../util/logging.c \
+	../file/file_posix.c \
+	../libbluray/hdmv/mobj_parse.c \
+	../libbluray/hdmv/mobj_print.c
 
 libbluray_test_SOURCES = \
 	libbluray_test.c ../util/logging.c
diff --git a/src/examples/Makefile.in b/src/examples/Makefile.in
index 2cab51e..2d12d75 100644
--- a/src/examples/Makefile.in
+++ b/src/examples/Makefile.in
@@ -75,19 +75,25 @@ am__bdsplice_SOURCES_DIST = bdsplice.c
 @USING_EXAMPLES_TRUE at am_bdsplice_OBJECTS = bdsplice.$(OBJEXT)
 bdsplice_OBJECTS = $(am_bdsplice_OBJECTS)
 @USING_EXAMPLES_TRUE at bdsplice_DEPENDENCIES = $(BLURAY_LIB)
-am__clpi_dump_SOURCES_DIST = clpi_dump.c util.c util.h
+am__clpi_dump_SOURCES_DIST = clpi_dump.c util.c util.h \
+	../util/logging.c ../file/file_posix.c \
+	../libbluray/bdnav/clpi_parse.c
 @USING_EXAMPLES_TRUE at am_clpi_dump_OBJECTS = clpi_dump.$(OBJEXT) \
- at USING_EXAMPLES_TRUE@	util.$(OBJEXT)
+ at USING_EXAMPLES_TRUE@	util.$(OBJEXT) logging.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	file_posix.$(OBJEXT) clpi_parse.$(OBJEXT)
 clpi_dump_OBJECTS = $(am_clpi_dump_OBJECTS)
- at USING_EXAMPLES_TRUE@clpi_dump_DEPENDENCIES = $(BLURAY_LIB_STATIC)
+clpi_dump_LDADD = $(LDADD)
 am__hdmv_test_SOURCES_DIST = hdmv_test.c
 @USING_EXAMPLES_TRUE at am_hdmv_test_OBJECTS = hdmv_test.$(OBJEXT)
 hdmv_test_OBJECTS = $(am_hdmv_test_OBJECTS)
 @USING_EXAMPLES_TRUE at hdmv_test_DEPENDENCIES = $(BLURAY_LIB)
-am__index_dump_SOURCES_DIST = index_dump.c
- at USING_EXAMPLES_TRUE@am_index_dump_OBJECTS = index_dump.$(OBJEXT)
+am__index_dump_SOURCES_DIST = index_dump.c ../util/logging.c \
+	../file/file_posix.c ../libbluray/bdnav/index_parse.c
+ at USING_EXAMPLES_TRUE@am_index_dump_OBJECTS = index_dump.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	logging.$(OBJEXT) file_posix.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	index_parse.$(OBJEXT)
 index_dump_OBJECTS = $(am_index_dump_OBJECTS)
- at USING_EXAMPLES_TRUE@index_dump_DEPENDENCIES = $(BLURAY_LIB_STATIC)
+index_dump_LDADD = $(LDADD)
 am__libbluray_test_SOURCES_DIST = libbluray_test.c ../util/logging.c
 @USING_EXAMPLES_TRUE at am_libbluray_test_OBJECTS =  \
 @USING_EXAMPLES_TRUE@	libbluray_test.$(OBJEXT) \
@@ -99,20 +105,33 @@ am__list_titles_SOURCES_DIST = list_titles.c ../util/logging.c
 @USING_EXAMPLES_TRUE@	logging.$(OBJEXT)
 list_titles_OBJECTS = $(am_list_titles_OBJECTS)
 @USING_EXAMPLES_TRUE at list_titles_DEPENDENCIES = $(BLURAY_LIB)
-am__mobj_dump_SOURCES_DIST = mobj_dump.c
- at USING_EXAMPLES_TRUE@am_mobj_dump_OBJECTS = mobj_dump.$(OBJEXT)
+am__mobj_dump_SOURCES_DIST = mobj_dump.c ../util/logging.c \
+	../file/file_posix.c ../libbluray/hdmv/mobj_parse.c \
+	../libbluray/hdmv/mobj_print.c
+ at USING_EXAMPLES_TRUE@am_mobj_dump_OBJECTS = mobj_dump.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	logging.$(OBJEXT) file_posix.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	mobj_parse.$(OBJEXT) mobj_print.$(OBJEXT)
 mobj_dump_OBJECTS = $(am_mobj_dump_OBJECTS)
- at USING_EXAMPLES_TRUE@mobj_dump_DEPENDENCIES = $(BLURAY_LIB_STATIC)
+mobj_dump_LDADD = $(LDADD)
 am__mpls_dump_SOURCES_DIST = mpls_dump.c util.c util.h \
-	../util/strutl.c
+	../util/strutl.c ../util/logging.c ../file/file_posix.c \
+	../file/dir_posix.c ../libbluray/bdnav/mpls_parse.c \
+	../libbluray/bdnav/clpi_parse.c \
+	../libbluray/bdnav/navigation.c
 @USING_EXAMPLES_TRUE at am_mpls_dump_OBJECTS = mpls_dump.$(OBJEXT) \
- at USING_EXAMPLES_TRUE@	util.$(OBJEXT) strutl.$(OBJEXT)
+ at USING_EXAMPLES_TRUE@	util.$(OBJEXT) strutl.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	logging.$(OBJEXT) file_posix.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	dir_posix.$(OBJEXT) mpls_parse.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	clpi_parse.$(OBJEXT) navigation.$(OBJEXT)
 mpls_dump_OBJECTS = $(am_mpls_dump_OBJECTS)
- at USING_EXAMPLES_TRUE@mpls_dump_DEPENDENCIES = $(BLURAY_LIB_STATIC)
-am__sound_dump_SOURCES_DIST = sound_dump.c
- at USING_EXAMPLES_TRUE@am_sound_dump_OBJECTS = sound_dump.$(OBJEXT)
+mpls_dump_LDADD = $(LDADD)
+am__sound_dump_SOURCES_DIST = sound_dump.c ../util/logging.c \
+	../file/file_posix.c ../libbluray/bdnav/sound_parse.c
+ at USING_EXAMPLES_TRUE@am_sound_dump_OBJECTS = sound_dump.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	logging.$(OBJEXT) file_posix.$(OBJEXT) \
+ at USING_EXAMPLES_TRUE@	sound_parse.$(OBJEXT)
 sound_dump_OBJECTS = $(am_sound_dump_OBJECTS)
- at USING_EXAMPLES_TRUE@sound_dump_DEPENDENCIES = $(BLURAY_LIB_STATIC)
+sound_dump_LDADD = $(LDADD)
 DEFAULT_INCLUDES = -I. at am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
 am__depfiles_maybe = depfiles
@@ -299,31 +318,45 @@ AM_CFLAGS = -std=c99 $(SET_FEATURES) $(SET_WARNINGS) \
 	$(SET_OPTIMIZATIONS) $(SET_DEBUG_OPTS) $(SET_INCLUDES) \
 	$(am__append_1)
 @USING_EXAMPLES_TRUE at BLURAY_LIB = $(top_builddir)/src/libbluray.la
- at USING_EXAMPLES_TRUE@BLURAY_LIB_STATIC = $(top_builddir)/src/.libs/libbluray.a
 @USING_EXAMPLES_TRUE at bdsplice_SOURCES = \
 @USING_EXAMPLES_TRUE@	bdsplice.c
 
 @USING_EXAMPLES_TRUE at bdsplice_LDADD = $(BLURAY_LIB)
 @USING_EXAMPLES_TRUE at mpls_dump_SOURCES = \
- at USING_EXAMPLES_TRUE@	mpls_dump.c util.c util.h ../util/strutl.c
+ at USING_EXAMPLES_TRUE@	mpls_dump.c util.c util.h \
+ at USING_EXAMPLES_TRUE@	../util/strutl.c \
+ at USING_EXAMPLES_TRUE@	../util/logging.c \
+ at USING_EXAMPLES_TRUE@	../file/file_posix.c \
+ at USING_EXAMPLES_TRUE@	../file/dir_posix.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/bdnav/mpls_parse.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/bdnav/clpi_parse.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/bdnav/navigation.c
 
- at USING_EXAMPLES_TRUE@mpls_dump_LDADD = $(BLURAY_LIB_STATIC)
 @USING_EXAMPLES_TRUE at clpi_dump_SOURCES = \
- at USING_EXAMPLES_TRUE@	clpi_dump.c util.c util.h
+ at USING_EXAMPLES_TRUE@	clpi_dump.c util.c util.h \
+ at USING_EXAMPLES_TRUE@	../util/logging.c \
+ at USING_EXAMPLES_TRUE@	../file/file_posix.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/bdnav/clpi_parse.c
 
- at USING_EXAMPLES_TRUE@clpi_dump_LDADD = $(BLURAY_LIB_STATIC)
 @USING_EXAMPLES_TRUE at sound_dump_SOURCES = \
- at USING_EXAMPLES_TRUE@	sound_dump.c
+ at USING_EXAMPLES_TRUE@	sound_dump.c \
+ at USING_EXAMPLES_TRUE@	../util/logging.c \
+ at USING_EXAMPLES_TRUE@	../file/file_posix.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/bdnav/sound_parse.c
 
- at USING_EXAMPLES_TRUE@sound_dump_LDADD = $(BLURAY_LIB_STATIC)
 @USING_EXAMPLES_TRUE at index_dump_SOURCES = \
- at USING_EXAMPLES_TRUE@	index_dump.c
+ at USING_EXAMPLES_TRUE@	index_dump.c \
+ at USING_EXAMPLES_TRUE@	../util/logging.c \
+ at USING_EXAMPLES_TRUE@	../file/file_posix.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/bdnav/index_parse.c
 
- at USING_EXAMPLES_TRUE@index_dump_LDADD = $(BLURAY_LIB_STATIC)
 @USING_EXAMPLES_TRUE at mobj_dump_SOURCES = \
- at USING_EXAMPLES_TRUE@	mobj_dump.c
+ at USING_EXAMPLES_TRUE@	mobj_dump.c \
+ at USING_EXAMPLES_TRUE@	../util/logging.c \
+ at USING_EXAMPLES_TRUE@	../file/file_posix.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/hdmv/mobj_parse.c \
+ at USING_EXAMPLES_TRUE@	../libbluray/hdmv/mobj_print.c
 
- at USING_EXAMPLES_TRUE@mobj_dump_LDADD = $(BLURAY_LIB_STATIC)
 @USING_EXAMPLES_TRUE at libbluray_test_SOURCES = \
 @USING_EXAMPLES_TRUE@	libbluray_test.c ../util/logging.c
 
@@ -429,14 +462,23 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/bdj_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/bdsplice.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/clpi_dump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/clpi_parse.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/dir_posix.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/file_posix.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/hdmv_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/index_dump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/index_parse.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/libbluray_test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/list_titles.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/logging.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mobj_dump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mobj_parse.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mobj_print.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mpls_dump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/mpls_parse.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/navigation.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/sound_dump.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/sound_parse.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/strutl.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/util.Po at am__quote@
 
@@ -475,6 +517,76 @@ logging.obj: ../util/logging.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logging.obj `if test -f '../util/logging.c'; then $(CYGPATH_W) '../util/logging.c'; else $(CYGPATH_W) '$(srcdir)/../util/logging.c'; fi`
 
+file_posix.o: ../file/file_posix.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_posix.o -MD -MP -MF $(DEPDIR)/file_posix.Tpo -c -o file_posix.o `test -f '../file/file_posix.c' || echo '$(srcdir)/'`../file/file_posix.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/file_posix.Tpo $(DEPDIR)/file_posix.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../file/file_posix.c' object='file_posix.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_posix.o `test -f '../file/file_posix.c' || echo '$(srcdir)/'`../file/file_posix.c
+
+file_posix.obj: ../file/file_posix.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT file_posix.obj -MD -MP -MF $(DEPDIR)/file_posix.Tpo -c -o file_posix.obj `if test -f '../file/file_posix.c'; then $(CYGPATH_W) '../file/file_posix.c'; else $(CYGPATH_W) '$(srcdir)/../file/file_posix.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/file_posix.Tpo $(DEPDIR)/file_posix.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../file/file_posix.c' object='file_posix.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o file_posix.obj `if test -f '../file/file_posix.c'; then $(CYGPATH_W) '../file/file_posix.c'; else $(CYGPATH_W) '$(srcdir)/../file/file_posix.c'; fi`
+
+clpi_parse.o: ../libbluray/bdnav/clpi_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clpi_parse.o -MD -MP -MF $(DEPDIR)/clpi_parse.Tpo -c -o clpi_parse.o `test -f '../libbluray/bdnav/clpi_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/clpi_parse.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/clpi_parse.Tpo $(DEPDIR)/clpi_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/clpi_parse.c' object='clpi_parse.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clpi_parse.o `test -f '../libbluray/bdnav/clpi_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/clpi_parse.c
+
+clpi_parse.obj: ../libbluray/bdnav/clpi_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT clpi_parse.obj -MD -MP -MF $(DEPDIR)/clpi_parse.Tpo -c -o clpi_parse.obj `if test -f '../libbluray/bdnav/clpi_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/clpi_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/clpi_parse.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/clpi_parse.Tpo $(DEPDIR)/clpi_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/clpi_parse.c' object='clpi_parse.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o clpi_parse.obj `if test -f '../libbluray/bdnav/clpi_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/clpi_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/clpi_parse.c'; fi`
+
+index_parse.o: ../libbluray/bdnav/index_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT index_parse.o -MD -MP -MF $(DEPDIR)/index_parse.Tpo -c -o index_parse.o `test -f '../libbluray/bdnav/index_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/index_parse.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/index_parse.Tpo $(DEPDIR)/index_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/index_parse.c' object='index_parse.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o index_parse.o `test -f '../libbluray/bdnav/index_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/index_parse.c
+
+index_parse.obj: ../libbluray/bdnav/index_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT index_parse.obj -MD -MP -MF $(DEPDIR)/index_parse.Tpo -c -o index_parse.obj `if test -f '../libbluray/bdnav/index_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/index_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/index_parse.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/index_parse.Tpo $(DEPDIR)/index_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/index_parse.c' object='index_parse.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o index_parse.obj `if test -f '../libbluray/bdnav/index_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/index_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/index_parse.c'; fi`
+
+mobj_parse.o: ../libbluray/hdmv/mobj_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mobj_parse.o -MD -MP -MF $(DEPDIR)/mobj_parse.Tpo -c -o mobj_parse.o `test -f '../libbluray/hdmv/mobj_parse.c' || echo '$(srcdir)/'`../libbluray/hdmv/mobj_parse.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mobj_parse.Tpo $(DEPDIR)/mobj_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/hdmv/mobj_parse.c' object='mobj_parse.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mobj_parse.o `test -f '../libbluray/hdmv/mobj_parse.c' || echo '$(srcdir)/'`../libbluray/hdmv/mobj_parse.c
+
+mobj_parse.obj: ../libbluray/hdmv/mobj_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mobj_parse.obj -MD -MP -MF $(DEPDIR)/mobj_parse.Tpo -c -o mobj_parse.obj `if test -f '../libbluray/hdmv/mobj_parse.c'; then $(CYGPATH_W) '../libbluray/hdmv/mobj_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/hdmv/mobj_parse.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mobj_parse.Tpo $(DEPDIR)/mobj_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/hdmv/mobj_parse.c' object='mobj_parse.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mobj_parse.obj `if test -f '../libbluray/hdmv/mobj_parse.c'; then $(CYGPATH_W) '../libbluray/hdmv/mobj_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/hdmv/mobj_parse.c'; fi`
+
+mobj_print.o: ../libbluray/hdmv/mobj_print.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mobj_print.o -MD -MP -MF $(DEPDIR)/mobj_print.Tpo -c -o mobj_print.o `test -f '../libbluray/hdmv/mobj_print.c' || echo '$(srcdir)/'`../libbluray/hdmv/mobj_print.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mobj_print.Tpo $(DEPDIR)/mobj_print.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/hdmv/mobj_print.c' object='mobj_print.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mobj_print.o `test -f '../libbluray/hdmv/mobj_print.c' || echo '$(srcdir)/'`../libbluray/hdmv/mobj_print.c
+
+mobj_print.obj: ../libbluray/hdmv/mobj_print.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mobj_print.obj -MD -MP -MF $(DEPDIR)/mobj_print.Tpo -c -o mobj_print.obj `if test -f '../libbluray/hdmv/mobj_print.c'; then $(CYGPATH_W) '../libbluray/hdmv/mobj_print.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/hdmv/mobj_print.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mobj_print.Tpo $(DEPDIR)/mobj_print.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/hdmv/mobj_print.c' object='mobj_print.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mobj_print.obj `if test -f '../libbluray/hdmv/mobj_print.c'; then $(CYGPATH_W) '../libbluray/hdmv/mobj_print.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/hdmv/mobj_print.c'; fi`
+
 strutl.o: ../util/strutl.c
 @am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT strutl.o -MD -MP -MF $(DEPDIR)/strutl.Tpo -c -o strutl.o `test -f '../util/strutl.c' || echo '$(srcdir)/'`../util/strutl.c
 @am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/strutl.Tpo $(DEPDIR)/strutl.Po
@@ -489,6 +601,62 @@ strutl.obj: ../util/strutl.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strutl.obj `if test -f '../util/strutl.c'; then $(CYGPATH_W) '../util/strutl.c'; else $(CYGPATH_W) '$(srcdir)/../util/strutl.c'; fi`
 
+dir_posix.o: ../file/dir_posix.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dir_posix.o -MD -MP -MF $(DEPDIR)/dir_posix.Tpo -c -o dir_posix.o `test -f '../file/dir_posix.c' || echo '$(srcdir)/'`../file/dir_posix.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/dir_posix.Tpo $(DEPDIR)/dir_posix.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../file/dir_posix.c' object='dir_posix.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dir_posix.o `test -f '../file/dir_posix.c' || echo '$(srcdir)/'`../file/dir_posix.c
+
+dir_posix.obj: ../file/dir_posix.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dir_posix.obj -MD -MP -MF $(DEPDIR)/dir_posix.Tpo -c -o dir_posix.obj `if test -f '../file/dir_posix.c'; then $(CYGPATH_W) '../file/dir_posix.c'; else $(CYGPATH_W) '$(srcdir)/../file/dir_posix.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/dir_posix.Tpo $(DEPDIR)/dir_posix.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../file/dir_posix.c' object='dir_posix.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dir_posix.obj `if test -f '../file/dir_posix.c'; then $(CYGPATH_W) '../file/dir_posix.c'; else $(CYGPATH_W) '$(srcdir)/../file/dir_posix.c'; fi`
+
+mpls_parse.o: ../libbluray/bdnav/mpls_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mpls_parse.o -MD -MP -MF $(DEPDIR)/mpls_parse.Tpo -c -o mpls_parse.o `test -f '../libbluray/bdnav/mpls_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/mpls_parse.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mpls_parse.Tpo $(DEPDIR)/mpls_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/mpls_parse.c' object='mpls_parse.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mpls_parse.o `test -f '../libbluray/bdnav/mpls_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/mpls_parse.c
+
+mpls_parse.obj: ../libbluray/bdnav/mpls_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mpls_parse.obj -MD -MP -MF $(DEPDIR)/mpls_parse.Tpo -c -o mpls_parse.obj `if test -f '../libbluray/bdnav/mpls_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/mpls_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/mpls_parse.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/mpls_parse.Tpo $(DEPDIR)/mpls_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/mpls_parse.c' object='mpls_parse.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mpls_parse.obj `if test -f '../libbluray/bdnav/mpls_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/mpls_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/mpls_parse.c'; fi`
+
+navigation.o: ../libbluray/bdnav/navigation.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT navigation.o -MD -MP -MF $(DEPDIR)/navigation.Tpo -c -o navigation.o `test -f '../libbluray/bdnav/navigation.c' || echo '$(srcdir)/'`../libbluray/bdnav/navigation.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/navigation.Tpo $(DEPDIR)/navigation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/navigation.c' object='navigation.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o navigation.o `test -f '../libbluray/bdnav/navigation.c' || echo '$(srcdir)/'`../libbluray/bdnav/navigation.c
+
+navigation.obj: ../libbluray/bdnav/navigation.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT navigation.obj -MD -MP -MF $(DEPDIR)/navigation.Tpo -c -o navigation.obj `if test -f '../libbluray/bdnav/navigation.c'; then $(CYGPATH_W) '../libbluray/bdnav/navigation.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/navigation.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/navigation.Tpo $(DEPDIR)/navigation.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/navigation.c' object='navigation.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o navigation.obj `if test -f '../libbluray/bdnav/navigation.c'; then $(CYGPATH_W) '../libbluray/bdnav/navigation.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/navigation.c'; fi`
+
+sound_parse.o: ../libbluray/bdnav/sound_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sound_parse.o -MD -MP -MF $(DEPDIR)/sound_parse.Tpo -c -o sound_parse.o `test -f '../libbluray/bdnav/sound_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/sound_parse.c
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/sound_parse.Tpo $(DEPDIR)/sound_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/sound_parse.c' object='sound_parse.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sound_parse.o `test -f '../libbluray/bdnav/sound_parse.c' || echo '$(srcdir)/'`../libbluray/bdnav/sound_parse.c
+
+sound_parse.obj: ../libbluray/bdnav/sound_parse.c
+ at am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sound_parse.obj -MD -MP -MF $(DEPDIR)/sound_parse.Tpo -c -o sound_parse.obj `if test -f '../libbluray/bdnav/sound_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/sound_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/sound_parse.c'; fi`
+ at am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/sound_parse.Tpo $(DEPDIR)/sound_parse.Po
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='../libbluray/bdnav/sound_parse.c' object='sound_parse.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sound_parse.obj `if test -f '../libbluray/bdnav/sound_parse.c'; then $(CYGPATH_W) '../libbluray/bdnav/sound_parse.c'; else $(CYGPATH_W) '$(srcdir)/../libbluray/bdnav/sound_parse.c'; fi`
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
diff --git a/src/examples/bdj_test.c b/src/examples/bdj_test.c
index dedd8b2..bb8a46f 100644
--- a/src/examples/bdj_test.c
+++ b/src/examples/bdj_test.c
@@ -36,23 +36,28 @@ void usage(void) {
     printf("Usage: [path to disc] [starting object]\n");
 }
 
-int main(int argc, char** argv) {
-    printf("%s %s\n", argv[1], argv[2]);
+int main(int argc, char** argv)
+{
     if (argc < 3) {
         usage();
         return 0;
     }
 
+    printf("%s %s\n", argv[1], argv[2]);
+
     BLURAY* bd = bd_open(argv[1], NULL);
 
-    bd_get_titles(bd, TITLES_ALL);
+    bd_get_titles(bd, TITLES_ALL, 0);
     bd_select_title(bd, 1);
 
-    if (bd_start_bdj(bd, argv[2]))
+    if (!bd_start_bdj(bd, argv[2])) {
         printf("Failed to start BD-J application.\n");
-    else {
+    } else {
         while (1) { sleep(20); }
         bd_stop_bdj(bd);
     }
+
+    bd_close(bd);
+
     return 0;
 }
diff --git a/src/examples/bdsplice.c b/src/examples/bdsplice.c
index d654541..4d61b06 100644
--- a/src/examples/bdsplice.c
+++ b/src/examples/bdsplice.c
@@ -141,7 +141,7 @@ main(int argc, char *argv[])
         return 1;
     }
 
-    title_count = bd_get_titles(bd, TITLES_RELEVANT);
+    title_count = bd_get_titles(bd, TITLES_RELEVANT, 0);
     if (title_count <= 0) {
         fprintf(stderr, "No titles found: %s\n", bdpath);
         return 1;
@@ -162,7 +162,7 @@ main(int argc, char *argv[])
         out = stdout;
     }
 
-    ti = bd_get_title_info(bd, title_no);
+    ti = bd_get_title_info(bd, title_no, angle);
 
     if (angle >= (int)ti->angle_count) {
         fprintf(stderr, "Invalid angle %d > angle count %d. Using angle 1.\n", 
diff --git a/src/examples/hdmv_test.c b/src/examples/hdmv_test.c
index c0037e7..fb542ba 100644
--- a/src/examples/hdmv_test.c
+++ b/src/examples/hdmv_test.c
@@ -58,6 +58,18 @@ static void _print_event(BD_EVENT *ev)
             printf("EVENT_STILL:\t%d\n", ev->param);
             break;
 
+        case BD_EVENT_SEEK:
+            printf("EVENT_SEEK:\t%d\n", ev->param);
+            break;
+
+        case BD_EVENT_STILL_TIME:
+            if (ev->param) {
+                printf("EVENT_STILL_TIME:\t%d\n", ev->param);
+            } else {
+                printf("EVENT_STILL_TIME:\tinfinite\n");
+            }
+            break;
+
         /* stream selection */
 
         case BD_EVENT_AUDIO_STREAM:
@@ -89,10 +101,9 @@ static void _print_event(BD_EVENT *ev)
             printf("EVENT_SECONDARY_VIDEO_SIZE:\t%s\n", ev->param==0 ? "PIP" : "fullscreen");
             break;
 
-
         default:
-          printf("UNKNOWN EVENT %d:\t%d\n", ev->event, ev->param);
-          break;
+            printf("UNKNOWN EVENT %d:\t%d\n", ev->event, ev->param);
+            break;
       }
 
       fflush(stdout);
diff --git a/src/examples/libbluray_test.c b/src/examples/libbluray_test.c
index 646d822..47e3014 100644
--- a/src/examples/libbluray_test.c
+++ b/src/examples/libbluray_test.c
@@ -41,11 +41,11 @@ int main(int argc, char *argv[])
 
     BD_DEBUG(DBG_BLURAY,"\nListing titles:\n");
 
-    count = bd_get_titles(bd, TITLES_RELEVANT);
+    count = bd_get_titles(bd, TITLES_RELEVANT, 0);
     for (ii = 0; ii < count; ii++)
     {
         BLURAY_TITLE_INFO* ti;
-        ti = bd_get_title_info(bd, ii);
+        ti = bd_get_title_info(bd, ii, 0);
         BD_DEBUG(DBG_BLURAY,
        "index: %d duration: %02"PRIu64":%02"PRIu64":%02"PRIu64" chapters: %d\n",
               ii,
diff --git a/src/examples/list_titles.c b/src/examples/list_titles.c
index 3f91f74..a987951 100644
--- a/src/examples/list_titles.c
+++ b/src/examples/list_titles.c
@@ -81,15 +81,11 @@ int main(int argc, char *argv[])
     }
     bd = bd_open(bd_dir, NULL);
 
-    count = bd_get_titles(bd, TITLES_RELEVANT);
+    count = bd_get_titles(bd, TITLES_RELEVANT, seconds);
     for (ii = 0; ii < count; ii++)
     {
         BLURAY_TITLE_INFO* ti;
-        ti = bd_get_title_info(bd, ii);
-        if (ti->duration / 90000 < seconds)
-        {
-            continue;
-        }
+        ti = bd_get_title_info(bd, ii, 0);
         printf(
        "index: %d duration: %02"PRIu64":%02"PRIu64":%02"PRIu64" chapters: %d angles: %u clips %u\n",
               ii + 1,
diff --git a/src/examples/mpls_dump.c b/src/examples/mpls_dump.c
index d9ed8d8..e1206e8 100644
--- a/src/examples/mpls_dump.c
+++ b/src/examples/mpls_dump.c
@@ -215,6 +215,12 @@ _show_details(MPLS_PL *pl, int level)
                         pi->connection_condition);
         indent_printf(level+1, "In-Time: %d", pi->in_time);
         indent_printf(level+1, "Out-Time: %d", pi->out_time);
+        if (pi->still_mode == 1) {
+            indent_printf(level+1, "Still time: %ds\n", pi->still_time);
+        }
+        if (pi->still_mode == 2) {
+            indent_printf(level+1, "Still time: infinite\n");
+        }
         if (pi->angle_count > 1) {
             for (jj = 1; jj < pi->angle_count; jj++) {
                 indent_printf(level+1, "Angle %d:", jj);
diff --git a/src/file/filesystem.h b/src/file/filesystem.h
index 4e707a2..5c2b9ce 100644
--- a/src/file/filesystem.h
+++ b/src/file/filesystem.h
@@ -21,6 +21,10 @@
 #ifndef BD_FILESYSTEM_H_
 #define BD_FILESYSTEM_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <stdint.h>
 
 /*
@@ -78,5 +82,8 @@ BD_FILE_OPEN bd_register_file(BD_FILE_OPEN p);
  */
 BD_DIR_OPEN bd_register_dir(BD_DIR_OPEN p);
 
+#ifdef __cplusplus
+};
+#endif
 
 #endif /* BD_FILESYSTEM_H_ */
diff --git a/src/libbluray/bdj/bdj_util.c b/src/libbluray/bdj/bdj_util.c
index a4e4b24..5bf4560 100644
--- a/src/libbluray/bdj/bdj_util.c
+++ b/src/libbluray/bdj/bdj_util.c
@@ -1,3 +1,6 @@
+
+#include "util/logging.h"
+
 #include "bdj_util.h"
 
 jobject bdj_make_object(JNIEnv* env, const char* name, const char* sig, ...)
@@ -5,6 +8,11 @@ jobject bdj_make_object(JNIEnv* env, const char* name, const char* sig, ...)
     jclass obj_class = (*env)->FindClass(env, name);
     jmethodID obj_constructor = (*env)->GetMethodID(env, obj_class, "<init>", sig);
 
+    if (!obj_class) {
+        BD_DEBUG(DBG_BDJ | DBG_CRIT, "Class %s not found\n", name);
+        return NULL;
+    }
+
     va_list ap;
     va_start(ap, sig);
     jobject obj = (*env)->NewObjectV(env, obj_class, obj_constructor, ap);
diff --git a/src/libbluray/bdj/bdjo_parser.c b/src/libbluray/bdj/bdjo_parser.c
index 94effb9..052e9e2 100644
--- a/src/libbluray/bdj/bdjo_parser.c
+++ b/src/libbluray/bdj/bdjo_parser.c
@@ -395,7 +395,9 @@ static jobject _parse_bdjo(JNIEnv* env, BITBUFFER* buf)
 
 jobject bdjo_read(JNIEnv* env, const char* file)
 {
+    jobject    result = NULL;
     BD_FILE_H *handle = file_open(file, "rb");
+
     if (handle == NULL) {
         BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to open bdjo file (%s)\n", file);
         return NULL;
@@ -404,26 +406,31 @@ jobject bdjo_read(JNIEnv* env, const char* file)
     file_seek(handle, 0, SEEK_END);
     int64_t length = file_tell(handle);
 
-    if (length > 0) {
+    if (length <= 0) {
+        BD_DEBUG(DBG_BDJ | DBG_CRIT, "Error reading %s\n", file);
+
+    } else {
         file_seek(handle, 0, SEEK_SET);
 
         uint8_t *data = malloc(length);
         int64_t size_read = file_read(handle, data, length);
+
         if (size_read < length) {
-            free(data);
-            return NULL;
-        }
+            BD_DEBUG(DBG_BDJ | DBG_CRIT, "Error reading %s\n", file);
 
-        BITBUFFER* buf = malloc(sizeof(BITBUFFER));
-        bb_init(buf, data, length);
+        } else {
+            BITBUFFER *buf = malloc(sizeof(BITBUFFER));
+            bb_init(buf, data, length);
 
-        jobject result = _parse_bdjo(env, buf);
+            result = _parse_bdjo(env, buf);
 
-        free(buf);
-        file_close(handle);
+            free(buf);
+        }
 
-        return result;
-    } else {
-        return NULL;
+        free(data);
     }
+
+    file_close(handle);
+
+    return result;
 }
diff --git a/src/libbluray/bdj/native/org_videolan_Libbluray.c b/src/libbluray/bdj/native/org_videolan_Libbluray.c
index b441a25..a85838c 100644
--- a/src/libbluray/bdj/native/org_videolan_Libbluray.c
+++ b/src/libbluray/bdj/native/org_videolan_Libbluray.c
@@ -81,7 +81,7 @@ JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getTitleInfoN
 {
     BDJAVA* bdj = (BDJAVA*)np;
 
-    BLURAY_TITLE_INFO* ti = bd_get_title_info(bdj->bd, title);
+    BLURAY_TITLE_INFO* ti = bd_get_title_info(bdj->bd, title, 0);
     if (!ti)
         return NULL;
 
@@ -96,7 +96,7 @@ JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getPlaylistInfoN
   (JNIEnv * env, jclass cls, jlong np, jint playlist)
 {
     BDJAVA* bdj = (BDJAVA*)np;
-    BLURAY_TITLE_INFO* ti = bd_get_playlist_info(bdj->bd, playlist);
+    BLURAY_TITLE_INFO* ti = bd_get_playlist_info(bdj->bd, playlist, 0);
     if (!ti)
         return NULL;
 
@@ -110,7 +110,7 @@ JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getPlaylistInfoN
 JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_getTitlesN(JNIEnv * env,
         jclass cls, jlong np, jchar flags) {
     BDJAVA* bdj = (BDJAVA*) np;
-    return bd_get_titles(bdj->bd, flags);
+    return bd_get_titles(bdj->bd, flags, 0);
 }
 
 JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekN(JNIEnv * env,
diff --git a/src/libbluray/bdnav/meta_parse.c b/src/libbluray/bdnav/meta_parse.c
index c6ffeff..24b4219 100644
--- a/src/libbluray/bdnav/meta_parse.c
+++ b/src/libbluray/bdnav/meta_parse.c
@@ -31,9 +31,12 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <strings.h>
 #include <errno.h>
 
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+
 #ifdef HAVE_LIBXML2
 #include <libxml/parser.h>
 #include <libxml/xmlmemory.h>
@@ -114,6 +117,7 @@ static void _findMetaXMLfiles(META_ROOT *meta, const char *device_path)
             meta->dl_entries[i].filename = str_printf("%s", ent.d_name);
             strncpy(meta->dl_entries[i].language_code, ent.d_name+5,3);
             meta->dl_entries[i].language_code[3] = '\0';
+            str_tolower(meta->dl_entries[i].language_code);
         }
     }
     dir_close(dir);
@@ -187,7 +191,7 @@ META_DL *meta_get(META_ROOT *meta_root, const char *language_code)
 
     if (language_code) {
         for (i = 0; i < meta_root->dl_count; i++) {
-            if (strcasecmp(language_code, meta_root->dl_entries[i].language_code) == 0) {
+            if (strcmp(language_code, meta_root->dl_entries[i].language_code) == 0) {
                 return &meta_root->dl_entries[i];
             }
         }
@@ -195,7 +199,7 @@ META_DL *meta_get(META_ROOT *meta_root, const char *language_code)
     }
 
     for (i = 0; i < meta_root->dl_count; i++) {
-        if (strcasecmp(DEFAULT_LANGUAGE, meta_root->dl_entries[i].language_code) == 0) {
+        if (strcmp(DEFAULT_LANGUAGE, meta_root->dl_entries[i].language_code) == 0) {
             BD_DEBUG(DBG_DIR, "using default disclib language '"DEFAULT_LANGUAGE"'\n");
             return &meta_root->dl_entries[i];
         }
diff --git a/src/libbluray/bdnav/navigation.c b/src/libbluray/bdnav/navigation.c
index 1f6895a..bce26a7 100644
--- a/src/libbluray/bdnav/navigation.c
+++ b/src/libbluray/bdnav/navigation.c
@@ -40,6 +40,9 @@ static int _filter_dup(MPLS_PL *pl_list[], unsigned count, MPLS_PL *pl)
         if (pl->list_count != pl_list[ii]->list_count) {
             continue;
         }
+        if (pl->mark_count != pl_list[ii]->mark_count) {
+            continue;
+        }
         for (jj = 0; jj < pl->list_count; jj++) {
             MPLS_PI *pi1, *pi2;
 
@@ -108,7 +111,7 @@ _pl_duration(MPLS_PL *pl)
     return duration;
 }
 
-NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags)
+NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags, uint32_t min_title_length)
 {
     BD_DIR_H *dir;
     BD_DIRENT ent;
@@ -130,6 +133,7 @@ NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags)
     if (dir == NULL) {
         BD_DEBUG(DBG_NAV, "Failed to open dir: %s\n", path);
         X_FREE(path);
+        X_FREE(title_list->title_info);
         X_FREE(title_list);
         return NULL;
     }
@@ -167,6 +171,11 @@ NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags)
                 mpls_free(pl);
                 continue;
             }
+            if (min_title_length > 0 &&
+                _pl_duration(pl) < min_title_length*45000) {
+                mpls_free(pl);
+                continue;
+            }
             if (ii >= title_info_alloc) {
                 NAV_TITLE_INFO *tmp = NULL;
                 title_info_alloc += 100;
@@ -388,6 +397,7 @@ _extrapolate_title(NAV_TITLE *title)
 static void _fill_clip(NAV_TITLE *title,
                        MPLS_CLIP *mpls_clip,
                        uint8_t connection_condition, uint32_t in_time, uint32_t out_time,
+                       unsigned pi_angle_count,
                        NAV_CLIP *clip,
                        unsigned ref, uint32_t *pos, uint32_t *time)
 
@@ -396,13 +406,20 @@ static void _fill_clip(NAV_TITLE *title,
 
     clip->title = title;
     clip->ref   = ref;
-    clip->angle = 0;
+
+    if (title->angle >= pi_angle_count) {
+        clip->angle = 0;
+    } else {
+        clip->angle = title->angle;
+    }
+
     strncpy(clip->name, mpls_clip[clip->angle].clip_id, 5);
     strncpy(&clip->name[5], ".m2ts", 6);
     clip->clip_id = atoi(mpls_clip[clip->angle].clip_id);
 
     path = str_printf("%s"DIR_SEP"BDMV"DIR_SEP"CLIPINF"DIR_SEP"%s.clpi",
                       title->root, mpls_clip[clip->angle].clip_id);
+    clpi_free(clip->cl);
     clip->cl = clpi_parse(path, 0);
     X_FREE(path);
     if (clip->cl == NULL) {
@@ -417,8 +434,12 @@ static void _fill_clip(NAV_TITLE *title,
             clip->connection = CONNECT_SEAMLESS;
             break;
         default:
-            clip->start_pkt = clpi_lookup_spn(clip->cl, in_time, 1,
+            if (ref) {
+                clip->start_pkt = clpi_lookup_spn(clip->cl, in_time, 1,
                                               mpls_clip[clip->angle].stc_id);
+            } else {
+                clip->start_pkt = 0;
+            }
             clip->connection = CONNECT_NON_SEAMLESS;
             break;
     }
@@ -432,7 +453,7 @@ static void _fill_clip(NAV_TITLE *title,
     *time += clip->out_time - clip->in_time;
 }
 
-NAV_TITLE* nav_title_open(const char *root, const char *playlist)
+NAV_TITLE* nav_title_open(const char *root, const char *playlist, unsigned angle)
 {
     NAV_TITLE *title = NULL;
     char *path;
@@ -451,7 +472,7 @@ NAV_TITLE* nav_title_open(const char *root, const char *playlist)
     path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "PLAYLIST" DIR_SEP "%s",
                       root, playlist);
     title->angle_count = 0;
-    title->angle = 0;
+    title->angle = angle;
     title->pl = mpls_parse(path, 0);
     if (title->pl == NULL) {
         BD_DEBUG(DBG_NAV, "Fail: Playlist parse %s\n", path);
@@ -472,7 +493,8 @@ NAV_TITLE* nav_title_open(const char *root, const char *playlist)
 
         clip = &title->clip_list.clip[ii];
 
-        _fill_clip(title, pi->clip, pi->connection_condition, pi->in_time, pi->out_time, clip, ii, &pos, &time);
+        _fill_clip(title, pi->clip, pi->connection_condition, pi->in_time, pi->out_time, pi->angle_count,
+                   clip, ii, &pos, &time);
     }
 
     // sub paths
@@ -493,7 +515,8 @@ NAV_TITLE* nav_title_open(const char *root, const char *playlist)
                 MPLS_SUB_PI *pi   = &title->pl->sub_path[ss].sub_play_item[ii];
                 NAV_CLIP    *clip = &sub_path->clip_list.clip[ii];
 
-                _fill_clip(title, pi->clip, pi->connection_condition, pi->in_time, pi->out_time, clip, ii, &pos, &time);
+                _fill_clip(title, pi->clip, pi->connection_condition, pi->in_time, pi->out_time, 0,
+                           clip, ii, &pos, &time);
             }
         }
     }
@@ -511,6 +534,11 @@ NAV_TITLE* nav_title_open(const char *root, const char *playlist)
     title->mark_list.mark = calloc(title->pl->mark_count, sizeof(NAV_MARK));
 
     _extrapolate_title(title);
+
+    if (title->angle >= title->angle_count) {
+        title->angle = 0;
+    }
+
     return title;
 }
 
@@ -744,7 +772,6 @@ NAV_CLIP* nav_next_clip(NAV_TITLE *title, NAV_CLIP *clip)
 
 NAV_CLIP* nav_set_angle(NAV_TITLE *title, NAV_CLIP *clip, unsigned angle)
 {
-    char *path;
     int ii;
     uint32_t pos = 0;
     uint32_t time = 0;
@@ -770,48 +797,9 @@ NAV_CLIP* nav_set_angle(NAV_TITLE *title, NAV_CLIP *clip, unsigned angle)
 
         pi = &title->pl->play_item[ii];
         clip = &title->clip_list.clip[ii];
-        if (title->angle >= pi->angle_count) {
-            clip->angle = 0;
-        } else {
-            clip->angle = title->angle;
-        }
 
-        clpi_free(clip->cl);
-
-        clip->ref = ii;
-        strncpy(clip->name, pi->clip[clip->angle].clip_id, 5);
-        strncpy(&clip->name[5], ".m2ts", 6);
-        clip->clip_id  = atoi(pi->clip[clip->angle].clip_id);
-
-        path = str_printf("%s"DIR_SEP"BDMV"DIR_SEP"CLIPINF"DIR_SEP"%s.clpi",
-                      title->root, pi->clip[clip->angle].clip_id);
-        clip->cl = clpi_parse(path, 0);
-        X_FREE(path);
-        if (clip->cl == NULL) {
-            clip->start_pkt = 0;
-            clip->end_pkt = 0;
-            continue;
-        }
-        switch (pi->connection_condition) {
-            case 5:
-            case 6:
-                clip->start_pkt = 0;
-                clip->connection = CONNECT_SEAMLESS;
-                break;
-            default:
-                clip->start_pkt = clpi_lookup_spn(clip->cl, pi->in_time, 1,
-                                                  pi->clip[clip->angle].stc_id);
-                clip->connection = CONNECT_NON_SEAMLESS;
-            break;
-        }
-        clip->end_pkt = clpi_lookup_spn(clip->cl, pi->out_time, 0,
-                                        pi->clip[clip->angle].stc_id);
-        clip->in_time = pi->in_time;
-        clip->out_time = pi->out_time;
-        clip->pos = pos;
-        pos += clip->end_pkt - clip->start_pkt;
-        clip->start_time = time;
-        time += clip->out_time - clip->in_time;
+        _fill_clip(title, pi->clip, pi->connection_condition, pi->in_time, pi->out_time, pi->angle_count,
+                   clip, ii, &pos, &time);
     }
     _extrapolate_title(title);
     return clip;
diff --git a/src/libbluray/bdnav/navigation.h b/src/libbluray/bdnav/navigation.h
index 88caa56..497e903 100644
--- a/src/libbluray/bdnav/navigation.h
+++ b/src/libbluray/bdnav/navigation.h
@@ -137,7 +137,7 @@ struct nav_title_list_s
 
 BD_PRIVATE uint8_t nav_lookup_aspect(NAV_CLIP *clip, int pid);
 BD_PRIVATE char* nav_find_main_title(const char *root);
-BD_PRIVATE NAV_TITLE* nav_title_open(const char *root, const char *playlist);
+BD_PRIVATE NAV_TITLE* nav_title_open(const char *root, const char *playlist, unsigned angle);
 BD_PRIVATE void nav_title_close(NAV_TITLE *title);
 BD_PRIVATE NAV_CLIP* nav_next_clip(NAV_TITLE *title, NAV_CLIP *clip);
 BD_PRIVATE NAV_CLIP* nav_packet_search(NAV_TITLE *title, uint32_t pkt, uint32_t *clip_pkt,
@@ -150,7 +150,7 @@ BD_PRIVATE NAV_CLIP* nav_mark_search(NAV_TITLE *title, unsigned mark, uint32_t *
 BD_PRIVATE uint32_t nav_angle_change_search(NAV_CLIP *clip, uint32_t pkt, uint32_t *time);
 BD_PRIVATE NAV_CLIP* nav_set_angle(NAV_TITLE *title, NAV_CLIP *clip, unsigned angle);
 
-BD_PRIVATE NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags);
+BD_PRIVATE NAV_TITLE_LIST* nav_get_title_list(const char *root, uint32_t flags, uint32_t min_title_length);
 BD_PRIVATE void nav_free_title_list(NAV_TITLE_LIST *title_list);
 
 #endif // _NAVIGATION_H_
diff --git a/src/libbluray/bdnav/uo_mask_table.h b/src/libbluray/bdnav/uo_mask_table.h
index 2b642ae..b5dceef 100644
--- a/src/libbluray/bdnav/uo_mask_table.h
+++ b/src/libbluray/bdnav/uo_mask_table.h
@@ -67,7 +67,7 @@ static inline BD_UO_MASK bd_uo_mask_combine(BD_UO_MASK a, BD_UO_MASK b)
     unsigned   i;
 
     for (i = 0; i < sizeof(BD_UO_MASK); i++) {
-        po[i] = pa[i] & pb[i];
+        po[i] = pa[i] | pb[i];
     }
 
     return o;
diff --git a/src/libbluray/bluray.c b/src/libbluray/bluray.c
index 8f627ee..4e2fce3 100644
--- a/src/libbluray/bluray.c
+++ b/src/libbluray/bluray.c
@@ -80,6 +80,8 @@ typedef struct {
     /* current aligned unit */
     uint16_t       int_buf_off;
 
+    BD_UO_MASK     uo_mask;
+
 } BD_STREAM;
 
 typedef struct {
@@ -323,6 +325,9 @@ static void _close_m2ts(BD_STREAM *st)
         file_close(st->fp);
         st->fp = NULL;
     }
+
+    /* reset UO mask */
+    memset(&st->uo_mask, 0, sizeof(st->uo_mask));
 }
 
 static int _open_m2ts(BLURAY *bd, BD_STREAM *st)
@@ -356,6 +361,10 @@ static int _open_m2ts(BLURAY *bd, BD_STREAM *st)
             }
 
             if (st == &bd->st0) {
+                MPLS_PL *pl = st->clip->title->pl;
+                st->uo_mask = bd_uo_mask_combine(pl->app_info.uo_mask,
+                                                 pl->play_item[st->clip->ref].uo_mask);
+
                 _update_clip_psrs(bd, st->clip);
             }
 
@@ -766,7 +775,8 @@ static int _libbdplus_open(BLURAY *bd, const char *keyfile_path)
         return 0;
     }
 
-    bd->bdplus = bd->bdplus_init(bd->device_path, keyfile_path, _libaacs_get_vid(bd) ?: vid);
+    const uint8_t *aacs_vid = (const uint8_t *)_libaacs_get_vid(bd);
+    bd->bdplus = bd->bdplus_init(bd->device_path, keyfile_path, aacs_vid ? aacs_vid : vid);
 
     if (bd->bdplus) {
         BD_DEBUG(DBG_BLURAY,"libbdplus initialized\n");
@@ -1191,7 +1201,10 @@ int bd_read(BLURAY *bd, unsigned char *buf, int len)
                         return 0;
                     }
                     if (pi->still_mode == BLURAY_STILL_TIME) {
-                        _queue_event(bd, (BD_EVENT){BD_EVENT_STILL_TIME, pi->still_time});
+                        if (bd->event_queue) {
+                            _queue_event(bd, (BD_EVENT){BD_EVENT_STILL_TIME, pi->still_time});
+                            return 0;
+                        }
                     }
 
                     // find next clip
@@ -1204,14 +1217,6 @@ int bd_read(BLURAY *bd, unsigned char *buf, int len)
                     if (!_open_m2ts(bd, st)) {
                         return -1;
                     }
-
-                    // timed still mode: allow application to process BD_EVENT_STILL_TIME.
-                    // next bd_read() will return new data.
-                    if (bd->event_queue) {
-                        if (pi->still_mode == BLURAY_STILL_TIME) {
-                            return 0;
-                        }
-                    }
                 }
 
                 if (_read_block(bd, st, bd->int_buf)) {
@@ -1249,6 +1254,24 @@ int bd_read(BLURAY *bd, unsigned char *buf, int len)
     return -1;
 }
 
+int bd_read_skip_still(BLURAY *bd)
+{
+    BD_STREAM *st = &bd->st0;
+
+    if (st->clip) {
+        MPLS_PI *pi = &st->clip->title->pl->play_item[st->clip->ref];
+
+        if (pi->still_mode == BLURAY_STILL_TIME) {
+            st->clip = nav_next_clip(bd->title, st->clip);
+            if (st->clip) {
+                return _open_m2ts(bd, st);
+            }
+        }
+    }
+
+    return 0;
+}
+
 /*
  * preloader for asynchronous sub paths
  */
@@ -1327,11 +1350,11 @@ static void _close_playlist(BLURAY *bd)
     }
 }
 
-static int _open_playlist(BLURAY *bd, const char *f_name)
+static int _open_playlist(BLURAY *bd, const char *f_name, unsigned angle)
 {
     _close_playlist(bd);
 
-    bd->title = nav_title_open(bd->device_path, f_name);
+    bd->title = nav_title_open(bd->device_path, f_name, angle);
     if (bd->title == NULL) {
         BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Unable to open title %s! (%p)\n",
               f_name, bd);
@@ -1375,7 +1398,7 @@ int bd_select_playlist(BLURAY *bd, uint32_t playlist)
         }
     }
 
-    result = _open_playlist(bd, f_name);
+    result = _open_playlist(bd, f_name, 0);
 
     X_FREE(f_name);
     return result;
@@ -1401,7 +1424,7 @@ int bd_select_title(BLURAY *bd, uint32_t title_idx)
     bd->title_idx = title_idx;
     f_name = bd->title_list->title_info[title_idx].name;
 
-    return _open_playlist(bd, f_name);
+    return _open_playlist(bd, f_name, 0);
 }
 
 uint32_t bd_get_current_title(BLURAY *bd)
@@ -1460,7 +1483,7 @@ void bd_seamless_angle_change(BLURAY *bd, unsigned angle)
  * title lists
  */
 
-uint32_t bd_get_titles(BLURAY *bd, uint8_t flags)
+uint32_t bd_get_titles(BLURAY *bd, uint8_t flags, uint32_t min_title_length)
 {
     if (!bd) {
         BD_DEBUG(DBG_BLURAY | DBG_CRIT, "bd_get_titles(NULL) failed (%p)\n", bd);
@@ -1470,7 +1493,7 @@ uint32_t bd_get_titles(BLURAY *bd, uint8_t flags)
     if (bd->title_list != NULL) {
         nav_free_title_list(bd->title_list);
     }
-    bd->title_list = nav_get_title_list(bd->device_path, flags);
+    bd->title_list = nav_get_title_list(bd->device_path, flags, min_title_length);
 
     if (!bd->title_list) {
         BD_DEBUG(DBG_BLURAY | DBG_CRIT, "nav_get_title_list(%s) failed (%p)\n", bd->device_path, bd);
@@ -1546,12 +1569,13 @@ static BLURAY_TITLE_INFO* _fill_title_info(NAV_TITLE* title, uint32_t title_idx,
     return title_info;
 }
 
-static BLURAY_TITLE_INFO *_get_title_info(BLURAY *bd, uint32_t title_idx, uint32_t playlist, const char *mpls_name)
+static BLURAY_TITLE_INFO *_get_title_info(BLURAY *bd, uint32_t title_idx, uint32_t playlist, const char *mpls_name,
+                                          unsigned angle)
 {
     NAV_TITLE *title;
     BLURAY_TITLE_INFO *title_info;
 
-    title = nav_title_open(bd->device_path, mpls_name);
+    title = nav_title_open(bd->device_path, mpls_name, angle);
     if (title == NULL) {
         BD_DEBUG(DBG_BLURAY | DBG_CRIT, "Unable to open title %s! (%p)\n",
               mpls_name, bd);
@@ -1564,7 +1588,7 @@ static BLURAY_TITLE_INFO *_get_title_info(BLURAY *bd, uint32_t title_idx, uint32
     return title_info;
 }
 
-BLURAY_TITLE_INFO* bd_get_title_info(BLURAY *bd, uint32_t title_idx)
+BLURAY_TITLE_INFO* bd_get_title_info(BLURAY *bd, uint32_t title_idx, unsigned angle)
 {
     if (bd->title_list == NULL) {
         BD_DEBUG(DBG_BLURAY, "Title list not yet read! (%p)\n", bd);
@@ -1577,15 +1601,16 @@ BLURAY_TITLE_INFO* bd_get_title_info(BLURAY *bd, uint32_t title_idx)
 
     return _get_title_info(bd,
                            title_idx, bd->title_list->title_info[title_idx].mpls_id,
-                           bd->title_list->title_info[title_idx].name);
+                           bd->title_list->title_info[title_idx].name,
+                           angle);
 }
 
-BLURAY_TITLE_INFO* bd_get_playlist_info(BLURAY *bd, uint32_t playlist)
+BLURAY_TITLE_INFO* bd_get_playlist_info(BLURAY *bd, uint32_t playlist, unsigned angle)
 {
     char *f_name = str_printf("%05d.mpls", playlist);
     BLURAY_TITLE_INFO *title_info;
 
-    title_info = _get_title_info(bd, 0, playlist, f_name);
+    title_info = _get_title_info(bd, 0, playlist, f_name, angle);
 
     X_FREE(f_name);
 
@@ -1869,6 +1894,8 @@ static int _play_bdj(BLURAY *bd, const char *name)
 
 static int _play_hdmv(BLURAY *bd, unsigned id_ref)
 {
+    int result = 1;
+
     bd->title_type = title_hdmv;
 
 #ifdef USING_BDJAVA
@@ -1876,16 +1903,16 @@ static int _play_hdmv(BLURAY *bd, unsigned id_ref)
 #endif
 
     if (!bd->hdmv_vm) {
-        bd->hdmv_vm = hdmv_vm_init(bd->device_path, bd->regs);
+        bd->hdmv_vm = hdmv_vm_init(bd->device_path, bd->regs, bd->index);
     }
 
     if (hdmv_vm_select_object(bd->hdmv_vm, id_ref)) {
-        return 0;
+        result = 0;
     }
 
     bd->hdmv_suspended = !hdmv_vm_running(bd->hdmv_vm);
 
-    return 1;
+    return result;
 }
 
 static int _play_title(BLURAY *bd, unsigned title)
@@ -1968,8 +1995,10 @@ int bd_play(BLURAY *bd)
 
     _init_event_queue(bd);
 
+    bd_psr_lock(bd->regs);
     bd_psr_register_cb(bd->regs, _process_psr_event, bd);
     _queue_initial_psr_events(bd);
+    bd_psr_unlock(bd->regs);
 
     return _play_title(bd, BLURAY_TITLE_FIRST_PLAY);
 }
@@ -1977,7 +2006,12 @@ int bd_play(BLURAY *bd)
 int bd_play_title(BLURAY *bd, unsigned title)
 {
     if (bd->title_type == title_undef && title != BLURAY_TITLE_FIRST_PLAY) {
-        // bd_play not called
+        BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_play_title(): bd_play() not called\n");
+        return 0;
+    }
+
+    if (bd->st0.uo_mask.title_search) {
+        BD_DEBUG(DBG_BLURAY|DBG_CRIT, "title search masked by stream\n");
         return 0;
     }
 
@@ -1998,7 +2032,12 @@ int bd_menu_call(BLURAY *bd, int64_t pts)
     }
 
     if (bd->title_type == title_undef) {
-        // bd_play not called
+        BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_menu_call(): bd_play() not called\n");
+        return 0;
+    }
+
+    if (bd->st0.uo_mask.menu_call) {
+        BD_DEBUG(DBG_BLURAY|DBG_CRIT, "menu call masked by stream\n");
         return 0;
     }
 
@@ -2007,6 +2046,10 @@ int bd_menu_call(BLURAY *bd, int64_t pts)
             BD_DEBUG(DBG_BLURAY|DBG_CRIT, "menu call masked by movie object\n");
             return 0;
         }
+
+        if (hdmv_vm_suspend_pl(bd->hdmv_vm) < 0) {
+            BD_DEBUG(DBG_BLURAY|DBG_CRIT, "bd_menu_call(): error storing playback location\n");
+        }
     }
 
     return _play_title(bd, BLURAY_TITLE_TOP_MENU);
@@ -2082,7 +2125,6 @@ static void _process_hdmv_vm_event(BLURAY *bd, HDMV_EVENT *hev)
             break;
 
         case HDMV_EVENT_IG_END:
-            BD_DEBUG(DBG_BLURAY|DBG_CRIT, "HDMV_EVENT_IG_END\n");
             _run_gc(bd, GC_CTRL_IG_END, 0);
             break;
 
diff --git a/src/libbluray/bluray.h b/src/libbluray/bluray.h
index d2ace64..11f838c 100644
--- a/src/libbluray/bluray.h
+++ b/src/libbluray/bluray.h
@@ -22,6 +22,10 @@
 #ifndef BLURAY_H_
 #define BLURAY_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * @file libbluray/bluray.h
  * external API header
@@ -170,9 +174,10 @@ typedef struct bd_title_info {
  *
  * @param bd  BLURAY object
  * @param flags  title flags
+ * @param min_title_length  filter out titles shorter than min_title_length seconds
  * @return number of titles found
  */
-uint32_t bd_get_titles(BLURAY *bd, uint8_t flags);
+uint32_t bd_get_titles(BLURAY *bd, uint8_t flags, uint32_t min_title_length);
 
 /**
  *
@@ -180,9 +185,10 @@ uint32_t bd_get_titles(BLURAY *bd, uint8_t flags);
  *
  * @param bd  BLURAY object
  * @param title_idx title index number
+ * @param angle angle number (chapter offsets and clip size depend on selected angle)
  * @return allocated BLURAY_TITLE_INFO object, NULL on error
  */
-BLURAY_TITLE_INFO* bd_get_title_info(BLURAY *bd, uint32_t title_idx);
+BLURAY_TITLE_INFO* bd_get_title_info(BLURAY *bd, uint32_t title_idx, unsigned angle);
 
 /**
  *
@@ -190,9 +196,10 @@ BLURAY_TITLE_INFO* bd_get_title_info(BLURAY *bd, uint32_t title_idx);
  *
  * @param bd  BLURAY object
  * @param playlist playlist number
+ * @param angle angle number (chapter offsets and clip size depend on selected angle)
  * @return allocated BLURAY_TITLE_INFO object, NULL on error
  */
-BLURAY_TITLE_INFO* bd_get_playlist_info(BLURAY *bd, uint32_t playlist);
+BLURAY_TITLE_INFO* bd_get_playlist_info(BLURAY *bd, uint32_t playlist, unsigned angle);
 
 /**
  *
@@ -250,6 +257,15 @@ int bd_read(BLURAY *bd, unsigned char *buf, int len);
 
 /**
  *
+ *  Continue reading after still mode clip
+ *
+ * @param bd  BLURAY object
+ * @return 0 on error
+ */
+int bd_read_skip_still(BLURAY *bd);
+
+/**
+ *
  *  Seek to a chapter. First chapter is 0
  *
  * @param bd  BLURAY object
@@ -633,4 +649,8 @@ struct clpi_cl *bd_get_clpi(BLURAY *bd, unsigned clip_ref);
  */
 void bd_free_clpi(struct clpi_cl *cl);
 
+#ifdef __cplusplus
+};
+#endif
+
 #endif /* BLURAY_H_ */
diff --git a/src/libbluray/decoders/graphics_controller.c b/src/libbluray/decoders/graphics_controller.c
index d48b057..8b33b81 100644
--- a/src/libbluray/decoders/graphics_controller.c
+++ b/src/libbluray/decoders/graphics_controller.c
@@ -31,6 +31,7 @@
 #include "../keys.h"
 
 #include <inttypes.h>
+#include <string.h>
 
 #define GC_ERROR(...) BD_DEBUG(DBG_GC | DBG_CRIT, __VA_ARGS__)
 #define GC_TRACE(...) BD_DEBUG(DBG_GC,            __VA_ARGS__)
@@ -66,7 +67,6 @@ struct graphics_controller_s {
     /* data */
     PG_DISPLAY_SET *pgs;
     PG_DISPLAY_SET *igs;
-    uint16_t       *enabled_button;
 
     /* */
     GRAPHICS_PROCESSOR *pgp;
@@ -209,7 +209,7 @@ static int _is_button_enabled(GRAPHICS_CONTROLLER *gc, BD_IG_PAGE *page, unsigne
 {
     unsigned ii;
     for (ii = 0; ii < page->num_bogs; ii++) {
-        if (gc->enabled_button[ii] == button_id) {
+        if (gc->bog_data[ii].enabled_button == button_id) {
             return 1;
         }
     }
@@ -245,11 +245,12 @@ static uint16_t _find_selected_button_id(GRAPHICS_CONTROLLER *gc)
     /* 2) fallback to current PSR10 value if it is valid */
     for (ii = 0; ii < page->num_bogs; ii++) {
         BD_IG_BOG *bog = &page->bog[ii];
+        uint16_t   enabled_button = gc->bog_data[ii].enabled_button;
 
-        if (button_id == gc->enabled_button[ii]) {
-            if (_find_button_bog(bog, gc->enabled_button[ii])) {
-                GC_TRACE("_find_selected_button_id() -> PSR10 #%d\n", gc->enabled_button[ii]);
-                return gc->enabled_button[ii];
+        if (button_id == enabled_button) {
+            if (_find_button_bog(bog, enabled_button)) {
+                GC_TRACE("_find_selected_button_id() -> PSR10 #%d\n", enabled_button);
+                return enabled_button;
             }
         }
     }
@@ -257,10 +258,11 @@ static uint16_t _find_selected_button_id(GRAPHICS_CONTROLLER *gc)
     /* 3) fallback to find first valid_button_id_ref from page */
     for (ii = 0; ii < page->num_bogs; ii++) {
         BD_IG_BOG *bog = &page->bog[ii];
+        uint16_t   enabled_button = gc->bog_data[ii].enabled_button;
 
-        if (_find_button_bog(bog, gc->enabled_button[ii])) {
-            GC_TRACE("_find_selected_button_id() -> first valid #%d\n", gc->enabled_button[ii]);
-            return gc->enabled_button[ii];
+        if (_find_button_bog(bog, enabled_button)) {
+            GC_TRACE("_find_selected_button_id() -> first valid #%d\n", enabled_button);
+            return enabled_button;
         }
     }
 
@@ -324,13 +326,15 @@ static void _reset_page_state(GRAPHICS_CONTROLLER *gc)
 
     page = _find_page(&s->ics->interactive_composition, page_id);
     if (!page) {
-        GC_ERROR("_reset_enabled_button(): unknown page #%d (have %d pages)\n",
+        GC_ERROR("_reset_page_state(): unknown page #%d (have %d pages)\n",
               page_id, s->ics->interactive_composition.num_pages);
         return;
     }
 
-    gc->enabled_button = realloc(gc->enabled_button,
-                                 page->num_bogs * sizeof(uint16_t));
+    size_t size = page->num_bogs * sizeof(*gc->bog_data);
+    gc->bog_data = realloc(gc->bog_data, size);
+
+    memset(gc->bog_data, 0, size);
 
     for (ii = 0; ii < page->num_bogs; ii++) {
         gc->bog_data[ii].enabled_button = page->bog[ii].default_valid_button_id_ref;
@@ -338,23 +342,29 @@ static void _reset_page_state(GRAPHICS_CONTROLLER *gc)
     }
 }
 
-static void _clear_osd(GRAPHICS_CONTROLLER *gc, int plane)
+static void _clear_osd_area(GRAPHICS_CONTROLLER *gc, int plane,
+                            uint16_t x, uint16_t y, uint16_t w, uint16_t h)
 {
     if (gc->overlay_proc) {
         /* clear plane */
         const BD_OVERLAY ov = {
             .pts     = -1,
             .plane   = plane,
-            .x       = 0,
-            .y       = 0,
-            .w       = 1920,
-            .h       = 1080,
+            .x       = x,
+            .y       = y,
+            .w       = w,
+            .h       = h,
             .palette = NULL,
             .img     = NULL,
         };
 
         gc->overlay_proc(gc->overlay_proc_handle, &ov);
     }
+}
+
+static void _clear_osd(GRAPHICS_CONTROLLER *gc, int plane)
+{
+    _clear_osd_area(gc, plane, 0, 0, 1920, 1080);
 
     if (plane == BD_OVERLAY_IG) {
         gc->ig_drawn      = 0;
@@ -401,7 +411,7 @@ static void _gc_reset(GRAPHICS_CONTROLLER *gc)
     pg_display_set_free(&gc->pgs);
     pg_display_set_free(&gc->igs);
 
-    X_FREE(gc->enabled_button);
+    X_FREE(gc->bog_data);
 }
 
 /*
@@ -486,11 +496,11 @@ void gc_free(GRAPHICS_CONTROLLER **p)
  * graphics stream input
  */
 
-void gc_decode_ts(GRAPHICS_CONTROLLER *gc, uint16_t pid, uint8_t *block, unsigned num_blocks, int64_t stc)
+int gc_decode_ts(GRAPHICS_CONTROLLER *gc, uint16_t pid, uint8_t *block, unsigned num_blocks, int64_t stc)
 {
     if (!gc) {
         GC_TRACE("gc_decode_ts(): no graphics controller\n");
-        return;
+        return -1;
     }
 
     if (pid >= 0x1400 && pid < 0x1500) {
@@ -512,7 +522,7 @@ void gc_decode_ts(GRAPHICS_CONTROLLER *gc, uint16_t pid, uint8_t *block, unsigne
 
         if (!gc->igs || !gc->igs->complete) {
             bd_mutex_unlock(&gc->mutex);
-            return;
+            return 0;
         }
 
         gc->popup_visible = 0;
@@ -520,6 +530,8 @@ void gc_decode_ts(GRAPHICS_CONTROLLER *gc, uint16_t pid, uint8_t *block, unsigne
         _select_page(gc, 0);
 
         bd_mutex_unlock(&gc->mutex);
+
+        return 1;
     }
 
     else if (pid >= 0x1200 && pid < 0x1300) {
@@ -532,9 +544,13 @@ void gc_decode_ts(GRAPHICS_CONTROLLER *gc, uint16_t pid, uint8_t *block, unsigne
                                      stc);
 
         if (!gc->pgs || !gc->pgs->complete) {
-            return;
+            return 0;
         }
+
+        return 1;
     }
+
+    return -1;
 }
 
 /*
@@ -542,7 +558,7 @@ void gc_decode_ts(GRAPHICS_CONTROLLER *gc, uint16_t pid, uint8_t *block, unsigne
  */
 
 static void _render_button(GRAPHICS_CONTROLLER *gc, BD_IG_BUTTON *button, BD_PG_PALETTE *palette,
-                           int state)
+                           int state, BOG_DATA *bog_data)
 {
     BD_PG_OBJECT *object    = NULL;
     BD_OVERLAY    ov;
@@ -550,16 +566,19 @@ static void _render_button(GRAPHICS_CONTROLLER *gc, BD_IG_BUTTON *button, BD_PG_
     object = _find_object_for_button(gc->igs, button, state, bog_data);
     if (!object) {
         GC_TRACE("_render_button(#%d): object (state %d) not found\n", button->id, state);
+
+        _clear_bog_area(gc, bog_data);
+
         return;
     }
 
     ov.pts   = -1;
     ov.plane = BD_OVERLAY_IG;
 
-    ov.x = button->x_pos;
-    ov.y = button->y_pos;
-    ov.w = object->width;
-    ov.h = object->height;
+    ov.x = bog_data->x = button->x_pos;
+    ov.y = bog_data->y = button->y_pos;
+    ov.w = bog_data->w = object->width;
+    ov.h = bog_data->h = object->height;
 
     ov.img     = object->img;
     ov.palette = palette->entry;
@@ -608,7 +627,7 @@ static void _render_page(GRAPHICS_CONTROLLER *gc,
 
     for (ii = 0; ii < page->num_bogs; ii++) {
         BD_IG_BOG    *bog      = &page->bog[ii];
-        unsigned      valid_id = gc->enabled_button[ii];
+        unsigned      valid_id = gc->bog_data[ii].enabled_button;
         BD_IG_BUTTON *button;
 
         button = _find_button_bog(bog, valid_id);
@@ -617,11 +636,11 @@ static void _render_page(GRAPHICS_CONTROLLER *gc,
             GC_TRACE("_render_page(): bog %d: button %d not found\n", ii, valid_id);
 
         } else if (button->id == activated_button_id) {
-            _render_button(gc, button, palette, BTN_ACTIVATED);
+            _render_button(gc, button, palette, BTN_ACTIVATED, &gc->bog_data[ii]);
 
         } else if (button->id == selected_button_id) {
 
-            _render_button(gc, button, palette, BTN_SELECTED);
+            _render_button(gc, button, palette, BTN_SELECTED, &gc->bog_data[ii]);
 
             if (button->auto_action_flag && cmds) {
                 cmds->num_nav_cmds = button->num_nav_cmds;
@@ -629,7 +648,7 @@ static void _render_page(GRAPHICS_CONTROLLER *gc,
             }
 
         } else {
-            _render_button(gc, button, palette, BTN_NORMAL);
+            _render_button(gc, button, palette, BTN_NORMAL, &gc->bog_data[ii]);
 
         }
     }
@@ -681,7 +700,7 @@ static int _user_input(GRAPHICS_CONTROLLER *gc, bd_vk_key_e key, GC_NAV_CMDS *cm
 
     for (ii = 0; ii < page->num_bogs; ii++) {
         BD_IG_BOG *bog      = &page->bog[ii];
-        unsigned   valid_id = gc->enabled_button[ii];
+        unsigned   valid_id = gc->bog_data[ii].enabled_button;
         BD_IG_BUTTON *button = _find_button_bog(bog, valid_id);
         if (!button) {
             continue;
@@ -744,7 +763,7 @@ static int _user_input(GRAPHICS_CONTROLLER *gc, bd_vk_key_e key, GC_NAV_CMDS *cm
     return 0;
 }
 
-static void _set_button_page(GRAPHICS_CONTROLLER *gc, uint32_t param, GC_NAV_CMDS *cmds)
+static void _set_button_page(GRAPHICS_CONTROLLER *gc, uint32_t param)
 {
     unsigned page_flag   = param & 0x80000000;
     unsigned effect_flag = param & 0x40000000;
@@ -820,7 +839,7 @@ static void _set_button_page(GRAPHICS_CONTROLLER *gc, uint32_t param, GC_NAV_CMD
         _select_button(gc, button_id);
     }
 
-    _render_page(gc, 0xffff, cmds);
+    _render_page(gc, 0xffff, NULL);
 }
 
 static void _enable_button(GRAPHICS_CONTROLLER *gc, uint32_t button_id, unsigned enable)
@@ -849,15 +868,15 @@ static void _enable_button(GRAPHICS_CONTROLLER *gc, uint32_t button_id, unsigned
     }
 
     if (enable) {
-        if (gc->enabled_button[bog_idx] == cur_btn_id) {
+        if (gc->bog_data[bog_idx].enabled_button == cur_btn_id) {
             /* selected button goes to disabled state */
             bd_psr_write(gc->regs, PSR_SELECTED_BUTTON_ID, 0x10000|button_id);
         }
-        gc->enabled_button[bog_idx] = button_id;
+        gc->bog_data[bog_idx].enabled_button = button_id;
 
     } else {
-        if (gc->enabled_button[bog_idx] == button_id) {
-            gc->enabled_button[bog_idx] = 0xffff;
+        if (gc->bog_data[bog_idx].enabled_button == button_id) {
+            gc->bog_data[bog_idx].enabled_button = 0xffff;
         }
 
         if (cur_btn_id == button_id) {
@@ -912,7 +931,7 @@ static int _mouse_move(GRAPHICS_CONTROLLER *gc, unsigned x, unsigned y, GC_NAV_C
 
     for (ii = 0; ii < page->num_bogs; ii++) {
         BD_IG_BOG    *bog      = &page->bog[ii];
-        unsigned      valid_id = gc->enabled_button[ii];
+        unsigned      valid_id = gc->bog_data[ii].enabled_button;
         BD_IG_BUTTON *button   = _find_button_bog(bog, valid_id);
 
         if (!button)
@@ -988,7 +1007,7 @@ int gc_run(GRAPHICS_CONTROLLER *gc, gc_ctrl_e ctrl, uint32_t param, GC_NAV_CMDS
     switch (ctrl) {
 
         case GC_CTRL_SET_BUTTON_PAGE:
-            _set_button_page(gc, param, cmds);
+            _set_button_page(gc, param);
             break;
 
         case GC_CTRL_VK_KEY:
diff --git a/src/libbluray/decoders/graphics_controller.h b/src/libbluray/decoders/graphics_controller.h
index a0123e2..33efdd2 100644
--- a/src/libbluray/decoders/graphics_controller.h
+++ b/src/libbluray/decoders/graphics_controller.h
@@ -40,15 +40,21 @@ typedef struct graphics_controller_s GRAPHICS_CONTROLLER;
 typedef void (*gc_overlay_proc_f)(void *, const struct bd_overlay_s * const);
 
 typedef enum {
-    GC_CTRL_NOP,
+    /* */
+    GC_CTRL_NOP,             /* No input. Render page / run timers / run animations */
+    GC_CTRL_RESET,           /* reset graphics controller */
+
+    /* user input */
     GC_CTRL_VK_KEY,          /* param: bd_vk_key_e */
+    GC_CTRL_MOUSE_MOVE,      /* move selected button to (x,y), param: (x<<16 | y) */
+
+    /* HDMV VM control messages */
     GC_CTRL_ENABLE_BUTTON,   /* param: button_id */
     GC_CTRL_DISABLE_BUTTON,  /* param: button_id */
     GC_CTRL_SET_BUTTON_PAGE,
     GC_CTRL_POPUP,           /* param: on/off */
     GC_CTRL_IG_END,          /* execution of IG object is complete */
-    GC_CTRL_RESET,           /* reset graphics controller */
-    GC_CTRL_MOUSE_MOVE,      /* move selected button to (x,y), param: (x<<16 | y) */
+
 } gc_ctrl_e;
 
 typedef struct {
@@ -69,11 +75,18 @@ BD_PRIVATE GRAPHICS_CONTROLLER *gc_init(struct bd_registers_s *regs,
 
 BD_PRIVATE void                 gc_free(GRAPHICS_CONTROLLER **p);
 
-/*
- * input stream (MPEG-TS IG stream)
+/**
+ *
+ *  Decode data from MPEG-TS input stream
+ *
+ * @param p  GRAPHICS_CONTROLLER object
+ * @param pid  mpeg-ts PID to decode (HDMV IG/PG stream)
+ * @param block  mpeg-ts data
+ * @param num_blocks  number of aligned units in data
+ * @param stc  current playback time
+ * @return <0 on error, 0 when not complete, >0 when complete
  */
-
-BD_PRIVATE void                 gc_decode_ts(GRAPHICS_CONTROLLER *p,
+BD_PRIVATE int                  gc_decode_ts(GRAPHICS_CONTROLLER *p,
                                              uint16_t pid,
                                              uint8_t *block, unsigned num_blocks,
                                              int64_t stc);
diff --git a/src/libbluray/decoders/graphics_processor.c b/src/libbluray/decoders/graphics_processor.c
index f3b9412..8dfde2f 100644
--- a/src/libbluray/decoders/graphics_processor.c
+++ b/src/libbluray/decoders/graphics_processor.c
@@ -73,28 +73,14 @@ void pg_display_set_free(PG_DISPLAY_SET **s)
  * segment handling
  */
 
-static PES_BUFFER *_find_segment_by_type(PES_BUFFER *p, uint8_t seg_type)
-{
-    while (p) {
-        if (p->buf[0] == seg_type) {
-            return p;
-        }
-        p = p->next;
-    }
-    return NULL;
-}
-
 static PES_BUFFER *_find_segment_by_idv(PES_BUFFER *p,
                                         uint8_t seg_type, unsigned idv_pos,
                                         uint8_t *idv, unsigned idv_len)
 {
-    while (NULL != (_find_segment_by_type(p, seg_type))) {
-        if (!memcmp(p->buf + idv_pos, idv, idv_len)) {
-            return p;
-        }
+    while (p && (p->buf[0] != seg_type || memcmp(p->buf + idv_pos, idv, idv_len))) {
         p = p->next;
     }
-    return NULL;
+    return p;
 }
 
 static void _join_fragments(PES_BUFFER *p1, PES_BUFFER *p2, int data_pos)
@@ -234,8 +220,8 @@ static int _decode_pds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
         for (ii = 0; ii < s->num_palette; ii++) {
             if (s->palette[ii].id == id) {
                 int rr;
-                if ( (s->ics && s->ics->composition_descriptor.state == 0)/* ||
-                     (s->pcs && s->pcs->composition_descriptor.state == 2)*/) {
+                if ( (s->ics && s->ics->composition_descriptor.state == 0) ||
+                     (s->pcs && s->pcs->composition_descriptor.state == 0)) {
                     /* 8.8.3.1.1 */
                     rr = pg_decode_palette_update(bb, &s->palette[ii]);
                 } else {
@@ -264,14 +250,44 @@ static int _decode_pds(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
     return 0;
 }
 
+static void _check_epoch_start(PG_DISPLAY_SET *s)
+{
+    if ((s->pcs && s->pcs->composition_descriptor.state == 2) ||
+        (s->ics && s->ics->composition_descriptor.state == 2)) {
+        /* epoch start, drop all cached data */
+
+        unsigned ii;
+        for (ii = 0; ii < s->num_object; ii++) {
+            pg_clean_object(&s->object[ii]);
+        }
+
+        s->num_palette = 0;
+        s->num_window  = 0;
+        s->num_object  = 0;
+
+        s->epoch_start = 1;
+
+    } else {
+        s->epoch_start = 0;
+    }
+}
+
 static int _decode_pcs(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
 {
-    (void)s;
-    (void)bb;
-    (void)p;
+    pg_free_composition(&s->pcs);
+    s->pcs = calloc(1, sizeof(*s->pcs));
 
-    BD_DEBUG(DBG_DECODE | DBG_CRIT, "unhandled segment type (PGS_PG_COMPOSITION)\n");
-    return 0;
+    if (!pg_decode_composition(bb, s->pcs)) {
+        pg_free_composition(&s->pcs);
+        return 0;
+    }
+
+    s->pcs->pts  = p->pts;
+    s->valid_pts = p->pts;
+
+    _check_epoch_start(s);
+
+    return 1;
 }
 
 static int _decode_ics(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
@@ -284,25 +300,10 @@ static int _decode_ics(PG_DISPLAY_SET *s, BITBUFFER *bb, PES_BUFFER *p)
         return 0;
     }
 
-    s->ics->pts = p->pts;
+    s->ics->pts  = p->pts;
+    s->valid_pts = p->pts;
 
-    s->valid_pts   = s->ics->pts;
-    s->epoch_start = 0;
-
-    if (s->ics->composition_descriptor.state == 2) {
-        /* epoch start, drop all cached data */
-
-        unsigned ii;
-        for (ii = 0; ii < s->num_object; ii++) {
-            pg_clean_object(&s->object[ii]);
-        }
-
-        s->num_palette = 0;
-        s->num_window = 0;
-        s->num_object = 0;
-
-        s->epoch_start = 1;
-    }
+    _check_epoch_start(s);
 
     return 1;
 }
@@ -357,9 +358,7 @@ int graphics_processor_decode_pes(PG_DISPLAY_SET **s, PES_BUFFER **p, int64_t st
         *s = calloc(1, sizeof(PG_DISPLAY_SET));
     }
 
-    (*s)->complete = 0;
-
-    while (*p && !(*s)->complete) {
+    while (*p) {
 
         /* time to decode next segment ? */
         if (stc >= 0 && (*p)->dts > stc) {
@@ -374,18 +373,30 @@ int graphics_processor_decode_pes(PG_DISPLAY_SET **s, PES_BUFFER **p, int64_t st
             return 0;
         }
 
+        if ((*p)->len <= 2) {
+            BD_DEBUG(DBG_DECODE, "segment too short, skipping (%d bytes)\n", (*p)->len);
+            pes_buffer_remove(p, *p);
+            continue;
+        }
+
+        /* decode segment */
+
         GP_TRACE("Decoding segment, dts %010"PRId64" pts %010"PRId64" len %d\n",
                  (*p)->dts, (*p)->pts, (*p)->len);
 
-        /* decode segment */
-        if ((*p)->len > 2) {
-            _decode_segment(*s, *p);
-        }
+        (*s)->complete = 0;
+
+        _decode_segment(*s, *p);
 
         pes_buffer_remove(p, *p);
+
+        if ((*s)->complete) {
+            return 1;
+        }
+
     }
 
-    return (*s)->complete;
+    return 0;
 }
 
 /*
@@ -436,5 +447,9 @@ int graphics_processor_decode_ts(GRAPHICS_PROCESSOR *p,
         unit += 6144;
     }
 
-    return graphics_processor_decode_pes(s, &p->queue, stc);
+    if (p->queue) {
+        return graphics_processor_decode_pes(s, &p->queue, stc);
+    }
+
+    return 0;
 }
diff --git a/src/libbluray/decoders/graphics_processor.h b/src/libbluray/decoders/graphics_processor.h
index 37f6287..698b3c4 100644
--- a/src/libbluray/decoders/graphics_processor.h
+++ b/src/libbluray/decoders/graphics_processor.h
@@ -48,7 +48,7 @@ typedef struct {
 
     /* only one of the following segments can be present */
     BD_IG_INTERACTIVE   *ics;
-    /*BD_PG_PRESENTATON_COMPOSITION_SEGMENT  *pcs;*/
+    BD_PG_COMPOSITION   *pcs;
 
 } PG_DISPLAY_SET;
 
@@ -61,23 +61,40 @@ BD_PRIVATE void pg_display_set_free(PG_DISPLAY_SET **s);
 BD_PRIVATE GRAPHICS_PROCESSOR *graphics_processor_init(void);
 BD_PRIVATE void                graphics_processor_free(GRAPHICS_PROCESSOR **p);
 
-/*
- *  stc:      current STC
+/**
  *
- *  return:   0 : wait for more data
- *            1 : display set complete
+ *  Decode data from MPEG-PES input stream
  *
  *  Only segments where DTS <= STC are decoded.
  *  If STC < 0, all segments are immediately decoded to display set.
  *
  *  All decoded PES packets are removed from buffer.
+ *
+ * @param s  display set
+ * @param buf  data to decode
+ * @param stc  current playback time
+ * @return 1 if display set was completed, 0 otherwise
  */
-
 BD_PRIVATE int
 graphics_processor_decode_pes(PG_DISPLAY_SET **s,
                               struct pes_buffer_s **buf,
                               int64_t stc);
 
+/**
+ *
+ *  Decode data from MPEG-TS input stream
+ *
+ *  Segments are queued and decoded when DTS <= STC.
+ *  If STC < 0, all segments are immediately decoded to display set.
+ *
+ * @param p  GRAPHICS_PROCESSOR object
+ * @param s  display set
+ * @param pid  mpeg-ts PID to decode (HDMV IG/PG stream)
+ * @param unit  mpeg-ts data
+ * @param num_units  number of aligned units in data
+ * @param stc  current playback time
+ * @return 1 if display set was completed, 0 otherwise
+ */
 BD_PRIVATE int
 graphics_processor_decode_ts(GRAPHICS_PROCESSOR *p,
                              PG_DISPLAY_SET **s,
diff --git a/src/libbluray/decoders/pg.h b/src/libbluray/decoders/pg.h
index c6b54b3..cbc9b99 100644
--- a/src/libbluray/decoders/pg.h
+++ b/src/libbluray/decoders/pg.h
@@ -85,5 +85,25 @@ typedef struct {
 
 } BD_PG_OBJECT;
 
+typedef struct {
+    int64_t       pts;
+
+    BD_PG_VIDEO_DESCRIPTOR        video_descriptor;
+    BD_PG_COMPOSITION_DESCRIPTOR  composition_descriptor;
+
+    uint8_t       palette_update_flag;
+    uint8_t       palette_id_ref;
+
+    unsigned                  num_composition_objects;
+    BD_PG_COMPOSITION_OBJECT *composition_object;
+
+} BD_PG_COMPOSITION;
+
+typedef struct {
+    int64_t       pts;
+
+    unsigned      num_windows;
+    BD_PG_WINDOW *window;
+} BD_PG_WINDOWS;
 
 #endif // _BD_PG_H_
diff --git a/src/libbluray/decoders/pg_decode.c b/src/libbluray/decoders/pg_decode.c
index 3fac4b2..2cafa16 100644
--- a/src/libbluray/decoders/pg_decode.c
+++ b/src/libbluray/decoders/pg_decode.c
@@ -196,6 +196,42 @@ int pg_decode_object(BITBUFFER *bb, BD_PG_OBJECT *p)
     return _decode_rle(bb, p);
 }
 
+int pg_decode_composition(BITBUFFER *bb, BD_PG_COMPOSITION *p)
+{
+    unsigned ii;
+
+    pg_decode_video_descriptor(bb, &p->video_descriptor);
+    pg_decode_composition_descriptor(bb, &p->composition_descriptor);
+
+    p->palette_update_flag = bb_read(bb, 1);
+    bb_skip(bb, 7);
+
+    p->palette_id_ref      = bb_read(bb, 8);
+
+    p->num_composition_objects = bb_read(bb, 8);
+    p->composition_object      = calloc(p->num_composition_objects, sizeof(BD_PG_COMPOSITION_OBJECT));
+
+    for (ii = 0; ii < p->num_composition_objects; ii++) {
+        pg_decode_composition_object(bb, &p->composition_object[ii]);
+    }
+
+    return 1;
+}
+
+int pg_decode_windows(BITBUFFER *bb, BD_PG_WINDOWS *p)
+{
+    unsigned ii;
+
+    p->num_windows = bb_read(bb, 8);
+    p->window = calloc(p->num_windows, sizeof(BD_PG_WINDOW));
+
+    for (ii = 0; ii < p->num_windows; ii++) {
+        pg_decode_window(bb, &p->window[ii]);
+    }
+
+    return 1;
+}
+
 /*
  * cleanup
  */
@@ -207,10 +243,17 @@ void pg_clean_object(BD_PG_OBJECT *p)
     }
 }
 
-void pg_free_window(BD_PG_WINDOW **p)
+void pg_clean_composition(BD_PG_COMPOSITION *p)
 {
-    if (p && *p) {
-        X_FREE(*p);
+    if (p) {
+        X_FREE(p->composition_object);
+    }
+}
+
+void pg_clean_windows(BD_PG_WINDOWS *p)
+{
+    if (p) {
+        X_FREE(p->window);
     }
 }
 
@@ -228,3 +271,19 @@ void pg_free_object(BD_PG_OBJECT **p)
         X_FREE(*p);
     }
 }
+
+void pg_free_composition(BD_PG_COMPOSITION **p)
+{
+    if (p && *p) {
+        pg_clean_composition(*p);
+        X_FREE(*p);
+    }
+}
+
+void pg_free_windows(BD_PG_WINDOWS **p)
+{
+    if (p && *p) {
+        pg_clean_windows(*p);
+        X_FREE(*p);
+    }
+}
diff --git a/src/libbluray/decoders/pg_decode.h b/src/libbluray/decoders/pg_decode.h
index 169efe7..975b9e2 100644
--- a/src/libbluray/decoders/pg_decode.h
+++ b/src/libbluray/decoders/pg_decode.h
@@ -42,15 +42,20 @@ BD_PRIVATE void pg_decode_composition_object(BITBUFFER *bb, BD_PG_COMPOSITION_OB
 BD_PRIVATE int pg_decode_palette_update(BITBUFFER *bb, BD_PG_PALETTE *p);
 BD_PRIVATE int pg_decode_palette(BITBUFFER *bb, BD_PG_PALETTE *p);
 BD_PRIVATE int pg_decode_object(BITBUFFER *bb, BD_PG_OBJECT *p);
+BD_PRIVATE int pg_decode_composition(BITBUFFER *bb, BD_PG_COMPOSITION *p);
+BD_PRIVATE int pg_decode_windows(BITBUFFER *bb, BD_PG_WINDOWS *p);
 
 /*
  * cleanup
  */
 
 BD_PRIVATE void pg_clean_object(BD_PG_OBJECT *p);
+BD_PRIVATE void pg_clean_composition(BD_PG_COMPOSITION *p);
+BD_PRIVATE void pg_clean_windows(BD_PG_WINDOWS *p);
 
-BD_PRIVATE void pg_free_window(BD_PG_WINDOW **p);
 BD_PRIVATE void pg_free_palette(BD_PG_PALETTE **p);
 BD_PRIVATE void pg_free_object(BD_PG_OBJECT **p);
+BD_PRIVATE void pg_free_composition(BD_PG_COMPOSITION **p);
+BD_PRIVATE void pg_free_windows(BD_PG_WINDOWS **p);
 
 #endif // _PG_DECODE_H_
diff --git a/src/libbluray/hdmv/hdmv_vm.c b/src/libbluray/hdmv/hdmv_vm.c
index 24707d8..715ed3a 100644
--- a/src/libbluray/hdmv/hdmv_vm.c
+++ b/src/libbluray/hdmv/hdmv_vm.c
@@ -23,6 +23,7 @@
 #include "hdmv_insn.h"
 #include "../register.h"
 
+#include "../bdnav/index_parse.h"
 #include "util/macro.h"
 #include "util/strutl.h"
 #include "util/logging.h"
@@ -62,6 +63,9 @@ struct hdmv_vm_s {
     /* suspended object */
     MOBJ_OBJECT *suspended_object;
     int          suspended_pc;
+
+    /* disc index (used to verify CALL_TITLE/JUMP_TITLE) */
+    INDX_ROOT   *indx;
 };
 
 /*
@@ -235,7 +239,7 @@ static int _queue_event(HDMV_VM *p, uint32_t event, uint32_t param)
  * vm init
  */
 
-HDMV_VM *hdmv_vm_init(const char *disc_root, BD_REGISTERS *regs)
+HDMV_VM *hdmv_vm_init(const char *disc_root, BD_REGISTERS *regs, INDX_ROOT *indx)
 {
     HDMV_VM *p = calloc(1, sizeof(HDMV_VM));
     char *file;
@@ -250,6 +254,7 @@ HDMV_VM *hdmv_vm_init(const char *disc_root, BD_REGISTERS *regs)
     }
 
     p->regs         = regs;
+    p->indx         = indx;
 
     bd_mutex_init(&p->mutex);
 
@@ -412,6 +417,21 @@ static int _resume_object(HDMV_VM *p, int psr_restore)
  * branching
  */
 
+static int _is_valid_title(HDMV_VM *p, int title)
+{
+    if (title == 0 || title == 0xffff) {
+        INDX_PLAY_ITEM *pi = (!title) ? &p->indx->top_menu : &p->indx->first_play;
+
+        if (pi->object_type == indx_object_type_hdmv &&  pi->hdmv.id_ref == 0xffff) {
+            /* no top menu or first play title (5.2.3.3) */
+            return 0;
+        }
+        return 1;
+    }
+
+    return title > 0 && title <= p->indx->num_titles;
+}
+
 static int _jump_object(HDMV_VM *p, int object)
 {
     if (object < 0 || object >= p->movie_objects->num_objects) {
@@ -437,7 +457,7 @@ static int _jump_object(HDMV_VM *p, int object)
 
 static int _jump_title(HDMV_VM *p, int title)
 {
-    if (title >= 0 && title <= 0xffff) {
+    if (_is_valid_title(p, title)) {
         BD_DEBUG(DBG_HDMV, "_jump_title(%d)\n", title);
 
         /* discard suspended object */
@@ -466,7 +486,7 @@ static int _call_object(HDMV_VM *p, int object)
 
 static int _call_title(HDMV_VM *p, int title)
 {
-    if (title >= 0 && title <= 0xffff) {
+    if (_is_valid_title(p, title)) {
         BD_DEBUG(DBG_HDMV, "_call_title(%d)\n", title);
 
         _suspend_object(p, 1);
@@ -1071,7 +1091,7 @@ int hdmv_vm_resume(HDMV_VM *p)
     return result;
 }
 
-int hdmv_vm_suspend(HDMV_VM *p)
+int hdmv_vm_suspend_pl(HDMV_VM *p)
 {
     int result = -1;
     bd_mutex_lock(&p->mutex);
diff --git a/src/libbluray/hdmv/hdmv_vm.h b/src/libbluray/hdmv/hdmv_vm.h
index 9c0d945..f86cf89 100644
--- a/src/libbluray/hdmv/hdmv_vm.h
+++ b/src/libbluray/hdmv/hdmv_vm.h
@@ -58,6 +58,7 @@ typedef struct hdmv_vm_event_s {
  */
 
 struct bd_registers_s;
+struct indx_root_s;
 
 /*
  *
@@ -65,7 +66,7 @@ struct bd_registers_s;
 
 typedef struct hdmv_vm_s HDMV_VM;
 
-BD_PRIVATE HDMV_VM *hdmv_vm_init(const char *disc_root, struct bd_registers_s *regs);
+BD_PRIVATE HDMV_VM *hdmv_vm_init(const char *disc_root, struct bd_registers_s *regs, struct indx_root_s *indx);
 BD_PRIVATE void     hdmv_vm_free(HDMV_VM **p);
 
 BD_PRIVATE int      hdmv_vm_select_object(HDMV_VM *p, int object);
@@ -79,7 +80,35 @@ BD_PRIVATE int      hdmv_vm_running(HDMV_VM *p);
 #define HDMV_TITLE_SEARCH_MASK  0x02
 BD_PRIVATE uint32_t hdmv_vm_get_uo_mask(HDMV_VM *p);
 
-BD_PRIVATE int      hdmv_vm_suspend(HDMV_VM *p);
+/**
+ *
+ *  Suspend playlist playback
+ *
+ *  This function assumes playlist is currently playing and
+ *  movie object execution is suspended at PLAY_PL instruction.
+ *
+ *  If resume_intention_flag of current movie object is 1:
+ *    Copy playback position PSRs to backup registers
+ *    (suspend playlist playback at current position)
+ *  If resume_intention_flag of current movie object is 0:
+ *    Discard current movie object
+ *
+ * @param p  HDMV_VM object
+ * @return 0 on success, -1 if error
+ */
+BD_PRIVATE int      hdmv_vm_suspend_pl(HDMV_VM *p);
+
+/**
+ *
+ *  Resume HDMV execution
+ *
+ *  Continue execution of movie object after playlist playback.
+ *  Do not restore backup PSRs.
+ *  This function is called when playlist playback ends.
+ *
+ * @param p  HDMV_VM object
+ * @return 0 on success, -1 if error
+ */
 BD_PRIVATE int      hdmv_vm_resume(HDMV_VM *p);
 
 #endif // _HDMV_VM_H_
diff --git a/src/libbluray/register.c b/src/libbluray/register.c
index c83fd7a..7621866 100644
--- a/src/libbluray/register.c
+++ b/src/libbluray/register.c
@@ -284,17 +284,23 @@ void bd_psr_reset_backup_registers(BD_REGISTERS *p)
 
 void bd_psr_restore_state(BD_REGISTERS *p)
 {
-    uint32_t old_psr[BD_PSR_COUNT];
+    uint32_t old_psr[13];
+    uint32_t new_psr[13];
 
     bd_psr_lock(p);
 
-    if (p->num_cb)
-        memcpy(old_psr, p->psr, sizeof(old_psr));
+    if (p->num_cb) {
+        memcpy(old_psr, p->psr, sizeof(old_psr[0]) * 13);
+    }
 
     /* restore backup registers */
     memcpy(p->psr + 4,  p->psr + 36, sizeof(uint32_t) * 5);
     memcpy(p->psr + 10, p->psr + 42, sizeof(uint32_t) * 3);
 
+    if (p->num_cb) {
+        memcpy(new_psr, p->psr, sizeof(new_psr[0]) * 13);
+    }
+
     /* init backup registers to default */
     memcpy(p->psr + 36, bd_psr_init + 36, sizeof(uint32_t) * 5);
     memcpy(p->psr + 42, bd_psr_init + 42, sizeof(uint32_t) * 3);
@@ -307,11 +313,11 @@ void bd_psr_restore_state(BD_REGISTERS *p)
         ev.ev_type = BD_PSR_RESTORE;
 
         for (i = 4; i < 13; i++) {
-            if (i != 9 && old_psr[i] != p->psr[i]) {
+            if (i != PSR_NAV_TIMER) {
 
                 ev.psr_idx = i;
                 ev.old_val = old_psr[i];
-                ev.new_val = p->psr[i];
+                ev.new_val = new_psr[i];
 
                 for (j = 0; j < p->num_cb; j++) {
                     p->cb[j].cb(p->cb[j].handle, &ev);
diff --git a/src/util/bits.h b/src/util/bits.h
index 1a1b099..c693aef 100644
--- a/src/util/bits.h
+++ b/src/util/bits.h
@@ -71,12 +71,12 @@ static inline void bs_init( BITSTREAM *bs, BD_FILE_H *fp )
     bb_init(&bs->bb, bs->buf, bs->size);
 }
 
-static inline int bb_pos( const BITBUFFER *bb )
+static inline off_t bb_pos( const BITBUFFER *bb )
 {
     return 8 * ( bb->p - bb->p_start ) + 8 - bb->i_left;
 }
 
-static inline int bs_pos( const BITSTREAM *bs )
+static inline off_t bs_pos( const BITSTREAM *bs )
 {
     return bs->pos * 8 + bb_pos(&bs->bb);
 }
diff --git a/src/util/log_control.h b/src/util/log_control.h
index f413dd2..abbdb4d 100644
--- a/src/util/log_control.h
+++ b/src/util/log_control.h
@@ -21,6 +21,10 @@
 #ifndef BD_LOG_CONTROL_H_
 #define BD_LOG_CONTROL_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <stdint.h>
 
 
@@ -57,5 +61,8 @@ void bd_set_debug_handler(BD_LOG_FUNC);
 void bd_set_debug_mask(uint32_t mask);
 uint32_t bd_get_debug_mask(void);
 
+#ifdef __cplusplus
+};
+#endif
 
 #endif /* BD_LOG_CONTROL_H_ */
diff --git a/src/util/strutl.c b/src/util/strutl.c
index acc4b06..8330280 100644
--- a/src/util/strutl.c
+++ b/src/util/strutl.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <ctype.h>
 
 char * str_printf(const char *fmt, ...)
 {
@@ -78,3 +79,11 @@ uint32_t str_to_uint32(const char *s, int n)
 
     return val;
 }
+
+void str_tolower(char *s)
+{
+    while (*s) {
+        *s = tolower(*s);
+        s++;
+    }
+}
diff --git a/src/util/strutl.h b/src/util/strutl.h
index aa00095..4e87b4f 100644
--- a/src/util/strutl.h
+++ b/src/util/strutl.h
@@ -27,5 +27,6 @@
 BD_PRIVATE char * str_printf(const char *fmt, ...) BD_ATTR_FORMAT_PRINTF(1,2) BD_ATTR_MALLOC;
 
 BD_PRIVATE uint32_t str_to_uint32(const char *s, int n);
+BD_PRIVATE void     str_tolower(char *s);
 
 #endif // STRUTL_H_

-- 
libbluray packaging



More information about the pkg-multimedia-commits mailing list