[Matroska-cvs] [matroska] r1270 - in trunk/DvdMenuXtractor: . Resources libdvdread libdvdread/dvdread libdvdread/src libdvdread/win32 mpegparser vobparser vobparser/iso

robux4 at matroska.org robux4 at matroska.org
Sun Jan 28 17:49:11 CET 2007


Author: robux4
Date: 2007-01-28 19:48:11 +0300 (Sun, 28 Jan 2007)
New Revision: 1270

Added:
   trunk/DvdMenuXtractor/DvdMenuXtractor.proj
   trunk/DvdMenuXtractor/Resources/
   trunk/DvdMenuXtractor/Resources/back.png
   trunk/DvdMenuXtractor/Resources/dmx.png
   trunk/DvdMenuXtractor/Resources/error.png
   trunk/DvdMenuXtractor/Resources/log.png
   trunk/DvdMenuXtractor/Resources/next.png
   trunk/DvdMenuXtractor/Resources/quit.png
   trunk/DvdMenuXtractor/Resources/warning.png
   trunk/DvdMenuXtractor/chaptermanager.cpp
   trunk/DvdMenuXtractor/chaptermanager.h
   trunk/DvdMenuXtractor/config.h
   trunk/DvdMenuXtractor/dmx.cpp
   trunk/DvdMenuXtractor/dmx.h
   trunk/DvdMenuXtractor/dmx.ico
   trunk/DvdMenuXtractor/dmx.rc
   trunk/DvdMenuXtractor/dmxconsole.cpp
   trunk/DvdMenuXtractor/dmxconsole.h
   trunk/DvdMenuXtractor/dmxlogwidget.cpp
   trunk/DvdMenuXtractor/dmxlogwidget.h
   trunk/DvdMenuXtractor/dmxlogwidget.ui
   trunk/DvdMenuXtractor/dmxselectionitem.cpp
   trunk/DvdMenuXtractor/dmxselectionitem.h
   trunk/DvdMenuXtractor/dmxselectiontree.cpp
   trunk/DvdMenuXtractor/dmxselectiontree.h
   trunk/DvdMenuXtractor/dmxwizard.cpp
   trunk/DvdMenuXtractor/dmxwizard.h
   trunk/DvdMenuXtractor/dmxwizard.qrc
   trunk/DvdMenuXtractor/dmxwizard.ui
   trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.h
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread.proj
   trunk/DvdMenuXtractor/libdvdread/libdvdread.proj
   trunk/DvdMenuXtractor/libdvdread/src/filestat.c
   trunk/DvdMenuXtractor/libdvdread/src/src.proj
   trunk/DvdMenuXtractor/libdvdread/win32/posix.h
   trunk/DvdMenuXtractor/libdvdread/win32/stdint.h
   trunk/DvdMenuXtractor/libdvdread/win32/win32.proj
   trunk/DvdMenuXtractor/logtextedit.cpp
   trunk/DvdMenuXtractor/logtextedit.h
   trunk/DvdMenuXtractor/main.cpp
   trunk/DvdMenuXtractor/mpegparser/mpegparser.proj
   trunk/DvdMenuXtractor/outputreader.cpp
   trunk/DvdMenuXtractor/outputreader.h
   trunk/DvdMenuXtractor/selectiontreeitem.cpp
   trunk/DvdMenuXtractor/selectiontreeitem.h
   trunk/DvdMenuXtractor/selectiontreesubitem.cpp
   trunk/DvdMenuXtractor/selectiontreesubitem.h
   trunk/DvdMenuXtractor/utilities.cpp
   trunk/DvdMenuXtractor/utilities.h
   trunk/DvdMenuXtractor/vobparser/
   trunk/DvdMenuXtractor/vobparser/IFOContent.cpp
   trunk/DvdMenuXtractor/vobparser/IFOContent.h
   trunk/DvdMenuXtractor/vobparser/IFOFile.cpp
   trunk/DvdMenuXtractor/vobparser/IFOFile.h
   trunk/DvdMenuXtractor/vobparser/VobParser.cpp
   trunk/DvdMenuXtractor/vobparser/VobParser.h
   trunk/DvdMenuXtractor/vobparser/iso/
   trunk/DvdMenuXtractor/vobparser/iso/iso-639.def
   trunk/DvdMenuXtractor/vobparser/iso/iso_lang.c
   trunk/DvdMenuXtractor/vobparser/iso/iso_lang.h
   trunk/DvdMenuXtractor/vobparser/vobparser.proj
Removed:
   trunk/DvdMenuXtractor/A52Decoder.cpp
   trunk/DvdMenuXtractor/A52Decoder.h
   trunk/DvdMenuXtractor/DvdMenuXtractor.bkl
   trunk/DvdMenuXtractor/DvdMenuXtractor.cfg
   trunk/DvdMenuXtractor/DvdMenuXtractor.cpp
   trunk/DvdMenuXtractor/DvdMenuXtractor.dsp
   trunk/DvdMenuXtractor/DvdMenuXtractor.dsw
   trunk/DvdMenuXtractor/DvdMenuXtractor.h
   trunk/DvdMenuXtractor/DvdMenuXtractor.ini
   trunk/DvdMenuXtractor/DvdMenuXtractor.rc
   trunk/DvdMenuXtractor/DvdMenuXtractor.sln
   trunk/DvdMenuXtractor/DvdMenuXtractor.vcproj
   trunk/DvdMenuXtractor/IFOFile.cpp
   trunk/DvdMenuXtractor/IFOFile.h
   trunk/DvdMenuXtractor/MPEG2Decoder.cpp
   trunk/DvdMenuXtractor/MPEG2Decoder.h
   trunk/DvdMenuXtractor/Makefile
   trunk/DvdMenuXtractor/MyWizard.cpp
   trunk/DvdMenuXtractor/MyWizard.h
   trunk/DvdMenuXtractor/README.txt
   trunk/DvdMenuXtractor/VobParser.cpp
   trunk/DvdMenuXtractor/VobParser.h
   trunk/DvdMenuXtractor/base64.cpp
   trunk/DvdMenuXtractor/base64.h
   trunk/DvdMenuXtractor/iso/
   trunk/DvdMenuXtractor/libdvdread/libdvdread.bkl
   trunk/DvdMenuXtractor/libdvdread/win32/libdvdread.vcproj
   trunk/DvdMenuXtractor/makefile.vc
   trunk/DvdMenuXtractor/resource/
   trunk/DvdMenuXtractor/win32/
Modified:
   trunk/DvdMenuXtractor/
   trunk/DvdMenuXtractor/libdvdread/dvdread/bswap.h
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.h
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.h
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.h
   trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread_internal.h
   trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_print.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_read.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_types.h
   trunk/DvdMenuXtractor/libdvdread/dvdread/nav_print.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/nav_read.c
   trunk/DvdMenuXtractor/libdvdread/dvdread/nav_types.h
   trunk/DvdMenuXtractor/libdvdread/src/disc_id.c
   trunk/DvdMenuXtractor/libdvdread/src/ifo_dump.c
   trunk/DvdMenuXtractor/libdvdread/src/play_title.c
   trunk/DvdMenuXtractor/libdvdread/src/title_info.c
   trunk/DvdMenuXtractor/libdvdread/win32/config.h
   trunk/DvdMenuXtractor/libdvdread/win32/dirent.c
   trunk/DvdMenuXtractor/libdvdread/win32/gtchar.h
   trunk/DvdMenuXtractor/libdvdread/win32/inttypes.h
   trunk/DvdMenuXtractor/mpegparser/Types.h
Log:
introducting the new DvdMenuXtractor, based on Qt4 and using coremake


Property changes on: trunk/DvdMenuXtractor
___________________________________________________________________
Name: svn:ignore
   - build

   + build
stderr.txt
stdout.txt

Name: svn:externals
   + coremake https://svn.matroska.org/svn/misc/coremake


Deleted: trunk/DvdMenuXtractor/A52Decoder.cpp

Deleted: trunk/DvdMenuXtractor/A52Decoder.h

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.bkl

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.cfg

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.cpp

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.dsp

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.dsw

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.h

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.ini

Added: trunk/DvdMenuXtractor/DvdMenuXtractor.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/DvdMenuXtractor.proj	2007-01-22 11:21:16 UTC (r=
ev 1269)
+++ trunk/DvdMenuXtractor/DvdMenuXtractor.proj	2007-01-28 16:48:11 UTC (r=
ev 1270)
@@ -0,0 +1,91 @@
+CONFIG_FILE config.h
+PLATFORM_FILES coremake
+
+WORKSPACE dmx
+{
+  USE DvdMenuXtractor
+}
+
+#include "*/*.proj"
+
+CON DvdMenuXtractor
+{
+  USE dvdread
+  USE vobparser
+  USE mpegparser
+
+  INCLUDE "$(QTDIR)/include/QtCore"
+  INCLUDE "$(QTDIR)/include/QtGui"
+  INCLUDE "$(QTDIR)/include/QtXml"
+  INCLUDE "$(QTDIR)/include"
+  INCLUDE(COMPILER_MSVC) libdvdread/win32
+  INCLUDE libdvdread
+ =20
+  DEFINE(QT_NO_DEBUG) QT_NO_DEBUG_STREAM
+ =20
+  LIBS_RELEASE(COMPILER_MSVC) qtmain.lib
+  LIBS_RELEASE(COMPILER_MSVC && CONFIG_STATIC) QtCore.lib
+  LIBS_RELEASE(COMPILER_MSVC && CONFIG_STATIC) QtGui.lib
+  LIBS_RELEASE(COMPILER_MSVC && CONFIG_STATIC) QtNetwork.lib
+  LIBS_RELEASE(COMPILER_MSVC && CONFIG_STATIC) QtXml.lib
+  LIBS_RELEASE(COMPILER_MSVC && !CONFIG_STATIC) QtCore4.lib
+  LIBS_RELEASE(COMPILER_MSVC && !CONFIG_STATIC) QtGui4.lib
+  LIBS_RELEASE(COMPILER_MSVC && !CONFIG_STATIC) QtNetwork4.lib
+  LIBS_RELEASE(COMPILER_MSVC && !CONFIG_STATIC) QtXml4.lib
+  LIBS_DEBUG(COMPILER_MSVC) qtmaind.lib
+  LIBS_DEBUG(COMPILER_MSVC && CONFIG_STATIC) QtCored.lib
+  LIBS_DEBUG(COMPILER_MSVC && CONFIG_STATIC) QtGuid.lib
+  LIBS_DEBUG(COMPILER_MSVC && CONFIG_STATIC) QtNetworkd.lib
+  LIBS_DEBUG(COMPILER_MSVC && CONFIG_STATIC) QtXmld.lib
+  LIBS_DEBUG(COMPILER_MSVC && !CONFIG_STATIC) QtCored4.lib
+  LIBS_DEBUG(COMPILER_MSVC && !CONFIG_STATIC) QtGuid4.lib
+  LIBS_DEBUG(COMPILER_MSVC && !CONFIG_STATIC) QtNetworkd4.lib
+  LIBS_DEBUG(COMPILER_MSVC && !CONFIG_STATIC) QtXml4.lib
+  LIBS(COMPILER_GCC) qtmain
+  LIBS(COMPILER_GCC && CONFIG_STATIC) QtNetwork
+  LIBS(COMPILER_GCC && CONFIG_STATIC) QtGui
+  LIBS(COMPILER_GCC && CONFIG_STATIC) QtCore
+  LIBS(COMPILER_GCC && CONFIG_STATIC) QtXml
+  LIBS(COMPILER_GCC && !CONFIG_STATIC) QtNetwork4
+  LIBS(COMPILER_GCC && !CONFIG_STATIC) QtGui4
+  LIBS(COMPILER_GCC && !CONFIG_STATIC) QtCore4
+  LIBS(COMPILER_GCC && !CONFIG_STATIC) QtXml4
+  LIBS(TARGET_WIN) imm32.lib
+  LIBS(TARGET_WIN) winmm.lib
+  LIBS(TARGET_WIN) ws2_32.lib
+
+  LIBINCLUDE "$(QTDIR)/lib"
+
+  SOURCE chaptermanager.cpp
+  SOURCE dmx.cpp
+  SOURCE dmxconsole.cpp
+  SOURCE dmxlogwidget.cpp
+  SOURCE dmxselectionitem.cpp
+  SOURCE dmxselectiontree.cpp
+  SOURCE dmxwizard.cpp
+  SOURCE logtextedit.cpp
+  SOURCE main.cpp
+  SOURCE outputreader.cpp
+  SOURCE selectiontreeitem.cpp
+  SOURCE selectiontreesubitem.cpp
+  SOURCE utilities.cpp
+  SOURCE(TARGET_WIN) dmx.rc
+
+  HEADER chaptermanager.h
+  HEADER_QT4 dmx.h
+  HEADER dmxconsole.h
+  HEADER_QT4 dmxlogwidget.h
+  HEADER dmxselectionitem.h
+  HEADER_QT4 dmxselectiontree.h
+  HEADER_QT4 dmxwizard.h
+  HEADER_QT4 logtextedit.h
+  HEADER_QT4 outputreader.h
+  HEADER selectiontreeitem.h
+  HEADER selectiontreesubitem.h
+  HEADER utilities.h
+ =20
+  UI_FORM_QT4 dmxlogwidget.ui
+  UI_FORM_QT4 dmxwizard.ui
+ =20
+  RESOURCE_QT4 dmxwizard.qrc
+}

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.rc

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.sln

Deleted: trunk/DvdMenuXtractor/DvdMenuXtractor.vcproj

Deleted: trunk/DvdMenuXtractor/IFOFile.cpp

Deleted: trunk/DvdMenuXtractor/IFOFile.h

Deleted: trunk/DvdMenuXtractor/MPEG2Decoder.cpp

Deleted: trunk/DvdMenuXtractor/MPEG2Decoder.h

Deleted: trunk/DvdMenuXtractor/Makefile

Deleted: trunk/DvdMenuXtractor/MyWizard.cpp

Deleted: trunk/DvdMenuXtractor/MyWizard.h

Deleted: trunk/DvdMenuXtractor/README.txt

Added: trunk/DvdMenuXtractor/Resources/back.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/Resources/back.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/DvdMenuXtractor/Resources/dmx.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/Resources/dmx.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/DvdMenuXtractor/Resources/error.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/Resources/error.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/DvdMenuXtractor/Resources/log.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/Resources/log.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/DvdMenuXtractor/Resources/next.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/Resources/next.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/DvdMenuXtractor/Resources/quit.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/Resources/quit.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/DvdMenuXtractor/Resources/warning.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/Resources/warning.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Deleted: trunk/DvdMenuXtractor/VobParser.cpp

Deleted: trunk/DvdMenuXtractor/VobParser.h

Deleted: trunk/DvdMenuXtractor/base64.cpp

Deleted: trunk/DvdMenuXtractor/base64.h

Added: trunk/DvdMenuXtractor/chaptermanager.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/chaptermanager.cpp	2007-01-22 11:21:16 UTC (rev=
 1269)
+++ trunk/DvdMenuXtractor/chaptermanager.cpp	2007-01-28 16:48:11 UTC (rev=
 1270)
@@ -0,0 +1,689 @@
+#include "chaptermanager.h"
+#include "utilities.h"
+
+#include <QtXml>
+
+QString ChapterManager::INFO_SUFFIX ("_info.xml");
+QString ChapterManager::CHAPTER_SUFFIX ("_menu.xml");
+
+bool ChapterManager::generateScript(const IFOFile& ifoFile, const QStrin=
g& filename, uint16_t title, const QString& editionUID) const
+{
+	static unsigned char _PrivateVTS[] =3D {0x30, 0x80, 0x00, 0x00};
+	static unsigned char _PrivateTT[]  =3D {0x28, 0x00, 0x00, 0x00};
+	uint64_t start_timeH =3D uint64_t(-1);
+
+	generateInfoScript(filename, title, editionUID);
+
+	// create document
+	QDomDocument document;
+
+	// specify processing info
+	document.appendChild(document.createProcessingInstruction("xml", "versi=
on=3D\"1.0\" encoding=3D\"UTF-8\" standalone=3D\"no\""));
+	document.appendChild(document.implementation().createDocumentType("Chap=
ters", QString::null, "matroskachapters.dtd"));
+
+	// create comments
+	document.appendChild(document.createComment("Created with " + Utilities=
::APPLICATION_NAME + " " + Utilities::APPLICATION_VERSION));
+
+	// create the root element
+	QDomNode root =3D document.createElement("Chapters");
+	document.appendChild(root);
+
+	// VTS content
+	QDomElement editionEntryElement =3D document.createElement("EditionEntr=
y");
+	root.appendChild(editionEntryElement);
+=09
+	editionEntryElement.appendChild(CreateDOMElement(document, "EditionUID"=
, editionUID));
+	editionEntryElement.appendChild(CreateDOMElement(document, "EditionFlag=
Ordered", "1"));
+	editionEntryElement.appendChild(document.createComment("Video Title Set=
"));
+
+	QDomElement chapterAtomElement =3D document.createElement("ChapterAtom"=
);
+	editionEntryElement.appendChild(chapterAtomElement);
+
+	QString _myUIDa =3D Utilities::CreateUID();
+	chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUID",=
 _myUIDa));
+	chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterFlagH=
idden", "1"));
+=09
+	_PrivateVTS[2] =3D title >> 8;
+	_PrivateVTS[3] =3D title & 0xFF;
+	AddCodecPrivateData(document, chapterAtomElement, _PrivateVTS, 4);
+
+	QDomNode chapterAtomParentElement =3D chapterAtomElement;
+
+	if (ifoFile.VtsTitles(title) && ifoFile.VtsPGCs(title))
+	{
+		for (int i =3D 0; i < ifoFile.VtsTitles(title)->nr_of_srpts; i++)
+		{
+			uint64_t start_time =3D uint64_t(-1), found_time;
+		=09
+			chapterAtomParentElement.appendChild(document.createComment(QString("=
Title TTU_%1").arg(i + 1)));
+			QDomElement chapterAtomElement =3D document.createElement("ChapterAto=
m");
+			chapterAtomParentElement.appendChild(chapterAtomElement);
+		=09
+			QString _myUIDa =3D Utilities::CreateUID();
+			chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUID=
", _myUIDa));
+			chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterFla=
gHidden", "1"));
+
+			// get the Title -> VTS+TTN map
+			const tt_srpt_t *p_map =3D ifoFile.TitleMap();
+
+			if ( p_map !=3D NULL )
+			{
+				for (int j=3D0; j<p_map->nr_of_srpts; j++)
+				{
+					if ( ( p_map->title[j].title_set_nr =3D=3D title ) && ( p_map->titl=
e[j].vts_ttn =3D=3D i+1 ) )
+					{
+						_PrivateTT[1] =3D (j+1) >> 8;   // Title#
+						_PrivateTT[2] =3D (j+1) & 0xFF;
+						_PrivateTT[3] =3D i+1;          // VTS_TTN#
+						AddCodecPrivateData(document, chapterAtomElement, _PrivateTT, 4);
+						break;
+					}
+				}
+			}
+
+			// add the PGC that match this PTT
+			for (int k =3D 0; k < ifoFile.VtsPGCs(title)->nr_of_pgci_srp; k++)
+			{
+				if ((ifoFile.VtsPGCs(title)->pgci_srp[k].entry_id & 0x7F) =3D=3D i+1=
)
+				{
+					found_time =3D AddPGC(document, chapterAtomElement,=20
+						ifoFile.VtsPGCs(title)->pgci_srp[k].pgc, k, 0, ifoFile.CellsList(t=
itle, false), &ifoFile.VtsTitles(title)->title[i], i+1);
+				=09
+					if (start_time > found_time)
+						start_time =3D found_time;
+				}
+			}
+
+			chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterTim=
eStart", Utilities::FormatTime(start_time)));
+
+			if (start_timeH > start_time)
+				start_timeH =3D start_time;
+		}
+	}
+
+	if (start_timeH =3D=3D uint64_t(-1))
+		start_timeH =3D 0;
+
+	chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterTimeS=
tart", Utilities::FormatTime(start_timeH)));
+=09
+	QString output =3D document.toString(INDENT_COUNT);
+
+	// TODO: not a good approach
+	output.replace("-->", "-->\n");
+
+	// chapter file
+	QFile chapterFile (filename + CHAPTER_SUFFIX);
+	if (!chapterFile.open(QIODevice::WriteOnly | QIODevice::Text))
+		throw;
+
+	chapterFile.write(output.toUtf8());
+	chapterFile.close();
+
+	return true;
+}
+
+bool ChapterManager::generateMenuScript(const IFOFile& ifoFile, const QS=
tring& filename, uint16_t title, const QString& editionUID) const
+{
+	static unsigned char _PrivateFP[]  =3D {0x30, 0x00, 0x00, 0x00};
+	static unsigned char _PrivateVM[]  =3D {0x30, 0xC0, 0x00, 0x00};
+	static unsigned char _PrivateVTS[] =3D {0x30, 0x40, 0x00, 0x00};
+
+	// generate info script
+	generateInfoScript(filename, title, editionUID);
+
+	// create document
+	QDomDocument document;
+
+	// specify processing info
+	document.appendChild(document.createProcessingInstruction("xml", "versi=
on=3D\"1.0\" encoding=3D\"UTF-8\" standalone=3D\"no\""));
+	document.appendChild(document.implementation().createDocumentType("Chap=
ters", QString::null, "matroskachapters.dtd"));
+
+	// create comments
+	document.appendChild(document.createComment("Created with " + Utilities=
::APPLICATION_NAME + " " + Utilities::APPLICATION_VERSION));
+
+	// create the root element
+	QDomNode parentElement =3D document.createElement("Chapters");
+	document.appendChild(parentElement);
+
+	// create Edition Entry Element and add to root
+	QDomElement currentElement =3D document.createElement("EditionEntry");
+	parentElement.appendChild(currentElement);
+=09
+	// use Edition Entry Element as parent
+	parentElement =3D currentElement;
+
+	// add EditionUID and EDitionFlagOrdered elements
+	parentElement.appendChild(CreateDOMElement(document, "EditionUID", edit=
ionUID));
+	parentElement.appendChild(CreateDOMElement(document, "EditionFlagOrdere=
d", "1"));
+
+	// Write the first play PGC
+	if (title =3D=3D 0 && ifoFile.FirstPlayPGC())
+	{
+		// add comment to Edition Entry Element
+		parentElement.appendChild(document.createComment("First Play PGC"));
+
+		// add Chapter Atom
+		QDomElement chapterAtomElement =3D document.createElement("ChapterAtom=
");
+		parentElement.appendChild(chapterAtomElement);
+
+		// create and set UID
+		QString _myUID =3D Utilities::CreateUID();
+		chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUID"=
, _myUID));
+
+		// the First Play PGC has no cell and no time
+		AddChapterTime(document, chapterAtomElement, 0, 0);
+
+		// display the UID for the lazy rippers
+		chapterAtomElement.appendChild(document.createComment("Enter your text=
 here"));
+
+		// add Chapter Display Element
+		currentElement =3D document.createElement("ChapterDisplay");
+		currentElement.appendChild(CreateDOMElement(document, "ChapterString",=
 "First Play PGC " + _myUID));
+		chapterAtomElement.appendChild(currentElement);
+
+		// add Chapter Process Element
+		currentElement =3D document.createElement("ChapterProcess");
+		AddCodecPrivateData(document, currentElement, _PrivateFP, 4, false);
+		chapterAtomElement.appendChild(currentElement);
+
+		// PGC commands
+		AddPGCCommands(document, currentElement, ifoFile.FirstPlayPGC()->comma=
nd_tbl);
+	}
+
+	// Write the Video Title Set
+	if (ifoFile.LanguageUnits(title) && ifoFile.LanguageUnits(title)->nr_of=
_lus)
+	{
+		// VTS Menu
+		if ( title =3D=3D 0 )
+			parentElement.appendChild(document.createComment("Video Manager"));
+		else
+			parentElement.appendChild(document.createComment("Video Title Set"));
+
+		// add another Chapter Atom element
+		currentElement =3D document.createElement("ChapterAtom");
+		parentElement.appendChild(currentElement);
+
+		QString _myUIDa =3D Utilities::CreateUID();
+		currentElement.appendChild(CreateDOMElement(document, "ChapterUID", _m=
yUIDa));
+		currentElement.appendChild(CreateDOMElement(document, "ChapterFlagHidd=
en", "1"));
+
+		if ( title !=3D 0 )
+		{
+			_PrivateVTS[2] =3D title >> 8;
+			_PrivateVTS[3] =3D title & 0xFF;
+			AddCodecPrivateData(document, currentElement, _PrivateVTS, 4);
+		}
+		else
+		{
+			_PrivateVM[2] =3D 0;
+			_PrivateVM[3] =3D 0;
+			AddCodecPrivateData(document, currentElement, _PrivateVM, 4);
+		}
+
+		uint64_t start_time =3D HandleLanguageUnit(document, currentElement, i=
foFile, title);
+
+		currentElement.appendChild(CreateDOMElement(document, "ChapterTimeStar=
t", Utilities::FormatTime(start_time)));
+	}
+
+	// get document string representation
+	QString output =3D document.toString(INDENT_COUNT);
+
+	// TODO: not a good approach
+	output.replace("-->", "-->\n");
+
+	// chapter file
+	QFile chapterFile(filename + CHAPTER_SUFFIX);
+	if (!chapterFile.open(QIODevice::WriteOnly | QIODevice::Text))
+		throw;
+=09
+	// write to the chpater file
+	chapterFile.write(output.toUtf8());
+	chapterFile.close();
+
+	return true;
+}
+
+void ChapterManager::generateInfoScript(const QString &filename, uint16_=
t title, const QString &editionUID) const
+{
+	// create document
+	QDomDocument document;
+
+	// specify xml version, encoding and DocType
+	document.appendChild(document.createProcessingInstruction("xml", "versi=
on=3D\"1.0\" encoding=3D\"UTF-8\" standalone=3D\"no\""));
+	document.appendChild(document.implementation().createDocumentType("Chap=
ters", QString::null, "matroskainfos.dtd"));
+
+	// add root element
+	QDomNode parentElement =3D document.createElement("Info");
+	document.appendChild(parentElement);
+
+	// add Segment Family Element
+	QDomElement currentElement =3D CreateDOMElement(document, "SegmentFamil=
y", Utilities::EncodeHex(familyUID, 16));
+	currentElement.setAttribute("format", "hex");
+	parentElement.appendChild(currentElement);
+
+	// add Chapter Translate Element
+	currentElement =3D document.createElement("ChapterTranslate");
+	currentElement.appendChild(CreateDOMElement(document, "ChapterTranslate=
EditionUID", editionUID));
+	currentElement.appendChild(CreateDOMElement(document, "ChapterTranslate=
Codec", "1"));
+=09
+	QDomElement chapterTranslateIDElement =3D CreateDOMElement(document, "C=
hapterTranslateID", QString("%1 00").arg(title, 2, 16, QChar('0')));
+	chapterTranslateIDElement.setAttribute("format", "hex");
+	currentElement.appendChild(chapterTranslateIDElement);
+
+	parentElement.appendChild(currentElement);
+
+	// get document string representation
+	QString output =3D document.toString(INDENT_COUNT);
+=09
+	// segment file
+	QFile segementFile(filename + INFO_SUFFIX);
+	if (!segementFile.open(QIODevice::WriteOnly | QIODevice::Text))
+		throw;
+=09
+	segementFile.write(output.toUtf8());
+	segementFile.close();
+}
+
+QDomElement ChapterManager::CreateDOMElement(QDomDocument &document, con=
st QString &elementName, const QString &content)
+{
+	QDomElement element =3D document.createElement(elementName);
+	element.appendChild(document.createTextNode(content));
+
+	return element;
+}
+
+void ChapterManager::AddChapterTime(QDomDocument& document, QDomNode& pa=
rent, uint64_t start_time, uint64_t end_time)
+{
+	parent.appendChild(CreateDOMElement(document, "ChapterTimeStart", Utili=
ties::FormatTime(start_time)));
+	parent.appendChild(CreateDOMElement(document, "ChapterTimeEnd", Utiliti=
es::FormatTime(end_time)));
+}
+
+void ChapterManager::AddCodecPrivateData(QDomDocument& document, QDomNod=
e& parent, const unsigned char *buffer, unsigned int size, bool createCha=
pterProcessElement /*=3D true*/)
+{
+	QDomNode node =3D parent;
+
+	if (createChapterProcessElement)
+	{
+		QDomElement chapterProcessElement =3D document.createElement("ChapterP=
rocess");
+		parent.appendChild(chapterProcessElement);
+		node =3D chapterProcessElement;
+	}
+
+	node.appendChild(CreateDOMElement(document, "ChapterProcessCodecID", "1=
"));
+
+	QDomElement chapterProcessPrivateElement =3D CreateDOMElement(document,=
 "ChapterProcessPrivate", Utilities::EncodeHex(buffer, size));
+	chapterProcessPrivateElement.setAttribute("format", "hex");
+	node.appendChild(chapterProcessPrivateElement);
+}
+
+void ChapterManager::AddPGCCommands(QDomDocument& document, QDomNode& pa=
rent, const pgc_command_tbl_t * command_tbl)
+{
+	if (command_tbl)
+	{
+		unsigned char *_buf =3D (unsigned char*) malloc(1 + command_tbl->nr_of=
_pre * 8);
+
+		// Pre-commands
+		if (command_tbl->nr_of_pre)
+		{
+			parent.appendChild(document.createComment("Pre commands"));
+
+			QDomElement chapterCommandElement =3D document.createElement("Chapter=
ProcessCommand");
+			parent.appendChild(chapterCommandElement);
+
+			QDomElement chapterProcessTimeElement =3D document.createElement("Cha=
pterProcessTime");
+			chapterProcessTimeElement.appendChild(document.createTextNode("1"));
+			chapterCommandElement.appendChild(chapterProcessTimeElement);
+
+			_buf[0] =3D command_tbl->nr_of_pre;
+			memcpy(&_buf[1], command_tbl->pre_cmds, command_tbl->nr_of_pre * 8);
+
+			QDomElement chapterProcessDataElement =3D CreateDOMElement(document, =
"ChapterProcessData", Utilities::EncodeHex(_buf, 1 + command_tbl->nr_of_p=
re * 8));
+			chapterProcessDataElement.setAttribute("format", "hex");
+			chapterCommandElement.appendChild(chapterProcessDataElement);
+		}
+
+		// Cell commands
+		if (command_tbl->nr_of_cell)
+		{
+			parent.appendChild(document.createComment("Cell commands"));
+
+			QDomElement chapterCommandElement =3D document.createElement("Chapter=
ProcessCommand");
+			parent.appendChild(chapterCommandElement);
+
+			QDomElement chapterProcessTimeElement =3D document.createElement("Cha=
pterProcessTime");
+			chapterProcessTimeElement.appendChild(document.createTextNode("0"));
+			chapterCommandElement.appendChild(chapterProcessTimeElement);
+
+			_buf =3D (unsigned char*) realloc(_buf, 1 + command_tbl->nr_of_cell *=
 8);
+			_buf[0] =3D command_tbl->nr_of_cell;
+			memcpy(&_buf[1], command_tbl->cell_cmds, command_tbl->nr_of_cell * 8)=
;
+
+			QDomElement chapterProcessDataElement =3D CreateDOMElement(document, =
"ChapterProcessData", Utilities::EncodeHex(_buf, 1 + command_tbl->nr_of_c=
ell * 8));
+			chapterProcessDataElement.setAttribute("format", "hex");
+			chapterCommandElement.appendChild(chapterProcessDataElement);
+		}
+
+		// Post commands
+		if (command_tbl->nr_of_post)
+		{
+			parent.appendChild(document.createComment("Post commands"));
+
+			QDomElement chapterCommandElement =3D document.createElement("Chapter=
ProcessCommand");
+			parent.appendChild(chapterCommandElement);
+
+			QDomElement chapterProcessTimeElement =3D document.createElement("Cha=
pterProcessTime");
+			chapterProcessTimeElement.appendChild(document.createTextNode("2"));
+			chapterCommandElement.appendChild(chapterProcessTimeElement);
+
+			_buf =3D (unsigned char*) realloc(_buf, 1+command_tbl->nr_of_post * 8=
);
+			_buf[0] =3D command_tbl->nr_of_post;
+			memcpy(&_buf[1], command_tbl->post_cmds, command_tbl->nr_of_post * 8)=
;
+
+			QDomElement chapterProcessDataElement =3D CreateDOMElement(document, =
"ChapterProcessData", Utilities::EncodeHex(_buf, 1 + command_tbl->nr_of_p=
ost * 8));
+			chapterProcessDataElement.setAttribute("format", "hex");
+			chapterCommandElement.appendChild(chapterProcessDataElement);
+		}
+
+		free(_buf);
+	}
+}
+
+uint64_t ChapterManager::HandleLanguageUnit(QDomDocument& document, QDom=
Node& parent, const IFOFile& _ifo, int title)
+{
+	static unsigned char _PrivateLU[]  =3D {0x2A, 0x00, 0x00, 0x00};
+	uint64_t start_time =3D uint64_t(-1), found_time;
+
+	QDomElement chapterAtomElement;
+	QDomElement chapterDisplayElement;
+	QDomElement chapterStringElement;
+	QDomElement chapterTimeStartElement;
+
+	for (int i =3D 0 ;i < _ifo.LanguageUnits(title)->nr_of_lus; i++)
+	{
+		parent.appendChild(document.createComment("Language Units"));
+
+		chapterAtomElement =3D document.createElement("ChapterAtom");
+		parent.appendChild(chapterAtomElement);
+
+		// the Language Unit for a given language
+		const pgci_lu_t &_LU =3D _ifo.LanguageUnits(title)->lu[i];
+		_PrivateLU[1] =3D _LU.lang_code >> 8;
+		_PrivateLU[2] =3D _LU.lang_code & 0xFF;
+		_PrivateLU[3] =3D _LU.lang_extension;
+
+		chapterAtomElement.appendChild(document.createComment("Language: " + Q=
String(_LU.lang_code >> 8) + QString(_LU.lang_code & 0xFF)));=09
+		chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUID"=
, Utilities::CreateUID()));
+
+		AddCodecPrivateData(document, chapterAtomElement, _PrivateLU, 4);
+
+		// display the UID for the lazy rippers
+		chapterAtomElement.appendChild(document.createComment("Enter your text=
 here"));
+
+		chapterDisplayElement =3D document.createElement("ChapterDisplay");
+		chapterAtomElement.appendChild(chapterDisplayElement);
+
+		chapterStringElement =3D document.createElement("ChapterString");
+		chapterStringElement.appendChild(document.createTextNode("Language Uni=
t for " + QString(_LU.lang_code >> 8) + QString(_LU.lang_code & 0xFF) ));
+		chapterDisplayElement.appendChild(chapterStringElement);
+
+		if (_LU.pgcit)
+		{
+			for (int j =3D 0; j < _LU.pgcit->nr_of_pgci_srp; j++)
+			{
+				const pgci_srp_t &_PGC_SRP =3D _LU.pgcit->pgci_srp[j];
+
+				found_time =3D AddPGC(document, chapterAtomElement, _PGC_SRP.pgc, j,=
 _PGC_SRP.entry_id, _ifo.CellsList(title, true), NULL, 0);
+
+				if (start_time > found_time)
+					start_time =3D found_time;
+			}
+		}
+
+		chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterTime=
Start", Utilities::FormatTime(start_time)));
+	}
+
+	return start_time;
+}
+
+
+uint64_t ChapterManager::AddPGC(QDomDocument& document, QDomNode& parent=
, const pgc_t * pgc, uint16_t pgc_num, unsigned char pgc_type, const Cell=
sListType & cell_list, const ttu_t * ptts, int title)
+{
+	static unsigned char _PrivatePGC[] =3D {0x20, 0x00, 0x00, 0x00, 0x00, 0=
x00, 0x00, 0x00};
+	uint64_t start_time =3D uint64_t(-1), found_time;
+
+	parent.appendChild(document.createComment(QString("PGC PGC_%1 type %2")=
.arg(pgc_num+1).arg(GetPGCType(pgc_type))));
+
+	QDomElement chapterAtomElement =3D document.createElement("ChapterAtom"=
);
+	parent.appendChild(chapterAtomElement);
+
+	QString _myUID =3D Utilities::CreateUID();
+	chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUID",=
 _myUID));
+
+	// display the UID for the lazy rippers
+	if (ptts =3D=3D NULL)
+	{
+		chapterAtomElement.appendChild(document.createComment("Enter your text=
 here"));
+
+		QDomElement chapterDisplayElement =3D document.createElement("ChapterD=
isplay");
+		chapterDisplayElement.appendChild(CreateDOMElement(document, "ChapterS=
tring", "PGC type " + GetPGCType(pgc_type)));
+		chapterAtomElement.appendChild(chapterDisplayElement);
+	}
+	else
+		chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterFlag=
Hidden", "1"));
+
+	// PGC commands
+	QDomElement chapterProcessElement =3D document.createElement("ChapterPr=
ocess");
+	chapterAtomElement.appendChild(chapterProcessElement);
+
+	_PrivatePGC[1] =3D (pgc_num+1) >> 8;
+	_PrivatePGC[2] =3D (pgc_num+1) & 0xFF;
+	_PrivatePGC[3] =3D pgc_type;
+	_PrivatePGC[4] =3D ((uint8_t*) &pgc->prohibited_ops)[0];
+	_PrivatePGC[5] =3D ((uint8_t*) &pgc->prohibited_ops)[1];
+	_PrivatePGC[6] =3D ((uint8_t*) &pgc->prohibited_ops)[2];
+	_PrivatePGC[7] =3D ((uint8_t*) &pgc->prohibited_ops)[3];
+
+	AddCodecPrivateData(document, chapterProcessElement, _PrivatePGC, 8, fa=
lse);
+	AddPGCCommands(document, chapterProcessElement, pgc->command_tbl);
+
+	// Handle the Programs/Cells in the PGC
+	for (int i=3D0; i< pgc->nr_of_programs; i++)
+	{
+		found_time =3D AddProgram(document, chapterAtomElement, pgc, _myUID, i=
, cell_list, pgc_num, ptts, title);
+
+		if (start_time > found_time)
+			start_time =3D found_time;
+	}
+
+	if (start_time =3D=3D uint64_t(-1))
+		start_time =3D 0;
+
+	chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterTimeS=
tart", Utilities::FormatTime(start_time)));
+
+	return start_time;
+}
+
+
+QString ChapterManager::GetPGCType(unsigned char entry_id)
+{
+	QString result ("0x%1 =3D ");
+	result =3D result.arg(entry_id, 2, 16, QChar('0'));
+
+	if (entry_id & 0x80)
+		result +=3D "Entry + ";
+
+	switch (entry_id & ~0x80)
+	{
+	case 2:
+		result +=3D "Title-Menu";
+		break;
+	case 3:
+		result +=3D "Root Menu";
+		break;
+	case 4:
+		result +=3D "Subpicture Menu";
+		break;
+	case 5:
+		result +=3D "Audio Menu";
+		break;
+	case 6:
+		result +=3D "Angle Menu";
+		break;
+	case 7:
+		result +=3D "Chapter Menu";
+		break;
+	default:
+		result +=3D "Basic PGC";
+		break;
+	}
+
+	return result;
+}
+
+
+uint64_t ChapterManager::AddProgram(QDomDocument& document, QDomNode& pa=
rent, const pgc_t *pgc, const QString& PgcUID, int program_number, const =
CellsListType& cell_list, int16_t pgc_num, const ttu_t *ptts, int title)
+{
+	static unsigned char _PrivatePTT[] =3D {0x10, 0x00};
+	static unsigned char _PrivatePG[] =3D {0x18, 0x00, 0x00};
+	static unsigned char _PrivateCN[] =3D {0x08, 0x00, 0x00, 0x00, 0x00};
+
+	uint64_t start_time =3D uint64_t(-1), end_time =3D 0;
+
+	// for this program
+	int entry_cell_num =3D pgc->program_map[program_number];
+	int program_last_cell_num =3D pgc->nr_of_cells;
+	int next_program_entry_cell_num;
+	if (program_number+1 =3D=3D pgc->nr_of_programs)
+		next_program_entry_cell_num =3D program_last_cell_num+1;
+	else
+		next_program_entry_cell_num =3D pgc->program_map[program_number+1];
+
+	parent.appendChild(document.createComment("Program PGN#" + QString("%1"=
).arg(program_number + 1) + " in this PGC"));
+
+	QDomElement chapterAtomElement =3D document.createElement("ChapterAtom"=
);
+	parent.appendChild(chapterAtomElement);
+
+	QString _myUID =3D Utilities::CreateUID();
+	chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUID",=
 _myUID));
+	chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterFlagH=
idden", "1"));
+
+	_PrivatePG[1] =3D (program_number+1) >> 8;
+	_PrivatePG[2] =3D (program_number+1) & 0xFF;
+	AddCodecPrivateData(document, chapterAtomElement, _PrivatePG, 3);
+
+	if (ptts !=3D NULL)
+	{
+		// find all PTT corresponding to this PGC/PG number
+		for (uint16_t pppt_nr =3D 0; pppt_nr < ptts->nr_of_ptts; pppt_nr++)
+		{
+			// use the start timecode of the first cell
+			const cell_position_t & position =3D pgc->cell_position[entry_cell_nu=
m-1];
+			const CellListElem * cell_elt =3D cell_list.at(position);
+			// TODO: make this test optional (create chapters even without the co=
ntent)
+			if (cell_elt =3D=3D NULL || !cell_elt->found)
+				continue;
+		=09
+			start_time =3D cell_elt->start_time;
+
+			QDomElement chapterAtomParent =3D chapterAtomElement;
+
+			if (ptts->ptt[pppt_nr].pgcn =3D=3D pgc_num+1 && ptts->ptt[pppt_nr].pg=
n =3D=3D program_number+1)
+			{
+				chapterAtomElement.appendChild(document.createComment(QString("Chapt=
er PTT#%1 [%2.%3]").arg(QString::number(pppt_nr+1)).arg(pgc_num+1, 2, 10,=
 QChar('0')).arg(program_number+1, 2, 10, QChar('0'))));
+			=09
+				chapterAtomElement =3D document.createElement("ChapterAtom");
+				chapterAtomParent.appendChild(chapterAtomElement);
+
+				chapterAtomElement.appendChild(document.createComment("Enter your te=
xt here"));
+
+				QDomElement chapterDisplayElement =3D document.createElement("Chapte=
rDisplay");
+				chapterDisplayElement.appendChild(CreateDOMElement(document, "Chapte=
rString", QString("Your Name Here For Chapter #%1.%2").arg(QString::numbe=
r(title), QString::number(pppt_nr + 1))));
+				chapterAtomElement.appendChild(chapterDisplayElement);
+
+				QString _myUID =3D Utilities::CreateUID();
+				chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUI=
D", _myUID));
+
+				_PrivatePTT[1] =3D pppt_nr+1;
+				AddCodecPrivateData(document, chapterAtomElement, _PrivatePTT, 2);
+
+				chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterTi=
meStart", Utilities::FormatTime(start_time)));
+			}
+
+			chapterAtomElement =3D chapterAtomParent;
+		}
+	}
+
+	QDomElement parentChapterAtom =3D chapterAtomElement;
+
+	for (int cell_num =3D entry_cell_num; cell_num<next_program_entry_cell_=
num; cell_num++)
+	{
+		// Output cells
+		const cell_position_t & position =3D pgc->cell_position[cell_num-1];
+		const cell_playback_t & cell =3D pgc->cell_playback[cell_num-1];
+
+		if (cell.block_mode !=3D 0 && cell.block_mode !=3D 3)
+			continue;
+
+		const CellListElem * cell_elt =3D cell_list.at(position);
+		// TODO: make this test optional (create chapters even without the con=
tent)
+		if (cell_elt =3D=3D NULL || !cell_elt->found)
+			continue;
+
+		QString prefix =3D QString("Program %1 Cell CN#%2 ").arg( (cell_num =3D=
=3D entry_cell_num) ? "Entry" : "", QString::number(cell_num));
+		QString middle =3D QString("[%1.%2]").arg(cell_elt->vobid, 2, 10, QCha=
r('0')).arg(cell_elt->cellid);
+		QString suffix =3D QString(" (%1 angles)").arg(cell_num - entry_cell_n=
um + 1);
+
+		if (cell.block_mode) // multi-angle
+			parentChapterAtom.appendChild(document.createComment(prefix + middle =
+ suffix));
+		else
+			parentChapterAtom.appendChild(document.createComment(prefix + middle)=
);
+
+		QDomElement chapterAtomElement =3D document.createElement("ChapterAtom=
");
+		parentChapterAtom.appendChild(chapterAtomElement);
+
+		QString _myUID =3D Utilities::CreateUID();
+		chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterUID"=
, _myUID));
+		chapterAtomElement.appendChild(CreateDOMElement(document, "ChapterFlag=
Hidden", "1"));
+
+		_PrivateCN[1] =3D (position.vob_id_nr) >> 8;
+		_PrivateCN[2] =3D (position.vob_id_nr) & 0xFF;
+		_PrivateCN[3] =3D position.cell_nr;
+		_PrivateCN[4] =3D cell_num - entry_cell_num + 1; // Number of angles
+		AddCodecPrivateData(document, chapterAtomElement, _PrivateCN, 5);
+
+		if (cell.still_time =3D=3D 0xFF) {
+			chapterAtomElement.appendChild(document.createComment("Infinite loop =
Still Cell"));
+
+			// output an additional tag to specify this is cell should loop infin=
itely
+			// post-process command, jump to timecode "st_time"
+			QDomElement chapterProcessElement =3D document.createElement("Chapter=
Process");
+			chapterProcessElement.appendChild(CreateDOMElement(document, "Chapter=
ProcessCodecID", "0"));
+			chapterProcessElement.appendChild(document.createComment("Post comman=
d: replay this cell"));
+			chapterAtomElement.appendChild(chapterProcessElement);
+
+			QDomElement chapterProcessCommand =3D document.createElement("Chapter=
ProcessCommand");
+			chapterProcessCommand.appendChild(CreateDOMElement(document, "Chapter=
ProcessTime", "2"));
+			chapterProcessElement.appendChild(chapterProcessCommand);
+
+			QDomElement chapterProcessDataElement =3D CreateDOMElement(document, =
"ChapterProcessData", "GotoAndPlay(" + PgcUID + ");" );
+			chapterProcessDataElement.setAttribute("format", "ascii");
+			chapterProcessCommand.appendChild(chapterProcessDataElement);
+		} else if (cell.still_time !=3D 0)
+			chapterAtomElement.appendChild(document.createComment(QString("Still =
cell (%1s)").arg(cell.still_time)));
+
+		AddChapterTime(document, chapterAtomElement, cell_elt->start_time, cel=
l_elt->start_time + cell_elt->duration);
+
+		if (end_time < cell_elt->start_time + cell_elt->duration)
+			end_time =3D cell_elt->start_time + cell_elt->duration;
+
+		if (start_time > cell_elt->start_time)
+			start_time =3D cell_elt->start_time;
+	}
+
+	if (start_time =3D=3D uint64_t(-1))
+		start_time =3D 0; // unknown
+
+	parentChapterAtom.appendChild(CreateDOMElement(document, "ChapterTimeSt=
art", Utilities::FormatTime(start_time)));
+
+	return start_time;
+}
\ No newline at end of file

Added: trunk/DvdMenuXtractor/chaptermanager.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/chaptermanager.h	2007-01-22 11:21:16 UTC (rev 1=
269)
+++ trunk/DvdMenuXtractor/chaptermanager.h	2007-01-28 16:48:11 UTC (rev 1=
270)
@@ -0,0 +1,40 @@
+#ifndef CHAPTER_MANAGER_H
+#define CHAPTER_MANAGER_H
+
+#include <QString>
+#include "vobparser/IFOFile.h"
+
+class QDomNode;
+class QDomElement;
+class QDomDocument;
+
+class ChapterManager
+{
+public:
+	ChapterManager(unsigned xmlIdentCount)
+		: INDENT_COUNT(xmlIdentCount)
+	{
+	}
+	bool generateScript(const IFOFile& ifoFile, const QString& filename, ui=
nt16_t title, const QString& editionUID) const;
+	bool generateMenuScript(const IFOFile& ifoFile, const QString& filename=
, uint16_t title, const QString& editionUID) const;
+
+	static QString INFO_SUFFIX;
+	static QString CHAPTER_SUFFIX;
+
+private:
+	void generateInfoScript(const QString& filename, uint16_t title, const =
QString& editionUID) const;
+=09
+	static QDomElement CreateDOMElement(QDomDocument& document, const QStri=
ng& elementName, const QString& content);
+	static void AddChapterTime(QDomDocument& document, QDomNode& parent, ui=
nt64_t start_time, uint64_t end_time);
+	static void AddCodecPrivateData(QDomDocument& document, QDomNode& paren=
t, const unsigned char *buffer, unsigned int size, bool createChapterProc=
essElement =3D true);
+	static void AddPGCCommands(QDomDocument& document, QDomNode& parent, co=
nst pgc_command_tbl_t * command_tbl);
+	static uint64_t AddProgram(QDomDocument& document, QDomNode& parent, co=
nst pgc_t *pgc, const QString& PgcUID, int program_number, const CellsLis=
tType& cell_list, int16_t pgc_num, const ttu_t *ptts, int title);
+	static uint64_t AddPGC(QDomDocument& document, QDomNode& parent, const =
pgc_t * pgc, uint16_t pgc_num, unsigned char pgc_type, const CellsListTyp=
e & cell_list, const ttu_t * ptts, int title);
+	static QString GetPGCType(unsigned char entry_id);
+	static uint64_t HandleLanguageUnit(QDomDocument& document, QDomNode& pa=
rent, const IFOFile& _ifo, int title);
+
+	uint8_t familyUID[16];
+	unsigned INDENT_COUNT;
+};
+
+#endif //CHAPTER_MANAGER_H
\ No newline at end of file

Added: trunk/DvdMenuXtractor/config.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/config.h	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/config.h	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,31 @@
+#define CONFIG_STATIC
+//#define CONFIG_UNICODE not because dvdread is not unicode safe
+//#define CONFIG_MULTITHREAD
+//#define CONFIG_MSVCRT
+
+//-----------
+// failsafes
+
+#if !defined(ARM) || defined(TARGET_SYMBIAN)
+#undef CONFIG_WMMX
+#endif
+
+#if !defined(IX86) || defined(TARGET_SYMBIAN)
+#undef CONFIG_MMX
+#endif
+
+#if !defined(CONFIG_UNICODE) && (defined(TARGET_WINCE) || defined(TARGET=
_SYMBIAN))
+#define CONFIG_UNICODE
+#endif
+
+#if defined(CONFIG_MULTITHREAD) && (defined(TARGET_SYMBIAN) || defined(T=
ARGET_PALMOS))
+#undef CONFIG_MULTITHREAD
+#endif
+
+#if defined(CONFIG_UNICODE) && (defined(TARGET_PALMOS) || defined(TARGET=
_LINUX))
+#undef CONFIG_UNICODE
+#endif
+
+#if !defined(CONFIG_STATIC) && defined(TARGET_PALMOS) && defined(IX86)
+#define CONFIG_STATIC
+#endif

Added: trunk/DvdMenuXtractor/dmx.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx.cpp	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/dmx.cpp	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,486 @@
+#include "dmx.h"
+#include "utilities.h"
+#include "chaptermanager.h"
+
+#include <QDir>
+#include <QTime>
+#include <QMutexLocker>
+
+DMX::DMX(bool consoleMode)
+	: ifoFile_(0), needsAbort_(false), consoleMode_(consoleMode)
+{
+}
+
+DMX::~DMX()
+{
+	abort();
+
+	QMutex mutex;
+	mutex.lock();
+	delete ifoFile_;
+	ifoFile_ =3D 0;
+	mutex.unlock();
+}
+
+void DMX::abort()
+{
+	QMutex mutex;
+	mutex.lock();
+	needsAbort_ =3D true;
+	mutex.unlock();
+
+	wait();
+}
+
+void DMX::processTitle(int16_t title, int index)
+{
+	const QString editionUID =3D Utilities::CreateUID();
+
+	unsigned stepIndex =3D 0;
+	bool menu =3D ((index < 0) && !title) || ((index >=3D 0) && selection_[=
index].isMenu());
+	VobParser *aVobParser =3D 0;
+	QString str;
+	QString text =3D "Step %1 of 2: %3...";
+
+	do
+	{
+		printf("Treating Title %d %s VOB file(s)\n", title, menu ? "Menu" : ""=
);
+
+		stepIndex =3D 1;
+
+		str =3D text.arg(stepIndex++).arg("Building VOB map");
+	=09
+		if (consoleMode_)
+			printf(qPrintable(str + '\n'));
+		else
+			emit stepChanged(str);
+
+		aVobParser =3D buildVobParser(title, menu);
+
+		str =3D text.arg(stepIndex++).arg("Splitting and demuxing");
+	=09
+		if (consoleMode_)
+			printf(qPrintable(str + '\n'));
+		else
+			emit stepChanged(str);
+	=09
+		demux(aVobParser, index, editionUID, title, menu);
+
+		delete aVobParser;
+	=09
+		menu =3D !menu && ((index < 0) || selection_[index].isMenu());
+	} while (menu && !needsAbort_);
+}
+
+bool DMX::setExtractionParameters(const QString& sourcePath, const QStri=
ng& destinationPath, const QString& toolsPath, const SelectionType& selec=
tedItems)
+{
+	QMutex mutex;
+	QMutexLocker locker (&mutex);
+
+	// set selection
+	selection_ =3D selectedItems;
+
+	// check if require directories exist
+	if (!QFile::exists(sourcePath))
+	{
+		fprintf(stderr, "Input folder '%s' doesn't exist\n", qPrintable(source=
Path));
+		return false;
+	}
+
+	// set source path
+	sourcePath_ =3D sourcePath;
+
+	if (!QFile::exists(toolsPath))
+	{
+		fprintf(stderr, "Tools folder '%s' doesn't exist\n", qPrintable(toolsP=
ath));
+		return false;
+	}
+
+	// set "mkvmerge.exe" path
+	toolsPath_ =3D toolsPath;
+
+	// try to create output
+	if (!QFile::exists(destinationPath))
+	{
+		if (!QDir().mkpath(destinationPath))
+		{
+			fprintf(stderr,"Cannot create output folder: '%s'\n", qPrintable(dest=
inationPath));
+			return false;
+		}
+		else
+			printf("Successfully created output folder: '%s'\n", qPrintable(desti=
nationPath));
+	}
+
+	// set output path
+	destinationPath_ =3D destinationPath;
+
+	return true;
+}
+
+void DMX::run()
+{
+	// try to open input file
+	if (!sourcePath_.size() || !loadIFOFile(sourcePath_))
+		return;
+
+	QMutex mutex;
+	mutex.lock();
+	needsAbort_ =3D false;
+	mutex.unlock();
+
+	if (selection_.size()) // if selection is available
+	{
+		for (size_t index =3D 0; index < selection_.size(); ++index)
+		{
+			int16_t title =3D selection_[index].title();
+		=09
+			if (title >=3D 0)
+				processTitle(title, index);
+		}
+	}=20
+	else // if no selection is available, process all titles
+	{
+		for (int16_t title =3D 0; title <=3D ifoFile_->NumberOfTitles(); ++tit=
le)
+			processTitle(title, -1);
+	}
+}
+
+IFOFile* DMX::OpenIFOFile(const QString& path)
+{
+	IFOFile *file =3D 0;
+	QDir info (path);
+=09
+	try
+	{
+		file =3D new IFOFile(info.absolutePath());
+	}
+	catch(IFOException&)
+	{
+		// TODO : More verbose
+		fprintf(stderr, "Couldn't use input directory as DVD source\n");
+		return 0;
+	}
+
+	return file;
+}
+
+bool DMX::loadIFOFile(const QString& path)
+{
+	QMutex mutex;
+	QMutexLocker locker (&mutex);
+=09
+	// reset last file
+	delete ifoFile_;
+	ifoFile_ =3D OpenIFOFile(path);
+
+	if (ifoFile_ =3D=3D 0)
+		return false;
+
+	return true;
+}
+
+VobParser* DMX::buildVobParser(int16_t title, bool menu)
+{
+	VobParser* parser =3D 0;
+	if (consoleMode_)
+		printf("0%%");
+	else
+		emit progressChanged(0);
+=09
+	try=20
+	{
+		parser =3D new VobParser(qPrintable(sourcePath_), title, menu);
+	} catch (...)
+	{
+		if (consoleMode_)
+			printf("\r\r");
+	=09
+		printf("No VOB file(s) found in %s for Title %d\n", qPrintable(sourceP=
ath_), title);
+	}
+
+	if (consoleMode_)
+		printf("\r\r100%%\n");
+	else
+		emit progressChanged(100);
+=09
+	return parser;
+}
+
+void DMX::demuxAudioTrack(int16_t title, bool isMenu, const AudioTrackLi=
st& _audioTracks, size_t _stream, CompositeDemuxWriter& demuxer, const QS=
tring& filename)
+{
+	if (_stream < 0 || _stream >=3D _audioTracks.size())
+		return;
+
+	static const QString muxArgumentsFormat(" --track-name 0:\"aud-%1\" --l=
anguage 0:%2 --timecodes 0:\"%3_%4.tmc\" \"%3.%4\"");
+
+	const audio_attr_t *_attr =3D _audioTracks[_stream];
+	// get the possible ID for this track for this Cell/PGC
+	uint8_t _ID =3D ifoFile_->GetAudioId(_stream, title, isMenu);
+
+	Writer *_muxer =3D 0;
+=09
+	// if (_attr->lang_code =3D=3D 0)
+	QString lang ("und");
+	QString langSuffix (QString("_%1_un").arg(_ID));
+=09
+	if (_attr->lang_code !=3D 0)
+	{
+		lang =3D QString("%1%2").arg(QString(_attr->lang_code >> 8), QString(_=
attr->lang_code & 0xFF));
+		langSuffix =3D QString("_%1_%2%3").arg(QString::number(_ID), QString(_=
attr->lang_code >> 8), QString(_attr->lang_code & 0xFF));
+	}
+
+	QString muxArguments;
+	QString fullPrefix (destinationPath_ + QDir::separator() + filename + l=
angSuffix);
+
+	switch (_audioTracks[_stream]->audio_format)
+	{
+	case 0:
+		muxArguments =3D muxArgumentsFormat.arg(filename + langSuffix, lang, f=
ullPrefix, "ac3");
+	=09
+		_muxer =3D new AC3DemuxWriter(fullPrefix.toAscii().constData(), 0x80 +=
 _ID);
+		if (!demuxer.AddDemuxer(SUBSTREAM_AC3_LOW + _ID, _muxer, muxArguments)=
)
+			delete _muxer;
+		break;
+
+	case 2:
+	case 3:
+		muxArguments =3D muxArgumentsFormat.arg(filename + langSuffix, lang, f=
ullPrefix, "mpa");
+	=09
+		_muxer =3D new MPADemuxWriter(fullPrefix.toAscii().data(), 0xC0 + _ID)=
;
+		if (!demuxer.AddDemuxer(AUDIO_STREAM + _ID, _muxer, muxArguments))
+			delete _muxer;
+		break;
+
+	case 4:
+		// TODO possibly other LPCM formats ?
+		muxArguments =3D muxArgumentsFormat.arg(filename + langSuffix, lang, f=
ullPrefix, "wav");
+	=09
+		_muxer =3D new LPCMDemuxWriter(fullPrefix.toAscii().data(), 0xA0 + _ID=
, 48000, 16, 2);
+		if (!demuxer.AddDemuxer(SUBSTREAM_PCM_LOW + _ID, _muxer, muxArguments)=
)
+			delete _muxer;
+		break;
+
+	case 6:
+		muxArguments =3D muxArgumentsFormat.arg(filename + langSuffix, lang, f=
ullPrefix, "dts");
+	=09
+		_muxer =3D new DTSDemuxWriter(fullPrefix.toAscii().data(), 0x88 + _ID)=
;
+		if (!demuxer.AddDemuxer(SUBSTREAM_DTS_LOW + _ID, _muxer, muxArguments)=
)
+			delete _muxer;
+		break;
+
+	default:
+		fprintf(stderr, "Unknown Audio Format: %d\n", _attr->audio_format);
+	}
+}
+
+void DMX::demuxSubtitleTrack(int16_t title, bool isMenu, const SubtitleT=
rackList& _subTracks, size_t _stream,  CompositeDemuxWriter& demuxer, con=
st QString& filename, const uint32_t *_palette, uint16_t _width, uint16_t=
 _height)
+{
+	if (_stream < 0 || _stream >=3D _subTracks.size())
+		return;
+
+	static const QString subMuxArgumentsFormat(" --track-name 0:\"sub-%1\" =
--language 0:%2 \"%3\"");
+
+	const subp_attr_t *_attr =3D 0;
+	const QString prefix =3D destinationPath_ + QDir::separator() + filenam=
e;
+
+	// get the possible IDs for this track for this Cell/PGC
+	IdArray _IDs =3D ifoFile_->GetSubsId(_stream, title, isMenu);
+
+	Writer * _muxer =3D 0;
+	QString lang, langSuffix;
+=09
+	for (IdArray::size_type _IDidx=3D0; _IDidx < _IDs.size(); ++_IDidx)
+	{
+		_attr =3D _subTracks[_stream];
+	=09
+		// if (_attr->lang_code =3D=3D 0)
+		lang =3D "und";
+		langSuffix =3D QString("_%1_un").arg(_IDs.at(_IDidx));
+
+		if (_attr->lang_code !=3D 0)
+		{
+			lang =3D QString("%1%2 \"").arg(QString(_attr->lang_code >> 8), QStri=
ng(_attr->lang_code & 0xFF));
+			langSuffix =3D QString("_%1_%2%3").arg(QString::number(_IDs.at(_IDidx=
)), QString(_attr->lang_code >> 8), QString(_attr->lang_code & 0xFF));	=09
+		}
+
+		_muxer =3D new SubDemuxWriter(QString(prefix + langSuffix).toAscii().d=
ata(), 0x20 + _IDs.at(_IDidx), _width, _height, _palette, _attr->lang_cod=
e, _attr->lang_extension =3D=3D 9);
+		if (!demuxer.AddDemuxer(SUBSTREAM_SUB_LOW + _IDs.at(_IDidx), _muxer, s=
ubMuxArgumentsFormat.arg(filename + langSuffix, lang, prefix + langSuffix=
 + ".idx")))
+			delete _muxer;
+	}
+}
+
+void DMX::demux(VobParser *aVobParser, int selectionIndex, const QString=
 &editionUID, int16_t title, bool menu)
+{
+	// get list of all cells
+	const CellsListType *CellsList =3D ifoFile_->GetCellsList(title, menu);
+=09
+	if (!CellsList)
+		return;
+
+	static const QString demuxArguments (" --track-name 0:\"video\" --timec=
odes 0:\"%1_m2v.tmc\" \"%1.m2v\"");
+	static const QString btnMuxArgumentsFormat(" --track-name 0:\"btn-%1\" =
--timecodes 0:\"%2_btn.tmc\" \"%2.btn\"");
+=09
+	try
+	{
+		QString filename;
+		QString muxCommand;
+
+		// init filename
+		if (title =3D=3D 0)
+			filename =3D "VMG";
+		else
+			filename =3D QString("VTS%1%2").arg(menu ? "M" : "").arg(title, 2, 10=
, QChar('0'));
+
+		const QString prefix =3D destinationPath_ + QDir::separator() + filena=
me;
+
+		if (aVobParser !=3D 0)
+		{
+			aVobParser->Reset();
+
+			const AudioTrackList & _audioTracks =3D ifoFile_->AudioTracks(title, =
menu);
+			const SubtitleTrackList & _subTracks =3D ifoFile_->SubsTracks(title, =
menu);
+		=09
+			double _fps =3D 0;
+			uint16_t _width =3D 0, _height =3D 0;
+		=09
+			ifoFile_->VideoSize(title, menu, _width, _height, _fps);
+			const uint32_t * _palette =3D ifoFile_->GetPalette(title, menu);
+
+			uint32_t cell =3D 0;
+			CompositeDemuxWriter &demuxer =3D aVobParser->GetDemuxer();
+
+			//emit progressChanged(CellsList->count());
+
+			demuxer.Reset();
+			printf("Processing %s\n", qPrintable(filename));
+
+			if ((selectionIndex < 0) || (selection_[selectionIndex].isVideoEnable=
d()))
+			{
+				Writer *_muxer =3D new VideoDemuxWriter(prefix.toAscii().constData()=
, _fps);
+				if (!demuxer.AddDemuxer(VIDEO_STREAM, _muxer, demuxArguments.arg(pre=
fix)))
+					delete _muxer;
+			}
+
+			size_t _stream =3D 0;
+
+			QString lang;
+			QString langSuffix;
+
+			// decide which audio streams to process
+			if (_audioTracks.size())
+			{
+				if (selectionIndex > -1)
+				{
+					const std::vector<size_t>& selectedAudioTracks =3D selection_[selec=
tionIndex].audioTracks();
+				=09
+					for (size_t index =3D 0; index < selectedAudioTracks.size(); ++inde=
x)
+					{
+						_stream =3D selectedAudioTracks[index];
+						demuxAudioTrack(title, menu, _audioTracks, _stream,  demuxer, file=
name);
+					}
+				}
+				else
+				{
+					for (_stream =3D 0; _stream < _audioTracks.size(); ++_stream)
+						demuxAudioTrack(title, menu, _audioTracks, _stream, demuxer, filen=
ame);
+				}
+			}
+
+			// process subtitle streams
+			if (_subTracks.size())
+			{
+				if (selectionIndex > -1)
+				{
+					const std::vector<size_t>& selectedSubTracks =3D selection_[selecti=
onIndex].subtitleTracks();
+
+					for (size_t index =3D 0; index < selectedSubTracks.size(); ++index)
+					{
+						_stream =3D selectedSubTracks[index];
+						demuxSubtitleTrack(title, menu, _subTracks, _stream,  demuxer, fil=
ename, _palette, _width, _height);
+					}
+				}
+				else
+				{
+					for (_stream =3D 0; _stream < _subTracks.size(); ++_stream)
+						demuxSubtitleTrack(title, menu, _subTracks, _stream, demuxer, file=
name, _palette, _width, _height);
+				}
+
+				// create a possible button demuxer too
+				Writer *_muxer =3D new BtnDemuxWriter(prefix.toAscii().data(), _widt=
h, _height);
+				if (!demuxer.AddDemuxer(SUBSTREAM_PCI, _muxer, btnMuxArgumentsFormat=
.arg(filename, prefix)))
+					delete _muxer;
+			}
+
+			if (consoleMode_)
+				printf("0%%");
+			else
+				emit progressChanged(0);
+		=09
+			const uint32_t maximum =3D aVobParser->GetPacketCount();
+		=09
+			while(aVobParser->ParseNextPacket(*CellsList) && !needsAbort_)
+			{
+				if (consoleMode_)
+					printf("\r\r\r%d%%", aVobParser->GetPacketIndex() * 100 / maximum);
+				else
+					emit progressChanged(aVobParser->GetPacketIndex() * 100 / maximum);
+			}
+			printf("\n");
+
+			// create the command line using the list of used files
+			// always put video first
+			if (demuxer.FileExists(VIDEO_STREAM))
+				muxCommand +=3D demuxer.GetString(VIDEO_STREAM);
+
+			for (_stream =3D 0; _stream < 256; _stream++)
+			{
+				if (_stream =3D=3D VIDEO_STREAM)
+					continue;
+			=09
+				if (demuxer.FileExists(_stream))
+					muxCommand +=3D demuxer.GetString(_stream);
+			}
+		}
+
+		CellsListType *CellsListDone =3D (CellsListType *)CellsList;
+		CellsListDone->arrange();
+
+		bool addChapters =3D false;
+		ChapterManager chapterEditor(2 /*indent count*/);
+
+		if (menu)
+			addChapters =3D chapterEditor.generateMenuScript(*ifoFile_, prefix, t=
itle, editionUID);
+		else
+			addChapters =3D chapterEditor.generateScript(*ifoFile_, prefix, title=
, editionUID);
+
+		if (addChapters)
+		{
+			muxCommand +=3D " --chapters \"" + prefix + ChapterManager::CHAPTER_S=
UFFIX + "\"";
+			muxCommand +=3D " --segmentinfo \"" + prefix + ChapterManager::INFO_S=
UFFIX + "\"";
+		}
+
+#if defined(WIN32)
+		muxCommand.insert(0, "\"" + toolsPath_ + "\\mkvmerge\" -o \"" + prefix=
 + ".mkv\"");
+#else
+		muxCommand.insert(0, toolsPath_ + "/mkvmerge -o \"" + prefix + ".mkv\"=
");
+#endif
+
+		QFile muxBatchFile(prefix + "_" + QTime::currentTime().toString("hh_mm=
_ss") + ".bat");
+
+		if (!muxBatchFile.open( QIODevice::WriteOnly | QIODevice::Text ))
+			fprintf(stderr, "Could not create batch file\n");
+	=09
+#if !defined(WIN32)
+		QString shellString ("#!/bin/sh\n\n");
+		muxBatchFile.write(shellString.toAscii());
+#endif
+		muxBatchFile.write(muxCommand.toAscii());
+		muxBatchFile.close();
+
+		printf("Done demuxing %s\n", qPrintable(filename));
+	}
+	catch(VobParserException e)
+	{
+		fprintf(stderr, "Vob Parser Exception Occurred: %s\n", e.m_message);
+	}
+}

Added: trunk/DvdMenuXtractor/dmx.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx.h	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/dmx.h	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,54 @@
+#ifndef DMX_H
+#define DMX_H
+
+#include <vector>
+#include <QThread>
+#include "dmxselectionitem.h"
+#include "vobparser/IFOFile.h"
+
+class DMX : public QThread
+{
+	Q_OBJECT
+
+public:
+	typedef std::vector<DMXSelectionItem> SelectionType;
+
+  DMX(bool consoleMode =3D false);
+  ~DMX();
+
+	static IFOFile* OpenIFOFile(const QString& path);
+	bool setExtractionParameters(const QString& sourcePath, const QString& =
destinationPath, const QString& toolsPath, const SelectionType& selection=
);
+=09
+signals:
+	// Signal is emitted when the current step progress is changed
+	void progressChanged(int);
+
+	// Signal is emitted when the step is changed
+	void stepChanged(const QString&);
+
+public slots:
+	void abort();
+
+protected:
+	void run();
+
+private:
+	IFOFile *ifoFile_;
+	bool consoleMode_;
+	QString toolsPath_;
+	QString sourcePath_;
+	QString destinationPath_;
+	SelectionType selection_;
+	volatile bool needsAbort_;
+=09
+	bool loadIFOFile(const QString& path);
+	void processTitle(int16_t title, int index);
+
+	VobParser* buildVobParser(int16_t title, bool isMenu);
+=09
+	void demux(VobParser* aVobParser, int selectionIndex, const QString& ed=
itionUID, int16_t title, bool isMenu);
+	void demuxAudioTrack(int16_t title, bool isMenu, const AudioTrackList& =
_audioTracks, size_t _stream, CompositeDemuxWriter& demuxer, const QStrin=
g& filename);
+	void demuxSubtitleTrack(int16_t title, bool isMenu, const SubtitleTrack=
List& _subTracks, size_t _stream,  CompositeDemuxWriter& demuxer, const Q=
String& filename, const uint32_t *_palette, uint16_t _width, uint16_t _he=
ight);
+};
+
+#endif // DMX_H

Added: trunk/DvdMenuXtractor/dmx.ico
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
(Binary files differ)


Property changes on: trunk/DvdMenuXtractor/dmx.ico
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/DvdMenuXtractor/dmx.rc
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmx.rc	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/dmx.rc	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,2 @@
+IDI_ICON1		ICON		DISCARDABLE	"dmx.ico"
+

Added: trunk/DvdMenuXtractor/dmxconsole.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxconsole.cpp	2007-01-22 11:21:16 UTC (rev 126=
9)
+++ trunk/DvdMenuXtractor/dmxconsole.cpp	2007-01-28 16:48:11 UTC (rev 127=
0)
@@ -0,0 +1,121 @@
+#include <iostream>
+
+#include "utilities.h"
+#include "dmxconsole.h"
+
+DMXConsole::~DMXConsole()
+{
+}
+
+DMXConsole::DMXConsole(char *arguments[], int argumentCount)
+{
+	ready_ =3D true;
+
+	if ((argumentCount !=3D 7) && (argumentCount !=3D 9))
+	{
+		ShowUsage();
+		ready_ =3D false;
+		return;
+	}
+
+	QString argument;
+=09
+	for (int i =3D 1; i < argumentCount; ++i)
+	{
+		argument =3D arguments[i];
+
+		if (argument =3D=3D "-h")
+		{
+			ShowUsage();
+			ready_ =3D false;
+			return;
+		}
+		else if (argument =3D=3D "-i")
+			sourcePath_ =3D arguments[++i];
+		else if (argument =3D=3D "-o")
+			destinationPath_ =3D arguments[++i];
+		else if (argument =3D=3D "-t")
+			toolsPath_ =3D arguments[++i];
+		else if (argument =3D=3D "-s")
+			selectionItems_ =3D generateSelectionItems(QString(arguments[++i]));
+		else
+		{
+			std::cout << "ERROR: Unknown option was specified" << std::endl;
+			DMXConsole::ShowUsage();
+			ready_ =3D false;
+			return;
+		}
+	}
+}
+
+DMX::SelectionType DMXConsole::generateSelectionItems(const QString& sel=
ectionString)
+{
+	QString item;
+	QStringList subItems;
+	DMX::SelectionType selectionItems;
+
+	// split string using ";" as delimeter into selection item string
+	QStringList items =3D selectionString.split(";");
+
+	// procfess each substring
+	for (int index =3D 0; index < items.size(); ++index)
+	{
+		item =3D items.at(index);
+
+		// split subitems into smaller parts using "," as delimeter
+		subItems =3D item.split(",");
+
+		// now check if we have all the components
+		if (subItems.size() =3D=3D ITEM_COUNT)
+		{
+			DMXSelectionItem item(subItems.at(TITLE_INDEX).toInt(),=20
+														subItems.at(MENU_INDEX).toInt(),
+														subItems.at(VIDEO_INDEX).toInt());
+
+			// add audio tracks
+			QStringList trackList =3D extractTrackNumbers(subItems.at(1));
+			foreach (QString trackStr, trackList)
+				item.addAudioTrack(trackStr.toUInt());
+
+			// add subtitle tracks
+			trackList =3D extractTrackNumbers(subItems.at(2));
+			foreach (QString trackStr, trackList)
+				item.addSubtitleTrack(trackStr.toUInt());
+
+			selectionItems.push_back(item);
+		}
+		else
+			fprintf(stderr, "WARNING: Incorrect selection item at index %d was fo=
und\n", index);
+	}
+
+	return selectionItems;
+}
+
+QStringList DMXConsole::extractTrackNumbers(const QString& trackNumberSt=
ring)
+{
+	if ( trackNumberString.size() <=3D 2 )
+		return QStringList();
+
+	return trackNumberString.mid(1, trackNumberString.size() - 1).split(","=
);
+}
+
+void DMXConsole::extract()
+{
+	if (ready_)
+	{
+		DMX extractor (true);
+		extractor.setExtractionParameters(sourcePath_, destinationPath_, tools=
Path_, selectionItems_);
+		extractor.start();
+		extractor.wait();
+	}
+}
+
+void DMXConsole::ShowUsage()
+{
+	std::cout << "USAGE: DvdMenuExtractor [<options>]\n\n"
+						<< " Show usage:        -h\n"
+						<< " Specify folders:   -i <dir> -o <dir> -t <dir>\n"
+						<< " Specify selection: -s title, extractMenu, extractVideo, {audi=
oTracks}, {subTracks};..."
+						<< std::endl;
+}
+

Added: trunk/DvdMenuXtractor/dmxconsole.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxconsole.h	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/dmxconsole.h	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,30 @@
+#ifndef DMXCONSOLE_H
+#define DMXCONSOLE_H
+
+#include "dmx.h"
+
+class DMXConsole
+{
+public:
+	DMXConsole(char *arguments[], int argumentCount);
+  ~DMXConsole();
+
+	void extract();
+
+	static void ShowUsage();
+
+private:
+	bool ready_;
+	QString toolsPath_;
+	QString sourcePath_;
+	QString destinationPath_;
+	DMX::SelectionType selectionItems_;
+
+	enum {TITLE_INDEX =3D 0, MENU_INDEX, VIDEO_INDEX,
+				AUDIO_TRACKS_INDEX, SUBTITLE_TRACKS_INDEX, ITEM_COUNT};
+=09
+	QStringList extractTrackNumbers(const QString& trackNumberString);
+	DMX::SelectionType generateSelectionItems(const QString& selectionStrin=
g);
+};
+
+#endif // DMXCONSOLE_H

Added: trunk/DvdMenuXtractor/dmxlogwidget.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxlogwidget.cpp	2007-01-22 11:21:16 UTC (rev 1=
269)
+++ trunk/DvdMenuXtractor/dmxlogwidget.cpp	2007-01-28 16:48:11 UTC (rev 1=
270)
@@ -0,0 +1,47 @@
+#include <QFile>
+#include <QCloseEvent>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QTextStream>
+
+#include "dmxlogwidget.h"
+
+DMXLogWidget::DMXLogWidget(QWidget *parent)
+    : QWidget(0)
+{
+	ui.setupUi(this);
+	setWindowFlags(windowFlags() | Qt::Tool);
+
+	//setup slots
+	connect(ui.saveButton, SIGNAL(clicked()), this, SLOT(saveButtonClicked(=
)));
+}
+
+DMXLogWidget::~DMXLogWidget()
+{
+
+}
+
+void DMXLogWidget::closeEvent(QCloseEvent *event)
+{
+	emit closed();
+	event->accept();
+}
+
+void DMXLogWidget::saveButtonClicked()
+{
+	QString filename =3D QFileDialog::getSaveFileName(this, "Save as...");
+
+	if (filename.size())
+	{
+		QFile output (filename);
+		if (!output.open(QIODevice::WriteOnly | QIODevice::Text))
+		{
+			QMessageBox::critical(this, "Error", "Could not open file for writing=
");
+			return;
+		}
+
+		QTextStream out (&output);
+		out << ui.textEdit->toPlainText();
+	}
+}
+

Added: trunk/DvdMenuXtractor/dmxlogwidget.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxlogwidget.h	2007-01-22 11:21:16 UTC (rev 126=
9)
+++ trunk/DvdMenuXtractor/dmxlogwidget.h	2007-01-28 16:48:11 UTC (rev 127=
0)
@@ -0,0 +1,28 @@
+#ifndef DMXLOGWIDGET_H
+#define DMXLOGWIDGET_H
+
+#include <QWidget>
+#include "ui_dmxlogwidget.h"
+
+class DMXLogWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+  DMXLogWidget(QWidget *parent =3D 0);
+  ~DMXLogWidget();
+
+signals:
+	void closed();
+
+protected:
+	virtual void closeEvent(QCloseEvent *event);
+
+private slots:
+	void saveButtonClicked();
+
+private:
+    Ui::DMXLogWidgetClass ui;
+};
+
+#endif // DMXLOGWIDGET_H

Added: trunk/DvdMenuXtractor/dmxlogwidget.ui
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxlogwidget.ui	2007-01-22 11:21:16 UTC (rev 12=
69)
+++ trunk/DvdMenuXtractor/dmxlogwidget.ui	2007-01-28 16:48:11 UTC (rev 12=
70)
@@ -0,0 +1,118 @@
+<ui version=3D"4.0" >
+ <class>DMXLogWidgetClass</class>
+ <widget class=3D"QWidget" name=3D"DMXLogWidgetClass" >
+  <property name=3D"geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>468</width>
+    <height>213</height>
+   </rect>
+  </property>
+  <property name=3D"windowTitle" >
+   <string>Log</string>
+  </property>
+  <layout class=3D"QVBoxLayout" >
+   <property name=3D"margin" >
+    <number>9</number>
+   </property>
+   <property name=3D"spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class=3D"LogTextEdit" name=3D"textEdit" >
+     <property name=3D"readOnly" >
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class=3D"QHBoxLayout" >
+     <property name=3D"margin" >
+      <number>0</number>
+     </property>
+     <property name=3D"spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class=3D"QPushButton" name=3D"clearButton" >
+       <property name=3D"text" >
+        <string>C&amp;lear</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class=3D"QPushButton" name=3D"saveButton" >
+       <property name=3D"text" >
+        <string>&amp;Save</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name=3D"orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name=3D"sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class=3D"QPushButton" name=3D"closeButton" >
+       <property name=3D"text" >
+        <string>&amp;Close</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing=3D"6" margin=3D"11" />
+ <customwidgets>
+  <customwidget>
+   <class>LogTextEdit</class>
+   <extends>QTextEdit</extends>
+   <header>logtextedit.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>clearButton</sender>
+   <signal>clicked()</signal>
+   <receiver>textEdit</receiver>
+   <slot>clear()</slot>
+   <hints>
+    <hint type=3D"sourcelabel" >
+     <x>62</x>
+     <y>202</y>
+    </hint>
+    <hint type=3D"destinationlabel" >
+     <x>39</x>
+     <y>169</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>closeButton</sender>
+   <signal>clicked()</signal>
+   <receiver>DMXLogWidgetClass</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type=3D"sourcelabel" >
+     <x>410</x>
+     <y>192</y>
+    </hint>
+    <hint type=3D"destinationlabel" >
+     <x>312</x>
+     <y>178</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

Added: trunk/DvdMenuXtractor/dmxselectionitem.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxselectionitem.cpp	2007-01-22 11:21:16 UTC (r=
ev 1269)
+++ trunk/DvdMenuXtractor/dmxselectionitem.cpp	2007-01-28 16:48:11 UTC (r=
ev 1270)
@@ -0,0 +1,71 @@
+#include <algorithm>
+#include "dmxselectionitem.h"
+
+DMXSelectionItem::DMXSelectionItem(int16_t title, bool isMenu, bool enab=
leVideo =3D 1)
+	: title_(title), menu_(isMenu), videoEnabled_(enableVideo)
+{
+	// override for VMG
+	if (!title)
+		menu_ =3D true;
+}
+
+DMXSelectionItem::~DMXSelectionItem()
+{
+}
+
+int16_t DMXSelectionItem::title() const
+{
+	return title_;
+}
+
+bool DMXSelectionItem::isMenu() const
+{
+	return menu_;
+}
+
+bool DMXSelectionItem::isVideoEnabled() const
+{
+	return videoEnabled_;
+}
+
+const DMXSelectionItem::TracksContainerType& DMXSelectionItem::audioTrac=
ks() const
+{
+	return audioTracks_;
+}
+
+const DMXSelectionItem::TracksContainerType& DMXSelectionItem::subtitleT=
racks() const
+{
+	return subtitleTracks_;
+}
+
+void DMXSelectionItem::disableVideo()
+{
+	videoEnabled_ =3D false;
+}
+
+bool DMXSelectionItem::addAudioTrack(size_t trackIndex)
+{
+	// check if audio track was already selected
+	if (std::count(audioTracks_.begin(), audioTracks_.end(), trackIndex) =3D=
=3D 0)
+	{
+		audioTracks_.push_back(trackIndex);
+		return true;
+	}
+
+	return false;
+}
+
+bool DMXSelectionItem::addSubtitleTrack(size_t trackIndex)
+{
+	// check if audio track was already selected
+	if (std::count(subtitleTracks_.begin(), subtitleTracks_.end(), trackInd=
ex) =3D=3D 0)
+	{
+		subtitleTracks_.push_back(trackIndex);
+		return true;
+	}
+
+	return false;
+}
+
+
+

Added: trunk/DvdMenuXtractor/dmxselectionitem.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxselectionitem.h	2007-01-22 11:21:16 UTC (rev=
 1269)
+++ trunk/DvdMenuXtractor/dmxselectionitem.h	2007-01-28 16:48:11 UTC (rev=
 1270)
@@ -0,0 +1,38 @@
+#ifndef DMX_SELECTION_ITEM
+#define DMX_SELECTION_ITEM
+
+#include <vector>
+#include <stdint.h>
+
+// Denotes each selected title
+class DMXSelectionItem
+{
+public:
+
+	typedef std::vector<size_t> TracksContainerType;
+
+	DMXSelectionItem(int16_t title, bool isMenu, bool enableVideo);
+	~DMXSelectionItem();
+
+	// Getters
+	bool isMenu() const;
+	int16_t title() const;
+	bool isVideoEnabled() const;
+	const TracksContainerType& audioTracks() const;
+	const TracksContainerType& subtitleTracks() const;
+
+	void disableVideo();
+	bool addAudioTrack(size_t trackIndex);
+	bool addSubtitleTrack(size_t trackIndex);
+
+private:
+	int16_t title_;
+	bool menu_;
+	bool videoEnabled_;
+
+	TracksContainerType audioTracks_;
+	TracksContainerType subtitleTracks_;
+};
+
+
+#endif // DMX_SELECTION_ITEM
\ No newline at end of file

Added: trunk/DvdMenuXtractor/dmxselectiontree.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxselectiontree.cpp	2007-01-22 11:21:16 UTC (r=
ev 1269)
+++ trunk/DvdMenuXtractor/dmxselectiontree.cpp	2007-01-28 16:48:11 UTC (r=
ev 1270)
@@ -0,0 +1,136 @@
+#include "dmxselectiontree.h"
+#include "selectiontreeitem.h"
+#include "selectiontreesubitem.h"
+
+DMXSelectionTree::DMXSelectionTree(QWidget *parent)
+: QTreeWidget(parent), ifoFile_(0)
+{
+	setColumnCount(1);
+	setHeaderLabels(QStringList("DVD"));
+	setAlternatingRowColors(true);
+}
+
+DMXSelectionTree::~DMXSelectionTree()
+{
+	delete ifoFile_;
+	ifoFile_ =3D 0;
+}
+
+bool DMXSelectionTree::loadIFOFile(const QString &path)
+{
+	clear();
+	setHeaderLabels(QStringList(QString("DVD - %1").arg(path)));
+
+	// reset last file
+	delete ifoFile_;
+	ifoFile_ =3D DMX::OpenIFOFile(path);
+
+	if (ifoFile_ =3D=3D 0)
+		return false;
+
+	bool menu =3D false;
+	SelectionTreeItem *item =3D 0;
+	SelectionTreeSubItem *subItem =3D 0;
+	QTreeWidgetItem *videoStreamItem =3D 0;
+	QTreeWidgetItem *audioTrackItem =3D 0;
+	QTreeWidgetItem *subtitleTrackItem =3D 0;
+
+	for (int16_t title =3D 0; title <=3D ifoFile_->NumberOfTitles(); ++titl=
e)
+	{
+		menu =3D !title;
+
+		do
+		{
+			item =3D new SelectionTreeItem(this, title, menu);
+
+			// add video stream item
+			videoStreamItem =3D new QTreeWidgetItem(item, QStringList("Video Stre=
am"));
+			videoStreamItem->setFlags(videoStreamItem->flags() | Qt::ItemIsTrista=
te);
+			videoStreamItem->setCheckState(0, Qt::Checked);
+
+			// get audio tracks
+			const AudioTrackList& audioTracks =3D ifoFile_->AudioTracks(title, me=
nu);
+
+			if (audioTracks.size())
+			{
+				audioTrackItem =3D new QTreeWidgetItem(item, QStringList("Audio Trac=
ks"));
+				audioTrackItem->setFlags(audioTrackItem->flags() | Qt::ItemIsTristat=
e);
+				audioTrackItem->setCheckState(0, Qt::Checked);
+
+				for (size_t index =3D 0; index < audioTracks.size(); ++index)
+					subItem =3D new SelectionTreeSubItem(audioTrackItem, *item, index, =
SelectionTreeSubItem::AUDIO_TRACK);
+			}
+		=09
+			// get subtitle tracks
+			const SubtitleTrackList& subTracks =3D ifoFile_->SubsTracks(title, me=
nu);
+
+			if (subTracks.size())
+			{
+				subtitleTrackItem =3D new QTreeWidgetItem(item, QStringList("Subtitl=
e Tracks"));
+				subtitleTrackItem->setFlags(subtitleTrackItem->flags() | Qt::ItemIsT=
ristate);
+				subtitleTrackItem->setCheckState(0, Qt::Checked);
+
+				for (size_t index =3D 0; index < subTracks.size(); ++index)
+					subItem =3D new SelectionTreeSubItem(subtitleTrackItem, *item, inde=
x, SelectionTreeSubItem::SUBTITLE_TRACK);
+			}
+		=09
+			menu =3D !menu;
+		} while (menu);
+	}
+
+	return true;
+}
+
+DMX::SelectionType DMXSelectionTree::getSelection() const
+{
+	DMX::SelectionType selection;
+	QTreeWidgetItem *trackListItem =3D 0;
+
+	for (int index =3D 0; index < topLevelItemCount(); ++index)
+	{
+		// if processing title item
+		if ( SelectionTreeItem *item =3D dynamic_cast<SelectionTreeItem*>(topL=
evelItem(index)) )
+		{
+			// if the title item is (partially) checked
+			if (item->checkState(0) !=3D Qt::Unchecked)
+			{
+				// create selection item instance
+				DMXSelectionItem selectionItem(item->title(), item->isMenuItem(), tr=
ue);
+
+				// check if video stream is selected
+				if ((item->childCount() > 0) && (item->child(0)->checkState(0) =3D=3D=
 Qt::Unchecked))
+					selectionItem.disableVideo();
+
+				for (int index =3D 0; index < item->childCount(); ++index)
+				{
+					trackListItem =3D item->child(index);
+
+					// check if track list item is checked
+					if (item->checkState(0) !=3D Qt::Unchecked)
+					{
+						for (int index =3D 0; index < trackListItem->childCount(); ++index=
)
+						{
+							// process track subitem
+							if (SelectionTreeSubItem *subItem =3D dynamic_cast<SelectionTreeS=
ubItem*>(trackListItem->child(index)))
+							{
+								// if sub item is checked
+								if (subItem->checkState(0) =3D=3D Qt::Checked)
+								{
+									if (subItem->type() =3D=3D SelectionTreeSubItem::AUDIO_TRACK)
+										selectionItem.addAudioTrack(subItem->index());
+
+									if (subItem->type() =3D=3D SelectionTreeSubItem::SUBTITLE_TRACK=
)
+											selectionItem.addSubtitleTrack(subItem->index());
+								}
+							}
+						}
+					}
+				}
+
+				selection.push_back(selectionItem);
+			}
+		}
+	}
+
+	return selection;
+}
\ No newline at end of file

Added: trunk/DvdMenuXtractor/dmxselectiontree.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxselectiontree.h	2007-01-22 11:21:16 UTC (rev=
 1269)
+++ trunk/DvdMenuXtractor/dmxselectiontree.h	2007-01-28 16:48:11 UTC (rev=
 1270)
@@ -0,0 +1,22 @@
+#ifndef DMX_SELECTIONTREE_H
+#define DMX_SELECTIONTREE_H
+
+#include "dmx.h"
+#include <QTreeWidget>
+
+class DMXSelectionTree : public QTreeWidget
+{
+	Q_OBJECT
+
+public:
+  DMXSelectionTree(QWidget *parent);
+  ~DMXSelectionTree();
+
+	DMX::SelectionType getSelection() const;
+	bool loadIFOFile(const QString& path);
+
+private:
+	IFOFile *ifoFile_;
+};
+
+#endif // DMX_SELECTIONTREE_H

Added: trunk/DvdMenuXtractor/dmxwizard.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxwizard.cpp	2007-01-22 11:21:16 UTC (rev 1269=
)
+++ trunk/DvdMenuXtractor/dmxwizard.cpp	2007-01-28 16:48:11 UTC (rev 1270=
)
@@ -0,0 +1,247 @@
+#include <QSettings>
+#include <QDirModel>
+#include <QFileDialog>
+#include <QCloseEvent>
+
+#include "dmxwizard.h"
+
+DMXWizard::DMXWizard(QWidget *parent)
+	: QDialog(parent), logWidget_(this)
+{
+	ui.setupUi(this);
+
+	setupSlots();
+	loadSettings();
+
+	// set first page
+	ui.stackedWidget->setCurrentIndex(SETTINGS_PAGE_INDEX);
+	ui.infoLabel->setText(tr("Welcome to DVD Menu Extraction Wizard!\nThe W=
izard will guide You through the extraction process"));
+}
+
+DMXWizard::~DMXWizard()
+{
+	storeSettings();
+}
+void DMXWizard::pathEditTextChanged(const QString& path)
+{
+	bool ready =3D true;
+
+	// set default styles
+	QPalette palette =3D ui.dvdPathEdit->palette();
+	palette.setColor(QPalette::Base, Qt::white);
+	ui.dvdPathEdit->setPalette(palette);
+	ui.toolsPathEdit->setPalette(palette);
+	ui.outputPathEdit->setPalette(palette);
+
+	// hide all message and image labels
+	ui.errorInfoLabel->clear();
+	ui.warningInfoLabel->clear();
+	ui.errorImageLabel->hide();
+	ui.warningImageLabel->hide();
+
+	// set background to "red" if incorrect paths are specified
+	// and show corresponding message
+	if (!QFile::exists(ui.dvdPathEdit->text()))
+	{=09
+		palette.setColor(QPalette::Base, Qt::red);
+		ui.dvdPathEdit->setPalette(palette);
+		ready =3D false;
+	}
+
+	if (!QFile::exists(ui.toolsPathEdit->text()))
+	{=09
+		palette.setColor(QPalette::Base, Qt::red);
+		ui.toolsPathEdit->setPalette(palette);
+		ready =3D false;
+	}
+
+	if (!ui.outputPathEdit->text().size())
+	{
+		palette.setColor(QPalette::Base, Qt::red);
+		ui.outputPathEdit->setPalette(palette);
+		ready =3D false;
+	}
+	else if (QFile::exists(ui.outputPathEdit->text())) // just a warning in=
 case the output folder exists
+	{
+		palette.setColor(QPalette::Base, Qt::yellow);
+		ui.outputPathEdit->setPalette(palette);
+	=09
+		ui.warningImageLabel->show();
+		ui.warningInfoLabel->setText(tr("Specified path already exists"));
+	}
+
+	// show error info if needed
+	if (!ready)
+	{
+		ui.errorImageLabel->show();
+		ui.errorInfoLabel->setText(tr("Missing or incorrect path was specified=
"));
+	}
+
+	ui.nextButton->setEnabled(ready);
+}
+
+void DMXWizard::browseButtonClicked()
+{
+	QString directory =3D QFileDialog::getExistingDirectory(this, "Select d=
irectory...");
+
+	if (!directory.size())
+		return;
+
+	if (QPushButton *senderObject =3D dynamic_cast<QPushButton*>(sender()))
+	{
+		if (senderObject =3D=3D ui.dvdBrowseButton)
+		{
+			if (!(directory.endsWith('/') || directory.endsWith('\\')))
+				directory.append('/');
+
+			ui.dvdPathEdit->setText(directory);
+		}
+		else if (senderObject =3D=3D ui.outputBrowseButton)
+			ui.outputPathEdit->setText(directory);
+		else if (senderObject =3D=3D ui.toolsBrowseButton)
+			ui.toolsPathEdit->setText(directory);
+	}
+}
+
+void DMXWizard::loadSettings()
+{
+	QSettings settings ("DMX", "MatroskaTeam");
+	ui.dvdPathEdit->setText(settings.value("Wizard/DVDPath").toString());
+	ui.outputPathEdit->setText(settings.value("Wizard/OutputPath").toString=
());
+	ui.toolsPathEdit->setText(settings.value("Wizard/ToolsPath").toString()=
);
+}
+
+void DMXWizard::storeSettings()
+{
+	QSettings settings ("DMX", "MatroskaTeam");
+	settings.setValue("Wizard/DVDPath", ui.dvdPathEdit->text());
+	settings.setValue("Wizard/OutputPath", ui.outputPathEdit->text());
+	settings.setValue("Wizard/ToolsPath", ui.toolsPathEdit->text());
+}
+
+void DMXWizard::setupSlots()
+{
+	// setup slots for buttons
+	connect(ui.backButton, SIGNAL(clicked()), this, SLOT(backButtonClicked(=
)));
+	connect(ui.nextButton, SIGNAL(clicked()), this, SLOT(nextButtonClicked(=
)));
+	connect(ui.stopButton, SIGNAL(clicked()), &dmx, SLOT(abort()));
+	connect(ui.dvdBrowseButton, SIGNAL(clicked()), this, SLOT(browseButtonC=
licked()));
+	connect(ui.outputBrowseButton, SIGNAL(clicked()), this, SLOT(browseButt=
onClicked()));
+	connect(ui.toolsBrowseButton, SIGNAL(clicked()), this, SLOT(browseButto=
nClicked()));
+
+	// setup slots for edits
+	connect(ui.dvdPathEdit, SIGNAL(textChanged(const QString&)), this, SLOT=
(pathEditTextChanged(const QString&)));
+	connect(ui.outputPathEdit, SIGNAL(textChanged(const QString&)), this, S=
LOT(pathEditTextChanged(const QString&)));
+	connect(ui.toolsPathEdit, SIGNAL(textChanged(const QString&)), this, SL=
OT(pathEditTextChanged(const QString&)));
+
+	// setup log widget
+	connect(ui.logButton, SIGNAL(toggled(bool)), &logWidget_, SLOT(setVisib=
le(bool)));
+	connect(&logWidget_, SIGNAL(closed()), ui.logButton, SLOT(toggle()));
+
+	// setup slots for extraction
+	connect(&dmx, SIGNAL(finished()), this, SLOT(extractionFinished()));
+	connect(&dmx, SIGNAL(progressChanged(int)), ui.progressBar, SLOT(setVal=
ue(int)));
+	connect(&dmx, SIGNAL(stepChanged(const QString&)), this, SLOT(extractio=
nStepChanged(const QString&)));
+}
+
+void DMXWizard::nextButtonClicked()
+{
+	if (ui.stackedWidget->currentIndex() =3D=3D SETTINGS_PAGE_INDEX)
+	{
+		// try to load DVD IFO
+		if (!ui.selectionTree->loadIFOFile(ui.dvdPathEdit->text()))
+			ui.nextButton->setEnabled(false);
+
+		// set button states
+		ui.backButton->setEnabled(true);
+
+		// turn to the "selection page"
+		ui.stackedWidget->setCurrentIndex(SELECTION_PAGE_INDEX);
+	}
+	else if (ui.stackedWidget->currentIndex() =3D=3D SELECTION_PAGE_INDEX)
+	{
+		ui.nextButton->setEnabled(false);
+
+		// turn to the "extraction page"
+		ui.stackedWidget->setCurrentIndex(EXTRACTION_PAGE_INDEX);
+
+		// get selection
+		DMX::SelectionType selection =3D ui.selectionTree->getSelection();
+		if (selection.size())
+		{
+			// unhide
+			ui.stopButton->show();
+			ui.progressBar->show();
+
+			// set button states
+			ui.backButton->setEnabled(false);
+			ui.stopButton->setEnabled(true);
+
+			ui.progressInfoLabel->setText(tr("Please wait...\nYou can stop the pr=
ocess at any moment by clicking the \"Stop\" button."));
+
+			dmx.setExtractionParameters(ui.dvdPathEdit->text(), ui.outputPathEdit=
->text(),
+											ui.toolsPathEdit->text(), ui.selectionTree->getSelection());
+
+			dmx.start();
+		}
+		else // nothing was selected
+		{
+			ui.stopButton->hide();
+			ui.progressBar->hide();
+			ui.progressInfoLabel->clear();
+
+			ui.stepInfoLabel->setText(tr("Nothing was selected, nothing to do..."=
));
+		=09
+			ui.backButton->setEnabled(true);
+			ui.stopButton->setEnabled(false);
+		}
+	}
+}
+
+void DMXWizard::backButtonClicked()
+{
+	// if going back from the "selection page"
+	if (ui.stackedWidget->currentIndex() =3D=3D SELECTION_PAGE_INDEX)
+	{
+		// set button states
+		ui.backButton->setEnabled(false);
+		ui.nextButton->setEnabled(true);
+
+		ui.stackedWidget->setCurrentIndex(SETTINGS_PAGE_INDEX);
+	}
+	else if (ui.stackedWidget->currentIndex() =3D=3D EXTRACTION_PAGE_INDEX)
+	{
+		// set button states
+		ui.backButton->setEnabled(true);
+		ui.nextButton->setEnabled(true);
+
+		ui.stackedWidget->setCurrentIndex(SELECTION_PAGE_INDEX);
+	}
+}
+
+void DMXWizard::extractionFinished()
+{
+	// set button states
+	ui.backButton->setEnabled(true);
+	ui.stopButton->setEnabled(false);
+
+	// chage text
+	ui.stepInfoLabel->setText("Extraction finished!");
+}
+
+void DMXWizard::extractionStepChanged(const QString &text)
+{
+	ui.stepInfoLabel->setText(text);
+=09
+	// send the message to the log
+	printf(qPrintable(text + '\n'));
+}
+
+void DMXWizard::closeEvent(QCloseEvent *evt)
+{
+	// stop extraction if in progress before quitting
+	if (dmx.isRunning())
+		dmx.abort();
+
+	evt->accept();
+}
\ No newline at end of file

Added: trunk/DvdMenuXtractor/dmxwizard.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxwizard.h	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/dmxwizard.h	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,40 @@
+#ifndef DMXWIZARD_H
+#define DMXWIZARD_H
+
+#include <QDialog>
+#include "ui_dmxwizard.h"
+#include "dmxlogwidget.h"
+
+class DMXWizard : public QDialog
+{
+    Q_OBJECT
+
+public:
+   DMXWizard(QWidget *parent =3D 0);
+   ~DMXWizard();
+
+protected:
+	void closeEvent(QCloseEvent* evt);
+
+private slots:
+	void backButtonClicked();
+	void nextButtonClicked();
+	void browseButtonClicked();
+	void extractionFinished();
+	void pathEditTextChanged(const QString& path);
+	void extractionStepChanged(const QString& text);
+
+private:
+  Ui::DMXWizardClass ui;
+=09
+	DMX dmx;
+	DMXLogWidget logWidget_;
+
+	enum {SETTINGS_PAGE_INDEX =3D 0, SELECTION_PAGE_INDEX, EXTRACTION_PAGE_=
INDEX};
+
+	void setupSlots();
+	void loadSettings();
+	void storeSettings();
+};
+
+#endif // DMXWIZARD_H

Added: trunk/DvdMenuXtractor/dmxwizard.qrc
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxwizard.qrc	2007-01-22 11:21:16 UTC (rev 1269=
)
+++ trunk/DvdMenuXtractor/dmxwizard.qrc	2007-01-28 16:48:11 UTC (rev 1270=
)
@@ -0,0 +1,11 @@
+<RCC>
+    <qresource prefix=3D"/DMXWizard" >
+        <file>Resources/back.png</file>
+        <file>Resources/dmx.png</file>
+        <file>Resources/error.png</file>
+        <file>Resources/log.png</file>
+        <file>Resources/next.png</file>
+        <file>Resources/quit.png</file>
+        <file>Resources/warning.png</file>
+    </qresource>
+</RCC>

Added: trunk/DvdMenuXtractor/dmxwizard.ui
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/dmxwizard.ui	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/dmxwizard.ui	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,514 @@
+<ui version=3D"4.0" >
+ <class>DMXWizardClass</class>
+ <widget class=3D"QDialog" name=3D"DMXWizardClass" >
+  <property name=3D"geometry" >
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>500</width>
+    <height>416</height>
+   </rect>
+  </property>
+  <property name=3D"windowTitle" >
+   <string>DMXWizard</string>
+  </property>
+  <layout class=3D"QVBoxLayout" >
+   <property name=3D"margin" >
+    <number>9</number>
+   </property>
+   <property name=3D"spacing" >
+    <number>6</number>
+   </property>
+   <item>
+    <widget class=3D"QFrame" name=3D"frame" >
+     <property name=3D"frameShape" >
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name=3D"frameShadow" >
+      <enum>QFrame::Plain</enum>
+     </property>
+     <layout class=3D"QHBoxLayout" >
+      <property name=3D"margin" >
+       <number>9</number>
+      </property>
+      <property name=3D"spacing" >
+       <number>6</number>
+      </property>
+      <item>
+       <widget class=3D"QLabel" name=3D"imageLabel" >
+        <property name=3D"minimumSize" >
+         <size>
+          <width>64</width>
+          <height>64</height>
+         </size>
+        </property>
+        <property name=3D"maximumSize" >
+         <size>
+          <width>64</width>
+          <height>64</height>
+         </size>
+        </property>
+        <property name=3D"text" >
+         <string/>
+        </property>
+        <property name=3D"pixmap" >
+         <pixmap resource=3D"dmxwizard.qrc" >:/DMXWizard/Resources/dmx.p=
ng</pixmap>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class=3D"QLabel" name=3D"infoLabel" >
+        <property name=3D"alignment" >
+         <set>Qt::AlignCenter</set>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class=3D"QStackedWidget" name=3D"stackedWidget" >
+     <property name=3D"currentIndex" >
+      <number>1</number>
+     </property>
+     <widget class=3D"QWidget" name=3D"settingsPage" >
+      <layout class=3D"QGridLayout" >
+       <property name=3D"margin" >
+        <number>9</number>
+       </property>
+       <property name=3D"spacing" >
+        <number>6</number>
+       </property>
+       <item row=3D"3" column=3D"0" >
+        <widget class=3D"QLabel" name=3D"label_2" >
+         <property name=3D"text" >
+          <string>Output path</string>
+         </property>
+         <property name=3D"buddy" >
+          <cstring>outputPathEdit</cstring>
+         </property>
+        </widget>
+       </item>
+       <item row=3D"4" column=3D"1" >
+        <widget class=3D"QLineEdit" name=3D"toolsPathEdit" />
+       </item>
+       <item row=3D"3" column=3D"1" >
+        <widget class=3D"QLineEdit" name=3D"outputPathEdit" />
+       </item>
+       <item row=3D"3" column=3D"2" >
+        <widget class=3D"QPushButton" name=3D"outputBrowseButton" >
+         <property name=3D"text" >
+          <string>Browse...</string>
+         </property>
+        </widget>
+       </item>
+       <item row=3D"2" column=3D"1" >
+        <widget class=3D"QLineEdit" name=3D"dvdPathEdit" />
+       </item>
+       <item row=3D"1" column=3D"1" >
+        <spacer>
+         <property name=3D"orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name=3D"sizeHint" >
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row=3D"4" column=3D"2" >
+        <widget class=3D"QPushButton" name=3D"toolsBrowseButton" >
+         <property name=3D"text" >
+          <string>Browse...</string>
+         </property>
+        </widget>
+       </item>
+       <item row=3D"2" column=3D"0" >
+        <widget class=3D"QLabel" name=3D"label" >
+         <property name=3D"text" >
+          <string>DVD path</string>
+         </property>
+         <property name=3D"buddy" >
+          <cstring>dvdPathEdit</cstring>
+         </property>
+        </widget>
+       </item>
+       <item row=3D"5" column=3D"1" >
+        <layout class=3D"QHBoxLayout" >
+         <property name=3D"margin" >
+          <number>0</number>
+         </property>
+         <property name=3D"spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class=3D"QLabel" name=3D"errorImageLabel" >
+           <property name=3D"maximumSize" >
+            <size>
+             <width>24</width>
+             <height>24</height>
+            </size>
+           </property>
+           <property name=3D"pixmap" >
+            <pixmap resource=3D"dmxwizard.qrc" >:/DMXWizard/Resources/er=
ror.png</pixmap>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class=3D"QLabel" name=3D"errorInfoLabel" >
+           <property name=3D"sizePolicy" >
+            <sizepolicy>
+             <hsizetype>5</hsizetype>
+             <vsizetype>0</vsizetype>
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name=3D"minimumSize" >
+            <size>
+             <width>0</width>
+             <height>24</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row=3D"6" column=3D"1" >
+        <layout class=3D"QHBoxLayout" >
+         <property name=3D"margin" >
+          <number>0</number>
+         </property>
+         <property name=3D"spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <widget class=3D"QLabel" name=3D"warningImageLabel" >
+           <property name=3D"maximumSize" >
+            <size>
+             <width>24</width>
+             <height>24</height>
+            </size>
+           </property>
+           <property name=3D"pixmap" >
+            <pixmap resource=3D"dmxwizard.qrc" >:/DMXWizard/Resources/wa=
rning.png</pixmap>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class=3D"QLabel" name=3D"warningInfoLabel" >
+           <property name=3D"sizePolicy" >
+            <sizepolicy>
+             <hsizetype>5</hsizetype>
+             <vsizetype>0</vsizetype>
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name=3D"minimumSize" >
+            <size>
+             <width>0</width>
+             <height>24</height>
+            </size>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row=3D"2" column=3D"2" >
+        <widget class=3D"QPushButton" name=3D"dvdBrowseButton" >
+         <property name=3D"text" >
+          <string>Browse...</string>
+         </property>
+        </widget>
+       </item>
+       <item row=3D"7" column=3D"1" >
+        <spacer>
+         <property name=3D"orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name=3D"sizeHint" >
+          <size>
+           <width>20</width>
+           <height>31</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item row=3D"4" column=3D"0" >
+        <widget class=3D"QLabel" name=3D"label_3" >
+         <property name=3D"text" >
+          <string>Tools path</string>
+         </property>
+         <property name=3D"buddy" >
+          <cstring>toolsPathEdit</cstring>
+         </property>
+        </widget>
+       </item>
+       <item row=3D"0" column=3D"1" >
+        <widget class=3D"QLabel" name=3D"label_5" >
+         <property name=3D"text" >
+          <string>Please specify the required paths and click "Next" but=
ton</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class=3D"QWidget" name=3D"selectionPage" >
+      <layout class=3D"QVBoxLayout" >
+       <property name=3D"margin" >
+        <number>9</number>
+       </property>
+       <property name=3D"spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class=3D"QLabel" name=3D"label_4" >
+         <property name=3D"text" >
+          <string>Please select which tracks and subtracks you want to e=
xtract and press "Next" button</string>
+         </property>
+         <property name=3D"buddy" >
+          <cstring>selectionTree</cstring>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class=3D"DMXSelectionTree" name=3D"selectionTree" />
+       </item>
+      </layout>
+     </widget>
+     <widget class=3D"QWidget" name=3D"extractionPage" >
+      <layout class=3D"QVBoxLayout" >
+       <property name=3D"margin" >
+        <number>9</number>
+       </property>
+       <property name=3D"spacing" >
+        <number>6</number>
+       </property>
+       <item>
+        <widget class=3D"QLabel" name=3D"progressInfoLabel" >
+         <property name=3D"text" >
+          <string>Please wait...
+You can stop the process at any moment by clicking the "Stop" button.</s=
tring>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer>
+         <property name=3D"orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name=3D"sizeHint" >
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class=3D"QLabel" name=3D"stepInfoLabel" >
+         <property name=3D"text" >
+          <string>Step</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class=3D"QProgressBar" name=3D"progressBar" >
+         <property name=3D"value" >
+          <number>0</number>
+         </property>
+         <property name=3D"orientation" >
+          <enum>Qt::Horizontal</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <layout class=3D"QHBoxLayout" >
+         <property name=3D"margin" >
+          <number>0</number>
+         </property>
+         <property name=3D"spacing" >
+          <number>6</number>
+         </property>
+         <item>
+          <spacer>
+           <property name=3D"orientation" >
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name=3D"sizeHint" >
+            <size>
+             <width>40</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class=3D"QPushButton" name=3D"stopButton" >
+           <property name=3D"enabled" >
+            <bool>false</bool>
+           </property>
+           <property name=3D"text" >
+            <string>S&amp;top</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <spacer>
+         <property name=3D"orientation" >
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name=3D"sizeHint" >
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <layout class=3D"QHBoxLayout" >
+     <property name=3D"margin" >
+      <number>0</number>
+     </property>
+     <property name=3D"spacing" >
+      <number>6</number>
+     </property>
+     <item>
+      <widget class=3D"QPushButton" name=3D"logButton" >
+       <property name=3D"text" >
+        <string>&amp;Show Log</string>
+       </property>
+       <property name=3D"icon" >
+        <iconset resource=3D"dmxwizard.qrc" >:/DMXWizard/Resources/log.p=
ng</iconset>
+       </property>
+       <property name=3D"checkable" >
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name=3D"orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name=3D"sizeType" >
+        <enum>QSizePolicy::Expanding</enum>
+       </property>
+       <property name=3D"sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class=3D"QPushButton" name=3D"backButton" >
+       <property name=3D"enabled" >
+        <bool>false</bool>
+       </property>
+       <property name=3D"text" >
+        <string>&amp;Back</string>
+       </property>
+       <property name=3D"icon" >
+        <iconset resource=3D"dmxwizard.qrc" >:/DMXWizard/Resources/back.=
png</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class=3D"QPushButton" name=3D"nextButton" >
+       <property name=3D"enabled" >
+        <bool>false</bool>
+       </property>
+       <property name=3D"text" >
+        <string>&amp;Next</string>
+       </property>
+       <property name=3D"icon" >
+        <iconset resource=3D"dmxwizard.qrc" >:/DMXWizard/Resources/next.=
png</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer>
+       <property name=3D"orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name=3D"sizeType" >
+        <enum>QSizePolicy::Fixed</enum>
+       </property>
+       <property name=3D"sizeHint" >
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class=3D"QPushButton" name=3D"quitButton" >
+       <property name=3D"text" >
+        <string>&amp;Quit</string>
+       </property>
+       <property name=3D"icon" >
+        <iconset resource=3D"dmxwizard.qrc" >:/DMXWizard/Resources/quit.=
png</iconset>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing=3D"6" margin=3D"11" />
+ <customwidgets>
+  <customwidget>
+   <class>DMXSelectionTree</class>
+   <extends>QTreeWidget</extends>
+   <header>dmxselectiontree.h</header>
+  </customwidget>
+ </customwidgets>
+ <tabstops>
+  <tabstop>dvdPathEdit</tabstop>
+  <tabstop>dvdBrowseButton</tabstop>
+  <tabstop>outputPathEdit</tabstop>
+  <tabstop>outputBrowseButton</tabstop>
+  <tabstop>toolsPathEdit</tabstop>
+  <tabstop>toolsBrowseButton</tabstop>
+  <tabstop>logButton</tabstop>
+  <tabstop>backButton</tabstop>
+  <tabstop>nextButton</tabstop>
+  <tabstop>quitButton</tabstop>
+  <tabstop>selectionTree</tabstop>
+  <tabstop>stopButton</tabstop>
+ </tabstops>
+ <resources>
+  <include location=3D"dmxwizard.qrc" />
+ </resources>
+ <connections>
+  <connection>
+   <sender>quitButton</sender>
+   <signal>clicked()</signal>
+   <receiver>DMXWizardClass</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type=3D"sourcelabel" >
+     <x>489</x>
+     <y>380</y>
+    </hint>
+    <hint type=3D"destinationlabel" >
+     <x>479</x>
+     <y>260</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/bswap.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/bswap.h	2007-01-22 11:21:16 =
UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/bswap.h	2007-01-28 16:48:11 =
UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #ifndef BSWAP_H_INCLUDED
 #define BSWAP_H_INCLUDED
=20
@@ -20,8 +21,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U=
SA
  */
=20
-#include <config.h>
-
 #if defined(WORDS_BIGENDIAN)
 /* All bigendian systems are fine, just ignore the swaps. */ =20
 #define B2N_16(x) (void)(x)
@@ -57,40 +56,69 @@
 #include <sys/endian.h>
 #define B2N_16(x) x =3D be16toh(x)
 #define B2N_32(x) x =3D be32toh(x)
+#if __FreeBSD_version >=3D 500000
 #define B2N_64(x) x =3D be64toh(x)
+#else
+#define B2N_64(x)                               \
+  x =3D ((((x) & 0xff00000000000000) >> 56) |     \
+       (((x) & 0x00ff000000000000) >> 40) |     \
+       (((x) & 0x0000ff0000000000) >> 24) |     \
+       (((x) & 0x000000ff00000000) >>  8) |     \
+       (((x) & 0x00000000ff000000) <<  8) |     \
+       (((x) & 0x0000000000ff0000) << 24) |     \
+       (((x) & 0x000000000000ff00) << 40) |     \
+       (((x) & 0x00000000000000ff) << 56))
+#endif /* _FreeBSD_version >=3D 500000 */
=20
+#elif defined(__DragonFly__)
+#include <sys/endian.h>
+#define B2N_16(x) x =3D be16toh(x)
+#define B2N_32(x) x =3D be32toh(x)
+#define B2N_64(x) x =3D be64toh(x)
+
+
+#elif defined(__APPLE__) || defined(__DARWIN__)
+#include <libkern/OSByteOrder.h>
+#define B2N_16(x) x =3D OSSwapBigToHostConstInt16(x)
+#define B2N_32(x) x =3D OSSwapBigToHostConstInt32(x)
+#define B2N_64(x) x =3D OSSwapBigToHostConstInt64(x)
+
+#else
+#if defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || defin=
ed(WIN32) || defined(__BEOS__) || defined(__INTERIX)
+/* These systems don't have swap macros */
+#else
+/* If there isn't a header provided with your system with this functiona=
lity
+ * add the relevant || define( ) to the list above.
+ */
+#warning "You should add endian swap macros for your system"
+#endif
+
 /* This is a slow but portable implementation, it has multiple evaluatio=
n=20
  * problems so beware.
  * Old FreeBSD's and Solaris don't have <byteswap.h> or any other such=20
  * functionality!=20
  */
=20
-#elif defined(__FreeBSD__) || defined(__sun) || defined(__bsdi__) || def=
ined(WIN32) || defined( __BEOS__ )
-#define B2N_16(x) \
- x =3D ((((x) & 0xff00) >> 8) | \
-      (((x) & 0x00ff) << 8))
-#define B2N_32(x) \
- x =3D ((((x) & 0xff000000) >> 24) | \
-      (((x) & 0x00ff0000) >>  8) | \
-      (((x) & 0x0000ff00) <<  8) | \
-      (((x) & 0x000000ff) << 24))
-#define B2N_64(x) \
- x =3D ((((x) & 0xff00000000000000) >> 56) | \
-      (((x) & 0x00ff000000000000) >> 40) | \
-      (((x) & 0x0000ff0000000000) >> 24) | \
-      (((x) & 0x000000ff00000000) >>  8) | \
-      (((x) & 0x00000000ff000000) <<  8) | \
-      (((x) & 0x0000000000ff0000) << 24) | \
-      (((x) & 0x000000000000ff00) << 40) | \
-      (((x) & 0x00000000000000ff) << 56))
-
-#else
+#define B2N_16(x)                               \
+  x =3D ((((x) & 0xff00) >> 8) |                  \
+       (((x) & 0x00ff) << 8))
+#define B2N_32(x)                               \
+  x =3D ((((x) & 0xff000000) >> 24) |             \
+       (((x) & 0x00ff0000) >>  8) |             \
+       (((x) & 0x0000ff00) <<  8) |             \
+       (((x) & 0x000000ff) << 24))
+#define B2N_64(x)                               \
+  x =3D ((((x) & 0xff00000000000000) >> 56) |     \
+       (((x) & 0x00ff000000000000) >> 40) |     \
+       (((x) & 0x0000ff0000000000) >> 24) |     \
+       (((x) & 0x000000ff00000000) >>  8) |     \
+       (((x) & 0x00000000ff000000) <<  8) |     \
+       (((x) & 0x0000000000ff0000) << 24) |     \
+       (((x) & 0x000000000000ff00) << 40) |     \
+       (((x) & 0x00000000000000ff) << 56))
=20
-/* If there isn't a header provided with your system with this functiona=
lity
- * add the relevant || define( ) to the portable implementation above.
- */
-#error "You need to add endian swap macros for you're system"
=20
+
 #endif
=20
 #endif /* WORDS_BIGENDIAN */

Added: trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.c	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.c	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -0,0 +1,550 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Martin Norb=E4ck, H=E5kan Hjort
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,=20
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 =
 USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
+#include "cmd_print.h"
+
+
+typedef struct
+{
+  uint8_t bits[8];
+  uint8_t examined[8];
+} cmd_t;
+
+
+static const char *cmp_op_table[] =3D {
+  NULL, "&", "=3D=3D", "!=3D", ">=3D", ">", "<=3D", "<"
+};
+static const char *set_op_table[] =3D {
+  NULL, "=3D", "<->", "+=3D", "-=3D", "*=3D", "/=3D", "%=3D", "rnd", "&=3D=
", "|=3D", "^=3D"
+};
+
+static const char *link_table[] =3D {
+  "LinkNoLink",  "LinkTopC",    "LinkNextC",   "LinkPrevC",
+  NULL,          "LinkTopPG",   "LinkNextPG",  "LinkPrevPG",
+  NULL,          "LinkTopPGC",  "LinkNextPGC", "LinkPrevPGC",
+  "LinkGoUpPGC", "LinkTailPGC", NULL,          NULL,
+  "RSM"
+};
+
+static const char *system_reg_table[] =3D {
+  "Menu Description Language Code",
+  "Audio Stream Number",
+  "Sub-picture Stream Number",
+  "Angle Number",
+  "Title Track Number",
+  "VTS Title Track Number",
+  "VTS PGC Number",
+  "PTT Number for One_Sequential_PGC_Title",
+  "Highlighted Button Number",
+  "Navigation Timer",
+  "Title PGC Number for Navigation Timer",
+  "Audio Mixing Mode for Karaoke",
+  "Country Code for Parental Management",
+  "Parental Level",
+  "Player Configurations for Video",
+  "Player Configurations for Audio",
+  "Initial Language Code for Audio",
+  "Initial Language Code Extension for Audio",
+  "Initial Language Code for Sub-picture",
+  "Initial Language Code Extension for Sub-picture",
+  "Player Regional Code",
+  "Reserved 21",
+  "Reserved 22",
+  "Reserved 23"
+};
+
+static const char *system_reg_abbr_table[] =3D {
+  NULL,
+  "ASTN",
+  "SPSTN",
+  "AGLN",
+  "TTN",
+  "VTS_TTN",
+  "TT_PGCN",
+  "PTTN",
+  "HL_BTNN",
+  "NVTMR",
+  "NV_PGCN",
+  NULL,
+  "CC_PLT",
+  "PLT",
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+   =20
+
+
+static unsigned int bits(cmd_t *cmd, int byte, int bit, int count) {
+  unsigned int val =3D 0;
+  unsigned int bit_mask;
+ =20
+  while(count--) {
+    if(bit > 7) {
+      bit =3D 0;
+      byte++;
+    }
+    bit_mask =3D 0x01 << (7-bit);
+    val <<=3D 1;
+    if((cmd->bits[byte]) & bit_mask)
+      val |=3D 1;
+    cmd->examined[byte] |=3D bit_mask;
+    bit++;
+  }
+  return val;
+}
+
+
+static void print_system_reg(unsigned int reg) {
+  if(reg < sizeof(system_reg_abbr_table) / sizeof(char *))
+    fprintf(stdout, system_reg_table[reg]);
+  else
+    fprintf(stdout, " WARNING: Unknown system register ");
+}
+
+static void print_reg(unsigned int reg) {
+  if(reg & 0x80)
+    print_system_reg(reg & 0x7f);
+  else
+    if(reg < 16)
+      fprintf(stdout, "g[%u]", reg);
+    else
+      fprintf(stdout, " WARNING: Unknown general register ");
+}
+
+static void print_cmp_op(unsigned int op) {
+  if(op < sizeof(cmp_op_table) / sizeof(char *) && cmp_op_table[op] !=3D=
 NULL)
+    fprintf(stdout, " %s ", cmp_op_table[op]);
+  else
+    fprintf(stdout, " WARNING: Unknown compare op ");
+}
+
+static void print_set_op(unsigned int op) {
+  if(op < sizeof(set_op_table) / sizeof(char *) && set_op_table[op] !=3D=
 NULL)
+    fprintf(stdout, " %s ", set_op_table[op]);
+  else
+    fprintf(stdout, " WARNING: Unknown set op ");
+}
+
+static void print_reg_or_data(cmd_t *cmd, unsigned int immediate, int by=
te) {
+  if(immediate) {
+    int i =3D bits(cmd,byte,0,16);
+   =20
+    fprintf(stdout, "0x%x", i);
+    if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
+      fprintf(stdout, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0=
xff));
+  } else {
+    print_reg(bits(cmd,byte + 1,0,8));
+  }
+}
+
+static void print_reg_or_data_2(cmd_t *cmd, unsigned int immediate, int =
byte) {
+  if(immediate)
+    fprintf(stdout, "0x%x", bits(cmd,byte,1,7));
+  else
+    fprintf(stdout, "g[%u]", bits(cmd,byte,4,4));
+}
+
+static void print_if_version_1(cmd_t *cmd) {
+  unsigned int op =3D bits(cmd,1,1,3);
+ =20
+  if(op) {
+    fprintf(stdout, "if (");
+    print_reg(bits(cmd,3,0,8));
+    print_cmp_op(op);
+    print_reg_or_data(cmd,bits(cmd,1,0,1), 4);
+    fprintf(stdout, ") ");
+  }
+}
+
+static void print_if_version_2(cmd_t *cmd) {
+  unsigned int op =3D bits(cmd,1,1,3);
+ =20
+  if(op) {
+    fprintf(stdout, "if (");
+    print_reg(bits(cmd,6,0,8));
+    print_cmp_op(op);
+    print_reg(bits(cmd,7,0,8));
+    fprintf(stdout, ") ");
+  }
+}
+
+static void print_if_version_3(cmd_t *cmd) {
+  unsigned int op =3D bits(cmd,1,1,3);
+ =20
+  if(op) {
+    fprintf(stdout, "if (");
+    print_reg(bits(cmd,2,0,8));
+    print_cmp_op(op);
+    print_reg_or_data(cmd,bits(cmd,1,0,1), 6);
+    fprintf(stdout, ") ");
+  }
+}
+
+static void print_if_version_4(cmd_t *cmd) {
+  unsigned int op =3D bits(cmd,1,1,3);
+ =20
+  if(op) {
+    fprintf(stdout, "if (");
+    print_reg(bits(cmd,1,4,4));
+    print_cmp_op(op);
+    print_reg_or_data(cmd,bits(cmd,1,0,1), 4);
+    fprintf(stdout, ") ");
+  }
+}
+
+static void print_if_version_5(cmd_t *cmd) {
+  unsigned int op =3D bits(cmd,1,1,3);
+ =20
+  if(op) {
+    fprintf(stdout, "if (");
+    print_reg(bits(cmd,4,0,8));
+    print_cmp_op(op);
+    print_reg(bits(cmd,5,0,8));
+    fprintf(stdout, ") ");
+  }
+}
+
+static void print_special_instruction(cmd_t *cmd) {
+  unsigned int op =3D bits(cmd,1,4,4);
+ =20
+  switch(op) {
+  case 0: // NOP
+    fprintf(stdout, "Nop");
+    break;
+  case 1: // Goto line
+    fprintf(stdout, "Goto %u", bits(cmd,7,0,8));
+    break;
+  case 2: // Break
+    fprintf(stdout, "Break");
+    break;
+  case 3: // Parental level
+    fprintf(stdout, "SetTmpPML %u, Goto %u",=20
+            bits(cmd,6,4,4), bits(cmd,7,0,8));
+    break;
+  default:
+    fprintf(stdout, "WARNING: Unknown special instruction (%u)",=20
+            bits(cmd,1,4,4));
+  }
+}
+
+static void print_linksub_instruction(cmd_t *cmd) {
+  unsigned int linkop =3D bits(cmd,7,3,5);
+  unsigned int button =3D bits(cmd,6,0,6);
+ =20
+  if(linkop < sizeof(link_table)/sizeof(char *) && link_table[linkop] !=3D=
 NULL)
+    fprintf(stdout, "%s (button %u)", link_table[linkop], button);
+  else
+    fprintf(stdout, "WARNING: Unknown linksub instruction (%u)", linkop)=
;
+}
+
+static void print_link_instruction(cmd_t *cmd, int optional) {
+  unsigned int op =3D bits(cmd,1,4,4);
+ =20
+  if(optional && op)
+    fprintf(stdout, ", ");
+ =20
+  switch(op) {
+  case 0:
+    if(!optional)
+      fprintf(stdout, "WARNING: NOP (link)!");
+    break;
+  case 1:
+    print_linksub_instruction(cmd);
+    break;
+  case 4:
+    fprintf(stdout, "LinkPGCN %u", bits(cmd,6,1,15));
+    break;
+  case 5:
+    fprintf(stdout, "LinkPTT %u (button %u)",=20
+            bits(cmd,6,6,10), bits(cmd,6,0,6));
+    break;
+  case 6:
+    fprintf(stdout, "LinkPGN %u (button %u)",=20
+            bits(cmd,7,1,7), bits(cmd,6,0,6));
+    break;
+  case 7:
+    fprintf(stdout, "LinkCN %u (button %u)",=20
+            bits(cmd,7,0,8), bits(cmd,6,0,6));
+    break;
+  default:
+    fprintf(stdout, "WARNING: Unknown link instruction");
+  }
+}
+
+static void print_jump_instruction(cmd_t *cmd) {
+  switch(bits(cmd,1,4,4)) {
+  case 1:
+    fprintf(stdout, "Exit");
+    break;
+  case 2:
+    fprintf(stdout, "JumpTT %u", bits(cmd,5,1,7));
+    break;
+  case 3:
+    fprintf(stdout, "JumpVTS_TT %u", bits(cmd,5,1,7));
+    break;
+  case 5:
+    fprintf(stdout, "JumpVTS_PTT %u:%u", bits(cmd,5,1,7), bits(cmd,2,6,1=
0));
+    break;
+  case 6:
+    switch(bits(cmd,5,0,2)) {
+    case 0:
+      fprintf(stdout, "JumpSS FP");
+      break;
+    case 1:
+      fprintf(stdout, "JumpSS VMGM (menu %u)", bits(cmd,5,4,4));
+      break;
+    case 2:
+      fprintf(stdout, "JumpSS VTSM (vts %u, title %u, menu %u)",=20
+              bits(cmd,4,0,8), bits(cmd,3,0,8), bits(cmd,5,4,4));
+      break;
+    case 3:
+      fprintf(stdout, "JumpSS VMGM (pgc %u)", bits(cmd,2,1,15));
+      break;
+    }
+    break;
+  case 8:
+    switch(bits(cmd,5,0,2)) {
+    case 0:
+      fprintf(stdout, "CallSS FP (rsm_cell %u)",
+              bits(cmd,4,0,8));
+      break;
+    case 1:
+      fprintf(stdout, "CallSS VMGM (menu %u, rsm_cell %u)",
+              bits(cmd,5,4,4), bits(cmd,4,0,8));
+      break;
+    case 2:
+      fprintf(stdout, "CallSS VTSM (menu %u, rsm_cell %u)",
+              bits(cmd,5,4,4), bits(cmd,4,0,8));
+      break;
+    case 3:
+      fprintf(stdout, "CallSS VMGM (pgc %u, rsm_cell %u)",=20
+              bits(cmd,2,1,15), bits(cmd,4,0,8));
+      break;
+    }
+    break;
+  default:
+    fprintf(stdout, "WARNING: Unknown Jump/Call instruction");
+  }
+}
+
+static void print_system_set(cmd_t *cmd) {
+  int i;
+ =20
+  switch(bits(cmd,0,4,4)) {
+  case 1: // Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle)
+    for(i =3D 1; i <=3D 3; i++) {
+      if(bits(cmd,2+i,0,1)) {
+        print_system_reg((unsigned int)i);
+        fprintf(stdout, " =3D ");
+        print_reg_or_data_2(cmd,bits(cmd,0,3,1), 2 + i);
+        fprintf(stdout, " ");
+      }
+    }
+    break;
+  case 2: // Set system reg 9 & 10 (Navigation timer, Title PGC number)
+    print_system_reg(9);
+    fprintf(stdout, " =3D ");
+    print_reg_or_data(cmd,bits(cmd,0,3,1), 2);
+    fprintf(stdout, " ");
+    print_system_reg(10);
+    fprintf(stdout, " =3D %u", bits(cmd,5,0,8)); // ??
+    break;
+  case 3: // Mode: Counter / Register + Set
+    fprintf(stdout, "SetMode ");
+    if(bits(cmd,5,0,1))
+      fprintf(stdout, "Counter ");
+    else
+      fprintf(stdout, "Register ");
+    print_reg(bits(cmd,5,4,4));
+    print_set_op(0x1); // '=3D'
+    print_reg_or_data(cmd,bits(cmd,0,3,1), 2);
+    break;
+  case 6: // Set system reg 8 (Highlighted button)
+    print_system_reg(8);
+    if(bits(cmd,0,3,1)) // immediate
+      fprintf(stdout, " =3D 0x%x (button no %u)",=20
+              bits(cmd,4,0,16), bits(cmd,4,0,6));
+    else
+      fprintf(stdout, " =3D g[%u]", bits(cmd,5,4,4));
+    break;
+  default:
+    fprintf(stdout, "WARNING: Unknown system set instruction (%u)",=20
+            bits(cmd,0,4,4));
+  }
+}
+
+static void print_set_version_1(cmd_t *cmd) {
+  unsigned int set_op =3D bits(cmd,0,4,4);
+ =20
+  if(set_op) {
+    print_reg(bits(cmd,3,0,8));
+    print_set_op(set_op);
+    print_reg_or_data(cmd,bits(cmd,0,3,1), 4);
+  } else {
+    fprintf(stdout, "NOP");
+  }
+}
+
+static void print_set_version_2(cmd_t *cmd) {
+  unsigned int set_op =3D bits(cmd,0,4,4);
+ =20
+  if(set_op) {
+    print_reg(bits(cmd,1,4,4));
+    print_set_op(set_op);
+    print_reg_or_data(cmd,bits(cmd,0,3,1), 2);
+  } else {
+    fprintf(stdout, "NOP");
+  }
+}
+
+static void print_set_version_3(cmd_t *cmd) {
+  unsigned int set_op =3D bits(cmd,0,4,4);
+ =20
+  if(set_op) {
+    print_reg(bits(cmd,1,4,4));
+    print_set_op(set_op);
+    if(bits(cmd,0,3,1)) { // print_reg_or_data
+      unsigned int i =3D bits(cmd,2,0,16);
+     =20
+      fprintf(stdout, "0x%x", i);
+      if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
+        fprintf(stdout, " (\"%c%c\")",=20
+                (char)((i>>8) & 0xff), (char)(i & 0xff));
+    } else {
+      print_reg(bits(cmd,2,0,8));
+    }
+  } else {
+    fprintf(stdout, "NOP");
+  }
+}
+
+static void print_command(cmd_t *cmd) {
+  switch(bits(cmd,0,0,3)) { /* three first bits */
+  case 0: // Special instructions
+    print_if_version_1(cmd);
+    print_special_instruction(cmd);
+    break;
+  case 1: // Jump/Call or Link instructions
+    if(bits(cmd,0,3,1)) {
+      print_if_version_2(cmd);
+      print_jump_instruction(cmd);
+    } else {
+      print_if_version_1(cmd);
+      print_link_instruction(cmd,0); // must be pressent
+    }
+    break;
+  case 2: // Set System Parameters instructions
+    print_if_version_2(cmd);
+    print_system_set(cmd);
+    print_link_instruction(cmd,1); // either 'if' or 'link'
+    break;
+  case 3: // Set General Parameters instructions
+    print_if_version_3(cmd);
+    print_set_version_1(cmd);
+    print_link_instruction(cmd,1); // either 'if' or 'link'
+    break;
+  case 4: // Set, Compare -> LinkSub instructions
+    print_set_version_2(cmd);
+    fprintf(stdout, ", ");
+    print_if_version_4(cmd);
+    print_linksub_instruction(cmd);
+    break;
+  case 5: // Compare -> (Set and LinkSub) instructions
+    if(bits(cmd,0,3,1))
+      print_if_version_5(cmd);
+    else
+      print_if_version_1(cmd);
+    fprintf(stdout, "{ ");
+    print_set_version_3(cmd);
+    fprintf(stdout, ", ");
+    print_linksub_instruction(cmd);
+    fprintf(stdout, " }");
+    break;
+  case 6: // Compare -> Set, always LinkSub instructions
+    if(bits(cmd,0,3,1))
+      print_if_version_5(cmd);
+    else
+      print_if_version_1(cmd);
+    fprintf(stdout, "{ ");
+    print_set_version_3(cmd);
+    fprintf(stdout, " } ");
+    print_linksub_instruction(cmd);
+    break;
+  default:
+    fprintf(stdout, "WARNING: Unknown instruction type (%i)",=20
+            bits(cmd,0,0,3));
+  }
+}
+
+void cmdPrint_mnemonic(vm_cmd_t *command)  {
+  int i, extra_bits;
+  cmd_t cmd;
+ =20
+  for(i =3D 0; i < 8; i++) {
+    cmd.bits[i] =3D command->bytes[i];
+    cmd.examined[i] =3D 0;
+  }
+
+  print_command(&cmd);
+ =20
+  // Check if there still are bits set that were not examined
+  extra_bits =3D 0;
+  for(i =3D 0; i < 8; i++)
+    if(cmd.bits[i] & ~ cmd.examined[i]) {
+      extra_bits =3D 1;
+      break;
+    }
+  if(extra_bits) {
+    fprintf(stdout, " [WARNING, unknown bits:");
+    for(i =3D 0; i < 8; i++)
+      fprintf(stdout, " %02x", cmd.bits[i] & ~ cmd.examined[i]);
+    fprintf(stdout, "]");
+  }
+}
+
+void cmdPrint_CMD(int row, vm_cmd_t *command) {
+  int i;
+
+  fprintf(stdout, "(%03d) ", row + 1);
+  for(i =3D 0; i < 8; i++)
+    fprintf(stdout, "%02x ", command->bytes[i]);
+  fprintf(stdout, "| ");
+
+  cmdPrint_mnemonic(command);
+  fprintf(stdout, "\n");
+}

Added: trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.h	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/cmd_print.h	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -0,0 +1,51 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#ifndef CMD_PRINT_H_INCLUDED
+#define CMD_PRINT_H_INCLUDED
+
+/*
+ * Copyright (C) 2000, 2001, 2002, 2003 Martin Norb=E4ck, H=E5kan Hjort
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,=20
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 =
 USA
+ */
+
+#include <dvdread/ifo_types.h>
+
+/**
+ * Pretty printing of the DVD commands (vm instructions).
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ =20
+/**
+ * Prints a text representation of the commands to stdout.
+ *
+ * @param command Pointer to the DVD command to be printed.
+ */
+void cmdPrint_mnemonic(vm_cmd_t *command);
+ =20
+/**
+ * Prints row, then a hex dump of the command followed by the text
+ * representation of the commands, as given by cmdPrint_mnemonic to
+ * stdout.
+ *
+ * @param command Pointer to the DVD command to be printed.  */
+void cmdPrint_CMD(int row, vm_cmd_t *command);
+
+#ifdef __cplusplus
+};
+#endif
+#endif /* CMD_PRINT_H_INCLUDED */

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.c	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.c	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2002 Samuel Hocevar <sam at zoy.org>,
  *                    H=E5kan Hjort <d95hjort at dtek.chalmers.se>
@@ -19,22 +20,38 @@
=20
 #include "config.h"
=20
+#if defined(WIN32)
+#include "posix.h"
+#endif
 #include <stdio.h>
 #include <stdlib.h>
-#include <fcntl.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#define __USE_GNU /* to get O_DIRECT in linux */
+#include <fcntl.h>
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
 #endif
=20
+#if defined(WIN32)
+#include <io.h>	// for open(), close(), etc..
+#include <share.h>
+#endif
+
 #include "dvd_reader.h"
 #include "dvd_input.h"
=20
+#include "dvdread_internal.h"
+
 /* The function pointers that is the exported interface of this file. */
 dvd_input_t (*dvdinput_open)  (const char *);
 int         (*dvdinput_close) (dvd_input_t);
 int         (*dvdinput_seek)  (dvd_input_t, int);
 int         (*dvdinput_title) (dvd_input_t, int);=20
+/**
+ *  pointer must be aligned to 2048 bytes
+ *  if reading from a raw/O_DIRECT file
+ */
 int         (*dvdinput_read)  (dvd_input_t, void *, int, int);
+
 char *      (*dvdinput_error) (dvd_input_t);
=20
 #ifdef HAVE_DVDCSS_DVDCSS_H
@@ -45,11 +62,11 @@
 #define DVDcss_seek    dvdcss_seek
 #define DVDcss_title   dvdcss_title
 #define DVDcss_read    dvdcss_read
-#define DVDcss_error   dvdcss_error
-#else
-/* dlopening libdvdcss */
-#ifdef HAVE_DLFCN_H
-#include <dlfcn.h>
+#define DVDcss_error   dvdcss_error
+#else=20
+/* dlopening libdvdcss */
+#if defined(HAVE_DLFCN_H)
+#include <dlfcn.h>
 #endif
 typedef struct dvdcss_s *dvdcss_handle;
 static dvdcss_handle (*DVDcss_open)  (const char *);
@@ -70,10 +87,6 @@
 };
=20
=20
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
 /**
  * initialize and open a DVD device or file.
  */
@@ -84,16 +97,15 @@
   /* Allocate the handle structure */
   dev =3D (dvd_input_t) malloc(sizeof(struct dvd_input_s));
   if(dev =3D=3D NULL) {
-    LOG_ERROR( stderr, "libdvdread: Could not allocate memory.\n");
+    /* malloc has set errno to ENOMEM */
     return NULL;
   }
  =20
   /* Really open it with libdvdcss */
   dev->dvdcss =3D DVDcss_open(target);
   if(dev->dvdcss =3D=3D 0) {
-    LOG_ERROR( stderr, "libdvdread: Could not open %s with libdvdcss.\n"=
, target);
     free(dev);
-    return NULL;
+    dev =3D NULL;
   }
  =20
   return dev;
@@ -149,29 +161,45 @@
   return 0;
 }
=20
+/* Need to use O_BINARY for WIN32 */
+#ifndef O_BINARY
+#ifdef _O_BINARY
+#define O_BINARY _O_BINARY
+#else
+#define O_BINARY 0
+#endif
+#endif
=20
-
-
-
-
 /**
  * initialize and open a DVD device or file.
  */
 static dvd_input_t file_open(const char *target)
 {
   dvd_input_t dev;
+  char *use_odirect;
+  int oflags;
  =20
+  oflags =3D O_RDONLY | O_BINARY;
+  use_odirect =3D getenv("DVDREAD_USE_DIRECT");
+  if(use_odirect) {
+#ifndef O_DIRECT
+#define O_DIRECT 0
+#endif
+    oflags |=3D O_DIRECT;
+  }
   /* Allocate the library structure */
   dev =3D (dvd_input_t) malloc(sizeof(struct dvd_input_s));
   if(dev =3D=3D NULL) {
-    LOG_ERROR( stderr, "libdvdread: Could not allocate memory.\n");
     return NULL;
   }
  =20
   /* Open the device */
-  dev->fd =3D open(target, O_RDONLY|O_BINARY);
+#if defined(_CRT_NONSTDC_DEPRECATE)
+  dev->fd =3D _open(target, oflags);
+#else
+  dev->fd =3D open(target, oflags);
+#endif
   if(dev->fd < 0) {
-    perror("libdvdread: Could not open input");
     free(dev);
     return NULL;
   }
@@ -193,11 +221,15 @@
  */
 static int file_seek(dvd_input_t dev, int blocks)
 {
-  off_t pos;
+  off_t pos =3D (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN;
=20
-  pos =3D lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_S=
ET);
+#if defined(_CRT_NONSTDC_DEPRECATE)
+  pos =3D _lseek(dev->fd, pos, SEEK_SET);
+#else
+  pos =3D lseek(dev->fd, pos, SEEK_SET);
+#endif
   if(pos < 0) {
-      return pos;
+    return pos;
   }
   /* assert pos % DVD_VIDEO_LB_LEN =3D=3D 0 */
   return (int) (pos / DVD_VIDEO_LB_LEN);
@@ -218,12 +250,17 @@
 {
   size_t len;
   ssize_t ret;
- =20
+  unsigned char *buf =3D buffer;
+
   len =3D (size_t)blocks * DVD_VIDEO_LB_LEN;
  =20
   while(len > 0) {
    =20
-    ret =3D read(dev->fd, buffer, len);
+#if defined(_CRT_NONSTDC_DEPRECATE)
+	ret =3D _read(dev->fd, buf, len);
+#else
+    ret =3D read(dev->fd, buf, len);
+#endif
    =20
     if(ret < 0) {
       /* One of the reads failed, too bad.  We won't even bother
@@ -234,14 +271,19 @@
    =20
     if(ret =3D=3D 0) {
       /* Nothing more to read.  Return the whole blocks, if any, that we=
 got.
-	 and adjust the file possition back to the previous block boundary. */
+         and adjust the file possition back to the previous block bounda=
ry. */
       size_t bytes =3D (size_t)blocks * DVD_VIDEO_LB_LEN - len;
-      off_t over_read =3D -(bytes % DVD_VIDEO_LB_LEN);
-      /*off_t pos =3D*/ lseek(dev->fd, over_read, SEEK_CUR);
+      off_t over_read =3D (unsigned)-(bytes % DVD_VIDEO_LB_LEN);
+#if defined(_CRT_NONSTDC_DEPRECATE)
+      /*off_t pos =3D*/ _lseek(dev->fd, over_read, SEEK_CUR);
+#else
+	  /*off_t pos =3D*/ lseek(dev->fd, over_read, SEEK_CUR);
+#endif
       /* should have pos % 2048 =3D=3D 0 */
       return (int) (bytes / DVD_VIDEO_LB_LEN);
     }
    =20
+    buf+=3Dret;
     len -=3D ret;
   }
=20
@@ -255,7 +297,12 @@
 {
   int ret;
=20
+#if defined(_CRT_NONSTDC_DEPRECATE)
+  ret =3D _close(dev->fd);
+#else
   ret =3D close(dev->fd);
+#endif
+ =20
=20
   if(ret < 0)
     return ret;
@@ -264,20 +311,52 @@
=20
   return 0;
 }
-
-#if !defined(WIN32)
-typedef void *HMODULE;
-#endif
=20
-static HMODULE dvdcss_library =3D NULL;
=20
+static void *dvdcss_library =3D NULL;
+static int dvdcss_library_init =3D 0;
+
 /**
+ * Free any objects allocated by dvdinput_setup.
+ * Should only be called when libdvdread is not to be used any more.
+ * Closes dlopened libraries.
+ */
+void dvdinput_free(void)
+{
+#ifdef HAVE_DVDCSS_DVDCSS_H
+  /* linked statically, nothing to free */
+  return;
+#else
+  if(dvdcss_library) {
+    dlclose(dvdcss_library);
+    dvdcss_library =3D NULL;
+  }
+  dvdcss_library_init =3D 0;
+  return;
+#endif
+}
+
+
+/**
  * Setup read functions with either libdvdcss or minimal DVD access.
  */
 int dvdinput_setup(void)
 {
   char **dvdcss_version =3D NULL;
+  int verbose;
=20
+  /* dlopening libdvdcss */
+  if(dvdcss_library_init) {
+    /* libdvdcss is already dlopened, function ptrs set */
+    if(dvdcss_library) {
+      return 1; /* css available */
+    } else {
+      return 0; /* css not available */
+    }
+  }
+
+  verbose =3D get_verbose();
+ =20
 #ifdef HAVE_DVDCSS_DVDCSS_H
   /* linking to libdvdcss */
   dvdcss_library =3D &dvdcss_library;  /* Give it some value !=3D NULL *=
/
@@ -285,13 +364,12 @@
   dvdcss_version =3D &dvdcss_interface_2;
=20
 #else
-  /* dlopening libdvdcss */
-#if defined(WIN32)
-  dvdcss_library =3D LoadLibrary("libdvdcss.dll");
-#else /* !WIN32 */
+#if defined(WIN32)
+  dvdcss_library =3D LoadLibraryA("libdvdcss.dll");
+#else
   dvdcss_library =3D dlopen("libdvdcss.so.2", RTLD_LAZY);
-#endif /* !WIN32 */
- =20
+#endif
+
   if(dvdcss_library !=3D NULL) {
 #if defined(__OpenBSD__) && !defined(__ELF__)
 #define U_S "_"
@@ -314,31 +392,39 @@
     dvdcss_version =3D (char **)dlsym(dvdcss_library, U_S "dvdcss_interf=
ace_2");
=20
     if(dlsym(dvdcss_library, U_S "dvdcss_crack")) {
-      LOG_ERROR( stderr,=20
-	      "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n"
-	      "libdvdread: You should get the latest version from "
-	      "http://www.videolan.org/\n" );
+      if(verbose >=3D 0) {
+        fprintf(stderr,=20
+                "libdvdread: Old (pre-0.0.2) version of libdvdcss found.=
\n"
+                "libdvdread: You should get the latest version from "
+                "http://www.videolan.org/\n" );
+      }
       dlclose(dvdcss_library);
       dvdcss_library =3D NULL;
     } else if(!DVDcss_open  || !DVDcss_close || !DVDcss_title || !DVDcss=
_seek
-	      || !DVDcss_read || !DVDcss_error || !dvdcss_version) {
-      LOG_ERROR( stderr, "libdvdread: Missing symbols in libdvdcss.so.2,=
 "
-	      "this shouldn't happen !\n");
+              || !DVDcss_read || !DVDcss_error || !dvdcss_version) {
+      if(verbose >=3D 0) {
+        fprintf(stderr,  "libdvdread: Missing symbols in libdvdcss.so.2,=
 "
+                "this shouldn't happen !\n");
+      }
       dlclose(dvdcss_library);
+      dvdcss_library =3D NULL;
     }
   }
 #endif /* HAVE_DVDCSS_DVDCSS_H */
+
+  dvdcss_library_init =3D 1;
  =20
-  if(dvdcss_library !=3D NULL) {
+  if(dvdcss_library) {
     /*
-    char *psz_method =3D getenv( "DVDCSS_METHOD" );
-    char *psz_verbose =3D getenv( "DVDCSS_VERBOSE" );
-    LOG_ERROR( stderr, "DVDCSS_METHOD %s\n", psz_method);
-    LOG_ERROR( stderr, "DVDCSS_VERBOSE %s\n", psz_verbose);
+      char *psz_method =3D getenv( "DVDCSS_METHOD" );
+      char *psz_verbose =3D getenv( "DVDCSS_VERBOSE" );
+      fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method);
+      fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose);
     */
-    LOG_ERROR( stderr, "libdvdread: Using libdvdcss version %s for DVD a=
ccess\n",
-	    *dvdcss_version);
-   =20
+    if(verbose >=3D 1) {
+      fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD ac=
cess\n",
+              *dvdcss_version);
+    }
     /* libdvdcss wrapper functions */
     dvdinput_open  =3D css_open;
     dvdinput_close =3D css_close;
@@ -349,8 +435,9 @@
     return 1;
    =20
   } else {
-    LOG_ERROR( stderr, "libdvdread: Encrypted DVD support unavailable.\n=
");
-
+    if(verbose >=3D 1) {
+      fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"=
);
+    }
     /* libdvdcss replacement functions */
     dvdinput_open  =3D file_open;
     dvdinput_close =3D file_close;
@@ -361,13 +448,3 @@
     return 0;
   }
 }
-
-/*
-  clear the resources
-*/
-void dvdinput_unsetup()
-{
-	if (dvdcss_library)
-		dlclose(dvdcss_library);
-}
-

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.h	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_input.h	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #ifndef DVD_INPUT_H_INCLUDED
 #define DVD_INPUT_H_INCLUDED
=20
@@ -40,12 +41,15 @@
 extern char *      (*dvdinput_error) (dvd_input_t);
=20
 /**
+ * Free any objects allocated by dvdinput_setup.
+ * Should only be called when libdvdread is not to be used any more.
+ * Closes dlopened libraries.
+ */
+void dvdinput_free(void);
+
+/**
  * Setup function accessed by dvd_reader.c.  Returns 1 if there is CSS s=
upport.
  */
 int dvdinput_setup(void);
-/**
- * Release all resources used
- */
-void dvdinput_unsetup(void);
=20
 #endif /* DVD_INPUT_H_INCLUDED */

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.c	2007-01-22 11:2=
1:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.c	2007-01-28 16:4=
8:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2001, 2002, 2003 Billy Biggs <vektor at dumbterm.net>,
  *                                H=E5kan Hjort <d95hjort at dtek.chalmers.=
se>,
@@ -20,9 +21,12 @@
=20
 #include "config.h"
=20
+#if defined(WIN32)
+#include "posix.h"
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
-#ifdef HAVE_SYS_TIME_H
+#if !defined(WIN32)
 #include <sys/time.h> /* For the timing of dvdcss_title crack. */
 #endif
 #include <fcntl.h>
@@ -30,13 +34,13 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
-#ifdef HAVE_UNISTD_H
+#if defined(HAVE_UNISTD_H)
 #include <unistd.h>
 #endif
 #include <limits.h>
 #include <dirent.h>
 =20
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) =
|| defined(__bsdi__)|| defined(__DARWIN__)
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) =
|| defined(__bsdi__) || defined(__DARWIN__) || defined(__DragonFly__)
 #define SYS_BSD 1
 #endif
=20
@@ -48,53 +52,97 @@
 #include <mntent.h>
 #endif
=20
+#include "dvd_reader.h"
+#include "dvd_input.h"
 #include "dvd_udf.h"
-#include "dvd_input.h"
-#include "dvd_reader.h"
 #include "md5.h"
=20
+#include "dvdread_internal.h"
+
 #define DEFAULT_UDF_CACHE_LEVEL 1
=20
 struct dvd_reader_s {
-    /* Basic information. */
-    int isImageFile;
+  /* Basic information. */
+  int isImageFile;
  =20
-    /* Hack for keeping track of the css status.=20
-     * 0: no css, 1: perhaps (need init of keys), 2: have done init */
-    int css_state;
-    int css_title; /* Last title that we have called dvdinpute_title for=
. */
+  /* Hack for keeping track of the css status.=20
+   * 0: no css, 1: perhaps (need init of keys), 2: have done init */
+  int css_state;
+  int css_title; /* Last title that we have called dvdinpute_title for. =
*/
=20
-    /* Information required for an image file. */
-    dvd_input_t dev;
+  /* Information required for an image file. */
+  dvd_input_t dev;
=20
-    /* Information required for a directory path drive. */
-    char *path_root;
+  /* Information required for a directory path drive. */
+  char *path_root;
  =20
-    /* Filesystem cache */
-    int udfcache_level; /* 0 - turned off, 1 - on */
-    void *udfcache;
+  /* Filesystem cache */
+  int udfcache_level; /* 0 - turned off, 1 - on */
+  void *udfcache;
+
+  /* block aligned malloc */
+  void *align;
+ =20
+  /* error message verbosity level */
+  int verbose;
 };
=20
 struct dvd_file_s {
-    /* Basic information. */
-    dvd_reader_t *dvd;
+  /* Basic information. */
+  dvd_reader_t *dvd;
  =20
-    /* Hack for selecting the right css title. */
-    int css_title;
+  /* Hack for selecting the right css title. */
+  int css_title;
=20
-    /* Information required for an image file. */
-    uint32_t lb_start;
-    uint32_t seek_pos;
+  /* Information required for an image file. */
+  uint32_t lb_start;
+  uint32_t seek_pos;
=20
-    /* Information required for a directory path drive. */
-    size_t title_sizes[ 9 ];
-    dvd_input_t title_devs[ 9 ];
+  /* Information required for a directory path drive. */
+  size_t title_sizes[ 9 ];
+  dvd_input_t title_devs[ 9 ];
=20
-    /* Calculated at open-time, size in blocks. */
-    ssize_t filesize;
+  /* Calculated at open-time, size in blocks. */
+  ssize_t filesize;
 };
=20
+
+#define DVDREAD_VERBOSE_DEFAULT 0
+
+int get_verbose(void)
+{
+  char *dvdread_verbose;
+  int verbose;
+ =20
+  dvdread_verbose =3D getenv("DVDREAD_VERBOSE");
+  if(dvdread_verbose) {
+    verbose =3D (int)strtol(dvdread_verbose, NULL, 0);
+  } else {
+    verbose =3D DVDREAD_VERBOSE_DEFAULT;
+  }
+  return verbose;
+}
+
+int dvdread_verbose(dvd_reader_t *dvd)
+{
+  return dvd->verbose;
+}
+
+dvd_reader_t *device_of_file(dvd_file_t *file)
+{
+  return file->dvd;
+}
+
 /**
+ * Returns the compiled version. (DVDREAD_VERSION as an int)
+ */
+int DVDVersion(void)
+{
+  return DVDREAD_VERSION;
+}
+
+
+/**
  * Set the level of caching on udf
  * level =3D 0 (no caching)
  * level =3D 1 (caching filesystem info)
@@ -128,149 +176,213 @@
   dev->udfcache =3D cache;
 }
=20
+void *GetAlignHandle(dvd_reader_t *device)
+{
+  struct dvd_reader_s *dev =3D (struct dvd_reader_s *)device;
+ =20
+  return dev->align;
+}
=20
-#if defined(WIN32)
-#include <windows.h>
-#  define GETTIME(v)  v =3D GetTickCount ()
-#  define TIMEDIFF(v) (v.end - v.start)
-#else /* !WIN32 */
-#  define GETTIME(v)  gettimeofday (&v, NULL)
-#  define TIMEDIFF(v) (v.end.tv_sec - v.start.tv_sec)
-#endif /* !WIN32 */
+void SetAlignHandle(dvd_reader_t *device, void *align)
+{
+  struct dvd_reader_s *dev =3D (struct dvd_reader_s *)device;
=20
-struct TimeVal
+  dev->align =3D align;
+}
+
+#ifdef WIN32 /* replacement gettimeofday implementation */
+#include <sys/timeb.h>
+#include <winsock.h> // for timeval
+static int gettimeofday( struct timeval *tv, void *tz )
 {
-#if defined(WIN32)
-  DWORD start;
-  DWORD end;
-#else /* !WIN32 */
-  struct timeval start;
-  struct timeval end;
-#endif /* !WIN32 */
-};
+  struct timeb t;
+  ftime( &t );
+  tv->tv_sec =3D (long)t.time;
+  tv->tv_usec =3D t.millitm * 1000;
+  return 0;
+}
+#endif
=20
=20
 /* Loop over all titles and call dvdcss_title to crack the keys. */
 static int initAllCSSKeys( dvd_reader_t *dvd )
 {
-    struct TimeVal all_time;
-    struct TimeVal t_time;
-    char filename[ MAX_UDF_FILE_NAME_LEN ];
-    uint32_t start, len;
-    int title;
-=09
-    char *nokeys_str =3D getenv("DVDREAD_NOKEYS");
-    if(nokeys_str !=3D NULL)
-      return 0;
+  struct timeval all_s, all_e;
+  struct timeval t_s, t_e;
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
+  uint32_t start, len;
+  int title;
+       =20
+  char *nokeys_str =3D getenv("DVDREAD_NOKEYS");
+  if(nokeys_str !=3D NULL)
+    return 0;
    =20
-    LOG_ERROR( stderr, "\n" );
-    LOG_ERROR( stderr, "libdvdread: Attempting to retrieve all CSS keys\=
n" );
-    LOG_ERROR( stderr, "libdvdread: This can take a _long_ time, "
-	     "please be patient\n\n" );
-=09
-    GETTIME( all_time.start );
-=09
-    for( title =3D 0; title < 100; title++ ) {
-	GETTIME( t_time.start );
-	if( title =3D=3D 0 ) {
-	    sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
-	} else {
-	    sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
-	}
-	start =3D UDFFindFile( dvd, filename, &len );
-	if( start !=3D 0 && len !=3D 0 ) {
-	    /* Perform CSS key cracking for this title. */
-	    LOG_ERROR( stderr, "libdvdread: Get key for %s at 0x%08x\n",=20
-		     filename, start );
-	    if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
-		LOG_ERROR( stderr, "libdvdread: Error cracking CSS key for %s (0x%08x)=
\n", filename, start);
-	    }
-	    GETTIME( t_time.end );
-	    LOG_ERROR( stderr, "libdvdread: Elapsed time %ld\n", =20
-		     (long int) TIMEDIFF(t_time) );
-	}
-	   =20
-	if( title =3D=3D 0 ) continue;
-	   =20
-	GETTIME( t_time.start );
-	sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
-	start =3D UDFFindFile( dvd, filename, &len );
-	if( start =3D=3D 0 || len =3D=3D 0 ) break;
-	   =20
-	/* Perform CSS key cracking for this title. */
-	LOG_ERROR( stderr, "libdvdread: Get key for %s at 0x%08x\n",=20
-		 filename, start );
-	if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
-	    LOG_ERROR( stderr, "libdvdread: Error cracking CSS key for %s (0x%0=
8x)!!\n", filename, start);
-	}
-	GETTIME( t_time.end );
-	LOG_ERROR( stderr, "libdvdread: Elapsed time %ld\n", =20
-		 (long int) TIMEDIFF(t_time) );
+  if(dvd->verbose >=3D 1) {
+    fprintf( stderr, "\n" );
+    fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n"=
 );
+    fprintf( stderr, "libdvdread: This can take a _long_ time, "
+             "please be patient\n\n" );
+  }
+  gettimeofday(&all_s, NULL);
+       =20
+  for( title =3D 0; title < 100; title++ ) {
+    gettimeofday( &t_s, NULL );
+    if( title =3D=3D 0 ) {
+      sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
+    } else {
+      sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
     }
-    title--;
+    start =3D UDFFindFile( dvd, filename, &len );
+    if( start !=3D 0 && len !=3D 0 ) {
+      /* Perform CSS key cracking for this title. */
+      if(dvd->verbose >=3D 1) {
+        fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",=20
+                 filename, start );
+      }
+      if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
+        if(dvd->verbose >=3D 0) {
+          fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0=
x%08x)\n", filename, start);
+        }
+      }
+      gettimeofday( &t_e, NULL );
+      if(dvd->verbose >=3D 1) {
+        fprintf( stderr, "libdvdread: Elapsed time %ld\n", =20
+                 (long int) t_e.tv_sec - t_s.tv_sec );
+      }
+    }
+           =20
+    if( title =3D=3D 0 ) continue;
+           =20
+    gettimeofday( &t_s, NULL );
+    sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
+    start =3D UDFFindFile( dvd, filename, &len );
+    if( start =3D=3D 0 || len =3D=3D 0 ) break;
+           =20
+    /* Perform CSS key cracking for this title. */
+    if(dvd->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",=20
+               filename, start );
+    }
+    if( dvdinput_title( dvd->dev, (int)start ) < 0 ) {
+      if(dvd->verbose >=3D 0) {
+        fprintf( stderr, "libdvdread: Error cracking CSS key for %s (0x%=
08x)!!\n", filename, start);
+      }
+    }
+    gettimeofday( &t_e, NULL );
+    if(dvd->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Elapsed time %ld\n", =20
+               (long int) t_e.tv_sec - t_s.tv_sec );
+    }
+  }
+  title--;
    =20
-    LOG_ERROR( stderr, "libdvdread: Found %d VTS's\n", title );
-    GETTIME( all_time.end );
-    LOG_ERROR( stderr, "libdvdread: Elapsed time %ld\n", =20
-	     (long int) TIMEDIFF(all_time) );
-   =20
-    return 0;
+  if(dvd->verbose >=3D 1) {
+    fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
+  }
+  gettimeofday(&all_e, NULL);
+  if(dvd->verbose >=3D 1) {
+    fprintf( stderr, "libdvdread: Elapsed time %ld\n", =20
+             (long int) all_e.tv_sec - all_s.tv_sec );
+  }
+  return 0;
 }
=20
=20
=20
 /**
  * Open a DVD image or block device file.
+ * Checks if the root directory in the udf image file can be found.
+ * If not it assumes this isn't a valid udf image and returns NULL
  */
 static dvd_reader_t *DVDOpenImageFile( const char *location, int have_cs=
s )
 {
-    dvd_reader_t *dvd;
-    dvd_input_t dev;
-   =20
-    dev =3D dvdinput_open( location );
-    if( !dev ) {
-	LOG_ERROR( stderr, "libdvdread: Can't open %s for reading\n", location =
);
-	return 0;
+  dvd_reader_t *dvd;
+  dvd_input_t dev;
+  int verbose;
+
+  verbose =3D get_verbose();
+
+  dev =3D dvdinput_open( location );
+  if( !dev ) {
+    if(verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Can't open '%s' for reading: %s\n",
+               location, strerror(errno));
     }
+    return NULL;
+  }
=20
-    dvd =3D (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
-    if( !dvd ) return 0;
-    dvd->isImageFile =3D 1;
-    dvd->dev =3D dev;
-    dvd->path_root =3D 0;
+  dvd =3D (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
+  if( !dvd ) {
+    int tmp_errno =3D errno;
+    dvdinput_close(dev);
+    errno =3D tmp_errno;
+    return NULL;
+  }
+  dvd->verbose =3D verbose;
+  dvd->isImageFile =3D 1;
+  dvd->dev =3D dev;
+  dvd->path_root =3D NULL;
    =20
-    dvd->udfcache_level =3D DEFAULT_UDF_CACHE_LEVEL;
-    dvd->udfcache =3D NULL;
+  dvd->udfcache_level =3D DEFAULT_UDF_CACHE_LEVEL;
+  dvd->udfcache =3D NULL;
=20
-    if( have_css ) {
-      /* Only if DVDCSS_METHOD =3D title, a bit if it's disc or if
-       * DVDCSS_METHOD =3D key but region missmatch. Unfortunaly we
-       * don't have that information. */
+  dvd->align =3D NULL;
+
+  if( have_css ) {
+    /* Only if DVDCSS_METHOD =3D title, a bit if it's disc or if
+     * DVDCSS_METHOD =3D key but region missmatch. Unfortunaly we
+     * don't have that information. */
    =20
-      dvd->css_state =3D 1; /* Need key init. */
+    dvd->css_state =3D 1; /* Need key init. */
+  }
+  dvd->css_title =3D 0;
+ =20
+  /* sanity check, is it a valid UDF image, can we find the root dir */
+  if(!UDFFindFile(dvd, "/", NULL)) {
+    dvdinput_close(dvd->dev);
+    if(dvd->udfcache) {
+      FreeUDFCache(dvd, dvd->udfcache);
     }
-    dvd->css_title =3D 0;
-   =20
-    return dvd;
+    if(dvd->align) {
+      if(dvd->verbose >=3D 0) {
+        fprintf(stderr, "libdvdread: DVDOpenImageFile(): Memory leak in =
align functions 1\n");
+      }
+    }
+    free(dvd);
+    return NULL;
+  }
+  return dvd;
 }
=20
 static dvd_reader_t *DVDOpenPath( const char *path_root )
 {
-    dvd_reader_t *dvd;
+  dvd_reader_t *dvd;
=20
-    dvd =3D (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
-    if( !dvd ) return 0;
-    dvd->isImageFile =3D 0;
-    dvd->dev =3D 0;
-    dvd->path_root =3D strdup( path_root );
+  dvd =3D (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
+  if( !dvd ) {
+    return NULL;
+  }
+  dvd->verbose =3D get_verbose();
+  dvd->isImageFile =3D 0;
+  dvd->dev =3D 0;
+#if defined(_CRT_NONSTDC_DEPRECATE)
+  dvd->path_root =3D _strdup( path_root );
+#else
+  dvd->path_root =3D strdup( path_root );
+#endif
+  if(!dvd->path_root) {
+    free(dvd);
+    return 0;
+  }
+  dvd->udfcache_level =3D DEFAULT_UDF_CACHE_LEVEL;
+  dvd->udfcache =3D NULL;
=20
-    dvd->udfcache_level =3D DEFAULT_UDF_CACHE_LEVEL;
-    dvd->udfcache =3D NULL;
-   =20
-    dvd->css_state =3D 0; /* Only used in the UDF path */
-    dvd->css_title =3D 0; /* Only matters in the UDF path */
+  dvd->align =3D NULL;
=20
-    return dvd;
+  dvd->css_state =3D 0; /* Only used in the UDF path */
+  dvd->css_title =3D 0; /* Only matters in the UDF path */
+
+  return dvd;
 }
=20
 #if defined(__sun)
@@ -279,254 +391,339 @@
    /vol/rdsk/<name> */
 static char *sun_block2char( const char *path )
 {
-    char *new_path;
+  char *new_path;
=20
-    /* Must contain "/dsk/" */=20
-    if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
+  /* Must contain "/dsk/" */=20
+  if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
=20
-    /* Replace "/dsk/" with "/rdsk/" */
-    new_path =3D malloc( strlen(path) + 2 );
-    strcpy( new_path, path );
-    strcpy( strstr( new_path, "/dsk/" ), "" );
-    strcat( new_path, "/rdsk/" );
-    strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) );
+  /* Replace "/dsk/" with "/rdsk/" */
+  new_path =3D malloc( strlen(path) + 2 );
+  strcpy( new_path, path );
+  strcpy( strstr( new_path, "/dsk/" ), "" );
+  strcat( new_path, "/rdsk/" );
+  strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) );
=20
-    return new_path;
+  return new_path;
 }
 #endif
=20
 #if defined(SYS_BSD)
 /* FreeBSD /dev/(r)(a)cd0c (a is for atapi), recomended to _not_ use r
+   update: FreeBSD and DragonFly no longer uses the prefix so don't add =
it.
+
    OpenBSD /dev/rcd0c, it needs to be the raw device
    NetBSD  /dev/rcd0[d|c|..] d for x86, c (for non x86), perhaps others
    Darwin  /dev/rdisk0,  it needs to be the raw device
-   BSD/OS  /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will=
 do) */
+   BSD/OS  /dev/sr0c (if not mounted) or /dev/rsr0c ('c' any letter will=
 do)
+  =20
+   returns a string allocated with strdup which should be free()'d when
+   no longer used.
+*/
 static char *bsd_block2char( const char *path )
 {
-    char *new_path;
+#if defined(__FreeBSD__) || defined(__DragonFly__)
+  return (char *) strdup( path );
+#else
+  char *new_path;
=20
-    /* If it doesn't start with "/dev/" or does start with "/dev/r" exit=
 */=20
-    if( !strncmp( path, "/dev/",  5 ) || strncmp( path, "/dev/r", 6 ) )=20
-      return (char *) strdup( path );
+  /* If it doesn't start with "/dev/" or does start with "/dev/r" exit *=
/=20
+  if( strncmp( path, "/dev/",  5 ) || !strncmp( path, "/dev/r", 6 ) )=20
+    return (char *) strdup( path );
=20
-    /* Replace "/dev/" with "/dev/r" */
-    new_path =3D malloc( strlen(path) + 2 );
-    strcpy( new_path, "/dev/r" );
-    strcat( new_path, path + strlen( "/dev/" ) );
+  /* Replace "/dev/" with "/dev/r" */
+  new_path =3D malloc( strlen(path) + 2 );
+  strcpy( new_path, "/dev/r" );
+  strcat( new_path, path + strlen( "/dev/" ) );
=20
-    return new_path;
+  return new_path;
+#endif /* __FreeBSD__ || __DragonFly__ */
 }
 #endif
=20
+
 dvd_reader_t *DVDOpen( const char *path )
 {
-    struct stat fileinfo;
-    int ret, have_css;
-    char *dev_name =3D 0;
+  struct stat fileinfo;
+  int ret, have_css;
+  char *dev_name =3D NULL;
+  int internal_errno =3D 0;
+  int verbose;
=20
-    if( path =3D=3D NULL )
-      return 0;
+  if( path =3D=3D NULL ) {
+    errno =3D EINVAL;
+    return NULL;
+  }
+ =20
+  verbose =3D get_verbose();
=20
-    ret =3D stat( path, &fileinfo );
-    if( ret < 0 ) {
-	/* If we can't stat the file, give up */
-	LOG_ERROR( stderr, "libdvdread: Can't stat %s\n", path );
-	perror("");
-	return 0;
+#ifdef WIN32
+  /* Stat doesn't work on devices under mingwin/cygwin. */
+  //if( path[0] && path[1] =3D=3D ':' && path[2] =3D=3D '\0' )
+  //  {
+  //    /* Don't try to stat the file */
+  //    fileinfo.st_mode =3D S_IFBLK;
+  //  }
+  //else
+#endif
+    {
+      ret =3D stat( path, &fileinfo );
+      if( ret < 0 ) {
+        int tmp_errno =3D errno;
+        /* If we can't stat the file, give up */
+        if(verbose >=3D 1) {
+          fprintf( stderr, "libdvdread: Can't stat '%s': %s\n",
+                   path, strerror(errno));
+        }
+        errno =3D tmp_errno;
+        return NULL;
+      }
     }
=20
-    /* Try to open libdvdcss or fall back to standard functions */
-    have_css =3D dvdinput_setup();
+  /* Try to open libdvdcss or fall back to standard functions */
+  have_css =3D dvdinput_setup();
=20
-    /* First check if this is a block/char device or a file*/
-    if( S_ISBLK( fileinfo.st_mode ) ||=20
-	S_ISCHR( fileinfo.st_mode ) ||=20
-	S_ISREG( fileinfo.st_mode ) ) {
-
-	/**
-	 * Block devices and regular files are assumed to be DVD-Video images.
-	 */
+  /* First check if this is a block/char device or a file*/
+  if( S_ISBLK( fileinfo.st_mode ) ||=20
+      S_ISCHR( fileinfo.st_mode ) ||=20
+      S_ISREG( fileinfo.st_mode ) ) {
+    /**
+     * Block devices and regular files are assumed to be DVD-Video image=
s.
+     */
+    dvd_reader_t *dvd =3D NULL;
 #if defined(__sun)
-	return DVDOpenImageFile( sun_block2char( path ), have_css );
+    dev_name =3D sun_block2char( path );
 #elif defined(SYS_BSD)
-	return DVDOpenImageFile( bsd_block2char( path ), have_css );
+    dev_name =3D bsd_block2char( path );
+#elif defined(_CRT_NONSTDC_DEPRECATE)
+	dev_name =3D _strdup( path );
 #else
-	return DVDOpenImageFile( path, have_css );
+    dev_name =3D strdup( path );
 #endif
-
-    } else if( S_ISDIR( fileinfo.st_mode ) ) {
-	dvd_reader_t *auth_drive =3D 0;
-	char *path_copy;
+    dvd =3D DVDOpenImageFile( dev_name, have_css );
+    free( dev_name );
+   =20
+    return dvd;
+  } else if( S_ISDIR( fileinfo.st_mode ) ) {
+    dvd_reader_t *auth_drive =3D 0;
+    char *path_copy;
 #if defined(SYS_BSD)
-	struct fstab* fe;
+    struct fstab* fe;
 #elif defined(__sun) || defined(__linux__)
-	FILE *mntfile;
+    FILE *mntfile;
 #endif
=20
-	/* XXX: We should scream real loud here. */
-	if( !(path_copy =3D strdup( path ) ) ) return 0;
-
-	/* Resolve any symlinks and get the absolut dir name. */
-#if !defined(WIN32)
-	{
-#ifdef __BEOS__
-	    char *current_path;
-#endif
-	    char *new_path;
-#ifndef __BEOS__
-	    int cdir =3D open( ".", O_RDONLY );
-	   =20
-	    if( cdir >=3D 0 ) {
+    /* XXX: We should scream real loud here. */
+#if defined(_CRT_NONSTDC_DEPRECATE)
+	if( !(path_copy =3D _strdup( path ) ) ) return 0;
 #else
-	    current_path =3D getcwd( NULL, PATH_MAX );
-	    if( current_path ) {
+    if( !(path_copy =3D strdup( path ) ) ) return 0;
 #endif
-		chdir( path_copy );
-		new_path =3D getcwd( NULL, PATH_MAX );
-#ifndef __BEOS__
-		fchdir( cdir );
-		close( cdir );
-#else
-		chdir( current_path );
-#endif
-		if( new_path ) {
-		    free( path_copy );
-		    path_copy =3D new_path;
-		}
-	    }
-	}
-#endif
-=09
-	/**
-	 * If we're being asked to open a directory, check if that directory
-	 * is the mountpoint for a DVD-ROM which we can use instead.
-	 */
=20
-	if( strlen( path_copy ) > 1 ) {
-#if !defined(WIN32)
-	    if( path_copy[ strlen( path_copy ) - 1 ] =3D=3D '/' )=20
-		path_copy[ strlen( path_copy ) - 1 ] =3D '\0';
-#else
-	    if( path_copy[ strlen( path_copy ) - 1 ] =3D=3D '\\' )=20
-		path_copy[ strlen( path_copy ) - 1 ] =3D '\0';
+#ifndef WIN32 /* don't have fchdir, and getcwd( NULL, ... ) is strange *=
/
+    /* Resolve any symlinks and get the absolut dir name. */
+    {
+      char *new_path;
+      char *current_path;
+
+      current_path =3D malloc(PATH_MAX);
+      if(current_path) {
+        if(!getcwd(current_path, PATH_MAX)) {
+          free(current_path);
+          current_path =3D NULL;
+        }
+      }
+      if(current_path) {
+        chdir( path_copy );
+        new_path =3D malloc(PATH_MAX);
+        if(new_path) {
+          if(!getcwd(new_path, PATH_MAX )) {
+            free(new_path);
+            new_path =3D NULL;
+          }
+        }
+
+        chdir(current_path);
+        free(current_path);
+        if( new_path ) {
+          free( path_copy );
+          path_copy =3D new_path;
+        }
+      }
+    }
 #endif
-	}
+       =20
+    /**
+     * If we're being asked to open a directory, check if that directory
+     * is the mountpoint for a DVD-ROM which we can use instead.
+     */
=20
-	if( strlen( path_copy ) > 9 ) {
-	    if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),=20
-			     "/video_ts" ) ) {
-	      path_copy[ strlen( path_copy ) - 9 ] =3D '\0';
-	    }
-	}
+    if( strlen( path_copy ) > 1 ) {
+      if( path_copy[ strlen( path_copy ) - 1 ] =3D=3D '/' ) {
+        path_copy[ strlen( path_copy ) - 1 ] =3D '\0';
+      }
+    }
=20
+    if( strlen( path_copy ) >=3D 9 ) {
+      if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),=20
+                       "/video_ts" ) ) {
+        path_copy[ strlen( path_copy ) - 9 ] =3D '\0';
+        if(path_copy[0] =3D=3D '\0') {
+          path_copy[0] =3D '/';
+          path_copy[1] =3D '\0';
+        }
+      }
+    }
+
 #if defined(SYS_BSD)
-	if( ( fe =3D getfsfile( path_copy ) ) ) {
-	    dev_name =3D bsd_block2char( fe->fs_spec );
-	    LOG_ERROR( stderr,=20
-		     "libdvdread: Attempting to use device %s"
-		     " mounted on %s for CSS authentication\n",
-		     dev_name,
-		     fe->fs_file );
-	    auth_drive =3D DVDOpenImageFile( dev_name, have_css );
-	}
+    if( ( fe =3D getfsfile( path_copy ) ) ) {
+      dev_name =3D bsd_block2char( fe->fs_spec );
+      if(verbose >=3D 1) {
+        fprintf( stderr,
+                 "libdvdread: Attempting to use device %s"
+                 " mounted on %s%s\n",
+                 dev_name,
+                 fe->fs_file,
+                 have_css ? " for CSS authentication" : "");
+      }
+      auth_drive =3D DVDOpenImageFile( dev_name, have_css );
+      if(!auth_drive) {
+        internal_errno =3D errno;
+      }
+    }
 #elif defined(__sun)
-	mntfile =3D fopen( MNTTAB, "r" );
-	if( mntfile ) {
-	    struct mnttab mp;
-	    int res;
-
-	    while( ( res =3D getmntent( mntfile, &mp ) ) !=3D -1 ) {
-		if( res =3D=3D 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
-		    dev_name =3D sun_block2char( mp.mnt_special );
-		    LOG_ERROR( stderr,=20
-			     "libdvdread: Attempting to use device %s"
-			     " mounted on %s for CSS authentication\n",
-			     dev_name,
-			     mp.mnt_mountp );
-		    auth_drive =3D DVDOpenImageFile( dev_name, have_css );
-		    break;
-		}
-	    }
-	    fclose( mntfile );
-	}
+    mntfile =3D fopen( MNTTAB, "r" );
+    if( mntfile ) {
+      struct mnttab mp;
+      int res;
+     =20
+      while( ( res =3D getmntent( mntfile, &mp ) ) !=3D -1 ) {
+        if( res =3D=3D 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
+          dev_name =3D sun_block2char( mp.mnt_special );
+          if(verbose >=3D 1) {
+            fprintf( stderr,=20
+                     "libdvdread: Attempting to use device %s"
+                     " mounted on %s%s\n",
+                     dev_name,
+                     mp.mnt_mountp,
+                     have_css ? " for CSS authentication" : "");
+          }
+          auth_drive =3D DVDOpenImageFile( dev_name, have_css );
+          if(!auth_drive) {
+            internal_errno =3D errno;
+          }
+          break;
+        }
+      }
+      fclose( mntfile );
+    }
 #elif defined(__linux__)
-        mntfile =3D fopen( MOUNTED, "r" );
-        if( mntfile ) {
-            struct mntent *me;
+    mntfile =3D fopen( MOUNTED, "r" );
+    if( mntfile ) {
+      struct mntent *me;
 =20
-            while( ( me =3D getmntent( mntfile ) ) ) {
-                if( !strcmp( me->mnt_dir, path_copy ) ) {
-		    LOG_ERROR( stderr,=20
-			     "libdvdread: Attempting to use device %s"
-			     " mounted on %s for CSS authentication\n",
-			     me->mnt_fsname,
-			     me->mnt_dir );
-                    auth_drive =3D DVDOpenImageFile( me->mnt_fsname, hav=
e_css );
-		    dev_name =3D strdup(me->mnt_fsname);
-                    break;
-                }
-            }
-            fclose( mntfile );
-	}
+      while( ( me =3D getmntent( mntfile ) ) ) {
+        if( !strcmp( me->mnt_dir, path_copy ) ) {
+          if(verbose >=3D 1) {
+            fprintf( stderr,=20
+                     "libdvdread: Attempting to use device %s"
+                     " mounted on %s%s\n",
+                     me->mnt_fsname,
+                     me->mnt_dir,
+                     have_css ? " for CSS authentication" : "");
+          }
+          auth_drive =3D DVDOpenImageFile( me->mnt_fsname, have_css );
+          if(!auth_drive) {
+            internal_errno =3D errno;
+          }
+          dev_name =3D strdup(me->mnt_fsname);
+          break;
+        }
+      }
+      fclose( mntfile );
+    }
 #endif
-	if( !dev_name ) {
-	  LOG_ERROR( stderr, "libdvdread: Couldn't find device name.\n" );
-	} else if( !auth_drive ) {
-	    LOG_ERROR( stderr, "libdvdread: Device %s inaccessible, "
-		     "CSS authentication not available.\n", dev_name );
-	}
+    if( !dev_name ) {
+      if(verbose >=3D 1) {
+        fprintf( stderr, "libdvdread: Couldn't find device name.\n" );
+      }
+    } else if( !auth_drive ) {
+      if(verbose >=3D 1) {
+        fprintf( stderr, "libdvdread: Device %s inaccessible%s: %s\n",
+                 dev_name,
+                 have_css ? ", CSS authentication not available" : "",
+                 strerror(internal_errno));
+      }
+    }
=20
-	free( dev_name );
-	free( path_copy );
+    free( dev_name );
+    free( path_copy );
=20
-        /**
-         * If we've opened a drive, just use that.
-         */
-        if( auth_drive ) return auth_drive;
-
-        /**
-         * Otherwise, we now try to open the directory tree instead.
-         */
-        return DVDOpenPath( path );
+    /**
+     * If we've opened a drive, just use that.
+     */
+    if( auth_drive ) {
+      return auth_drive;
     }
+    /**
+     * Otherwise, we now try to open the directory tree instead.
+     */
+    return DVDOpenPath( path );
+  }
=20
-    /* If it's none of the above, screw it. */
-    LOG_ERROR( stderr, "libdvdread: Could not open %s\n", path );
-    return 0;
+  /* If it's none of the above, screw it. */
+  if(verbose >=3D 1) {
+    fprintf( stderr, "libdvdread: Could not open %s\n", path );
+  }
+  return 0;
 }
=20
 void DVDClose( dvd_reader_t *dvd )
 {
-    if( dvd ) {
-        if( dvd->dev ) dvdinput_close( dvd->dev );
-        if( dvd->path_root ) free( dvd->path_root );
-	if( dvd->udfcache ) FreeUDFCache( dvd->udfcache );
-        free( dvd );
+  if( dvd ) {
+    if( dvd->dev ) dvdinput_close( dvd->dev );
+    if( dvd->path_root ) free( dvd->path_root );
+    if( dvd->udfcache ) FreeUDFCache( dvd, dvd->udfcache );
+    if(dvd->align) {
+      if(dvd->verbose >=3D 0) {
+        fprintf(stderr, "libdvdread: DVDClose(): Memory leak in align fu=
nctions\n");
+      }
     }
-	dvdinput_unsetup();
+
+    free( dvd );
+  }
 }
=20
+void DVDInit(void)
+{
+  dvdinput_setup();
+}
+
+void DVDFinish(void)
+{
+  dvdinput_free();
+}
+
 /**
  * Open an unencrypted file on a DVD image file.
  */
 static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
 {
-    uint32_t start, len;
-    dvd_file_t *dvd_file;
+  uint32_t start, len;
+  dvd_file_t *dvd_file;
=20
-    start =3D UDFFindFile( dvd, filename, &len );
-    if( !start ) return 0;
+  start =3D UDFFindFile( dvd, filename, &len );
+  if( !start ) return 0;
=20
-    dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
-    if( !dvd_file ) return 0;
-    dvd_file->dvd =3D dvd;
-    dvd_file->lb_start =3D start;
-    dvd_file->seek_pos =3D 0;
-    memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
-    memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
-    dvd_file->filesize =3D len / DVD_VIDEO_LB_LEN;
+  dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
+  if( !dvd_file ) return 0;
+  dvd_file->dvd =3D dvd;
+  dvd_file->lb_start =3D start;
+  dvd_file->seek_pos =3D 0;
+  memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
+  memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
+  dvd_file->filesize =3D len / DVD_VIDEO_LB_LEN;
=20
-    return dvd_file;
+  return dvd_file;
 }
=20
 /**
@@ -537,55 +734,54 @@
  */
 static int findDirFile( const char *path, const char *file, char *filena=
me )=20
 {
-    DIR *dir;
-    struct dirent *ent;
+  DIR *dir;
+  struct dirent *ent;
=20
-    dir =3D opendir( path );
-    if( !dir ) return -2;
+  dir =3D opendir( path );
+  if( !dir ) return -2;
=20
-    while( ( ent =3D readdir( dir ) ) !=3D NULL ) {
-        if( !strcasecmp( ent->d_name, file ) ) {
-            sprintf( filename, "%s%s%s", path,
-                     ( ( path[ strlen( path ) - 1 ] =3D=3D '/' ) ? "" : =
"/" ),
-                     ent->d_name );
-			closedir(dir);
-            return 0;
-        }
+  while( ( ent =3D readdir( dir ) ) !=3D NULL ) {
+    if( !strcasecmp( ent->d_name, file ) ) {
+      sprintf( filename, "%s%s%s", path,
+               ( ( path[ strlen( path ) - 1 ] =3D=3D '/' ) ? "" : "/" ),
+               ent->d_name );
+      closedir(dir);
+      return 0;
     }
-
-	closedir(dir);
-    return -1;
+  }
+  closedir(dir);
+  return -1;
 }
=20
 static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filen=
ame )
 {
-    char video_path[ PATH_MAX + 1 ];
-    const char *nodirfile;
-    int ret;
+  char video_path[ PATH_MAX + 1 ];
+  const char *nodirfile;
+  int ret;
=20
-    /* Strip off the directory for our search */
-    if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
-        nodirfile =3D &(file[ 10 ]);
-    } else {
-        nodirfile =3D file;
-    }
+  /* Strip off the directory for our search */
+  if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
+    nodirfile =3D &(file[ 10 ]);
+  } else {
+    nodirfile =3D file;
+  }
=20
-    ret =3D findDirFile( dvd->path_root, nodirfile, filename );
+  ret =3D findDirFile( dvd->path_root, nodirfile, filename );
+  if( ret < 0 ) {
+    /* Try also with adding the path, just in case. */
+    sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root );
+    ret =3D findDirFile( video_path, nodirfile, filename );
     if( ret < 0 ) {
-        /* Try also with adding the path, just in case. */
-        sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root );
-        ret =3D findDirFile( video_path, nodirfile, filename );
-        if( ret < 0 ) {
-            /* Try with the path, but in lower case. */
-            sprintf( video_path, "%s/video_ts/", dvd->path_root );
-            ret =3D findDirFile( video_path, nodirfile, filename );
-            if( ret < 0 ) {
-                return 0;
-            }
-        }
+      /* Try with the path, but in lower case. */
+      sprintf( video_path, "%s/video_ts/", dvd->path_root );
+      ret =3D findDirFile( video_path, nodirfile, filename );
+      if( ret < 0 ) {
+        return 0;
+      }
     }
+  }
=20
-    return 1;
+  return 1;
 }
=20
 /**
@@ -593,510 +789,787 @@
  */
 static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
 {
-    char full_path[ PATH_MAX + 1 ];
-    dvd_file_t *dvd_file;
-    struct stat fileinfo;
-    dvd_input_t dev;
+  char full_path[ PATH_MAX + 1 ];
+  dvd_file_t *dvd_file;
+  struct stat fileinfo;
+  dvd_input_t dev;
=20
-    /* Get the full path of the file. */
-    if( !findDVDFile( dvd, filename, full_path ) ) return 0;
+  /* Get the full path of the file. */
+  if( !findDVDFile( dvd, filename, full_path ) ) return 0;
=20
-    dev =3D dvdinput_open( full_path );
-    if( !dev ) return 0;
+  dev =3D dvdinput_open( full_path );
+  if( !dev ) return 0;
=20
-    dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
-    if( !dvd_file ) return 0;
-    dvd_file->dvd =3D dvd;
-    dvd_file->lb_start =3D 0;
-    dvd_file->seek_pos =3D 0;
-    memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
-    memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
-    dvd_file->filesize =3D 0;
+  dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
+  if( !dvd_file ) return 0;
+  dvd_file->dvd =3D dvd;
+  dvd_file->lb_start =3D 0;
+  dvd_file->seek_pos =3D 0;
+  memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
+  memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
+  dvd_file->filesize =3D 0;
=20
-    if( stat( full_path, &fileinfo ) < 0 ) {
-        LOG_ERROR( stderr, "libdvdread: Can't stat() %s.\n", filename );
-        free( dvd_file );
-        return 0;
+  if( stat( full_path, &fileinfo ) < 0 ) {
+    if(dvd->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
     }
-    dvd_file->title_sizes[ 0 ] =3D fileinfo.st_size / DVD_VIDEO_LB_LEN;
-    dvd_file->title_devs[ 0 ] =3D dev;
-    dvd_file->filesize =3D dvd_file->title_sizes[ 0 ];
+    free( dvd_file );
+    return 0;
+  }
+  dvd_file->title_sizes[ 0 ] =3D fileinfo.st_size / DVD_VIDEO_LB_LEN;
+  dvd_file->title_devs[ 0 ] =3D dev;
+  dvd_file->filesize =3D dvd_file->title_sizes[ 0 ];
=20
-    return dvd_file;
+  return dvd_file;
 }
=20
 static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu=
 )
 {
-    char filename[ MAX_UDF_FILE_NAME_LEN ];
-    uint32_t start, len;
-    dvd_file_t *dvd_file;
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
+  uint32_t start, len;
+  dvd_file_t *dvd_file;
=20
-    if( title =3D=3D 0 ) {
-        sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
-    } else {
-        sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 =
: 1 );
-    }
-    start =3D UDFFindFile( dvd, filename, &len );
-    if( start =3D=3D 0 ) return 0;
+  if( title =3D=3D 0 ) {
+    sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
+  } else {
+    sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 =
);
+  }
+  start =3D UDFFindFile( dvd, filename, &len );
+  if( start =3D=3D 0 ) return 0;
=20
-    dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
-    if( !dvd_file ) return 0;
-    dvd_file->dvd =3D dvd;
-    /*Hack*/ dvd_file->css_title =3D title << 1 | menu;
-    dvd_file->lb_start =3D start;
-    dvd_file->seek_pos =3D 0;
-    memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
-    memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
-    dvd_file->filesize =3D len / DVD_VIDEO_LB_LEN;
+  dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
+  if( !dvd_file ) return 0;
+  dvd_file->dvd =3D dvd;
+  /*Hack*/ dvd_file->css_title =3D title << 1 | menu;
+  dvd_file->lb_start =3D start;
+  dvd_file->seek_pos =3D 0;
+  memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
+  memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
+  dvd_file->filesize =3D len / DVD_VIDEO_LB_LEN;
=20
-    /* Calculate the complete file size for every file in the VOBS */
-    if( !menu ) {
-        int cur;
+  /* Calculate the complete file size for every file in the VOBS */
+  if( !menu ) {
+    int cur;
=20
-        for( cur =3D 2; cur < 10; cur++ ) {
-            sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur )=
;
-            if( !UDFFindFile( dvd, filename, &len ) ) break;
-            dvd_file->filesize +=3D len / DVD_VIDEO_LB_LEN;
-        }
+    for( cur =3D 2; cur < 10; cur++ ) {
+      sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
+      if( !UDFFindFile( dvd, filename, &len ) ) break;
+      dvd_file->filesize +=3D len / DVD_VIDEO_LB_LEN;
     }
+  }
    =20
-    if( dvd->css_state =3D=3D 1 /* Need key init */ ) {
-        initAllCSSKeys( dvd );
-	dvd->css_state =3D 2;
-    }
-    /*   =20
-    if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
-        LOG_ERROR( stderr, "libdvdread: Error cracking CSS key for %s\n"=
,
-		 filename );
-    }
-    */
+  if( dvd->css_state =3D=3D 1 /* Need key init */ ) {
+    initAllCSSKeys( dvd );
+    dvd->css_state =3D 2;
+  }
+  /*   =20
+        if( dvdinput_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
+        fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
+        filename );
+        }
+  */
    =20
-    return dvd_file;
+  return dvd_file;
 }
=20
 static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int men=
u )
 {
-    char filename[ MAX_UDF_FILE_NAME_LEN ];
-    char full_path[ PATH_MAX + 1 ];
-    struct stat fileinfo;
-    dvd_file_t *dvd_file;
-    int i;
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
+  char full_path[ PATH_MAX + 1 ];
+  struct stat fileinfo;
+  dvd_file_t *dvd_file;
+  int i;
=20
-    dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
-    if( !dvd_file ) return 0;
-    dvd_file->dvd =3D dvd;
-    /*Hack*/ dvd_file->css_title =3D title << 1 | menu;
-    dvd_file->lb_start =3D 0;
-    dvd_file->seek_pos =3D 0;
-    memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
-    memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
-    dvd_file->filesize =3D 0;
+  dvd_file =3D (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
+  if( !dvd_file ) return 0;
+  dvd_file->dvd =3D dvd;
+  /*Hack*/ dvd_file->css_title =3D title << 1 | menu;
+  dvd_file->lb_start =3D 0;
+  dvd_file->seek_pos =3D 0;
+  memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
+  memset( dvd_file->title_devs, 0, sizeof( dvd_file->title_devs ) );
+  dvd_file->filesize =3D 0;
    =20
-    if( menu ) {
-        dvd_input_t dev;
+  if( menu ) {
+    dvd_input_t dev;
=20
-        if( title =3D=3D 0 ) {
-            sprintf( filename, "VIDEO_TS.VOB" );
-        } else {
-            sprintf( filename, "VTS_%02i_0.VOB", title );
-        }
-        if( !findDVDFile( dvd, filename, full_path ) ) {
-            free( dvd_file );
-            return 0;
-        }
+    if( title =3D=3D 0 ) {
+      sprintf( filename, "VIDEO_TS.VOB" );
+    } else {
+      sprintf( filename, "VTS_%02i_0.VOB", title );
+    }
+    if( !findDVDFile( dvd, filename, full_path ) ) {
+      free( dvd_file );
+      return 0;
+    }
=20
-        dev =3D dvdinput_open( full_path );
-        if( dev =3D=3D NULL ) {
-            free( dvd_file );
-            return 0;
-        }
+    dev =3D dvdinput_open( full_path );
+    if( dev =3D=3D NULL ) {
+      free( dvd_file );
+      return 0;
+    }
=20
-        if( stat( full_path, &fileinfo ) < 0 ) {
-            LOG_ERROR( stderr, "libdvdread: Can't stat() %s.\n", filenam=
e );
-            free( dvd_file );
-            return 0;
-        }
-        dvd_file->title_sizes[ 0 ] =3D fileinfo.st_size / DVD_VIDEO_LB_L=
EN;
-        dvd_file->title_devs[ 0 ] =3D dev;
-	dvdinput_title( dvd_file->title_devs[0], 0);
-        dvd_file->filesize =3D dvd_file->title_sizes[ 0 ];
+    if( stat( full_path, &fileinfo ) < 0 ) {
+      if(dvd->verbose >=3D 1) {
+        fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+      }
+      free( dvd_file );
+      return 0;
+    }
+    dvd_file->title_sizes[ 0 ] =3D fileinfo.st_size / DVD_VIDEO_LB_LEN;
+    dvd_file->title_devs[ 0 ] =3D dev;
+    dvdinput_title( dvd_file->title_devs[0], 0);
+    dvd_file->filesize =3D dvd_file->title_sizes[ 0 ];
=20
-    } else {
-        for( i =3D 0; i < 9; ++i ) {
+  } else {
+    for( i =3D 0; i < 9; ++i ) {
=20
-            sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
-            if( !findDVDFile( dvd, filename, full_path ) ) {
-                break;
-            }
+      sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
+      if( !findDVDFile( dvd, filename, full_path ) ) {
+        break;
+      }
=20
-            if( stat( full_path, &fileinfo ) < 0 ) {
-                LOG_ERROR( stderr, "libdvdread: Can't stat() %s.\n", fil=
ename );
-                break;
-            }
+      if( stat( full_path, &fileinfo ) < 0 ) {
+        if(dvd->verbose >=3D 1) {
+          fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+        }
+        break;
+      }
=20
-            dvd_file->title_sizes[ i ] =3D fileinfo.st_size / DVD_VIDEO_=
LB_LEN;
-            dvd_file->title_devs[ i ] =3D dvdinput_open( full_path );
-	    dvdinput_title( dvd_file->title_devs[ i ], 0 );
-            dvd_file->filesize +=3D dvd_file->title_sizes[ i ];
-        }
-        if( !dvd_file->title_devs[ 0 ] ) {
-            free( dvd_file );
-            return 0;
-        }
+      dvd_file->title_sizes[ i ] =3D fileinfo.st_size / DVD_VIDEO_LB_LEN=
;
+      dvd_file->title_devs[ i ] =3D dvdinput_open( full_path );
+      dvdinput_title( dvd_file->title_devs[ i ], 0 );
+      dvd_file->filesize +=3D dvd_file->title_sizes[ i ];
     }
+    if( !dvd_file->title_devs[ 0 ] ) {
+      free( dvd_file );
+      return 0;
+    }
+  }
=20
-    return dvd_file;
+  return dvd_file;
 }
=20
 dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,=20
-			 dvd_read_domain_t domain )
+                         dvd_read_domain_t domain )
 {
-    char filename[ MAX_UDF_FILE_NAME_LEN ];
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
    =20
-    /* Check arguments. */
-    if( dvd =3D=3D NULL || titlenum < 0 )
-      return NULL;
+  /* Check arguments. */
+  if( dvd =3D=3D NULL || titlenum < 0 ) {
+    errno =3D EINVAL;
+    return NULL;
+  }
=20
-    switch( domain ) {
-    case DVD_READ_INFO_FILE:
-        if( titlenum =3D=3D 0 ) {
-            sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
-        } else {
-            sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
-        }
-        break;
-    case DVD_READ_INFO_BACKUP_FILE:
-        if( titlenum =3D=3D 0 ) {
-            sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
-        } else {
-            sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
-        }
-        break;
-    case DVD_READ_MENU_VOBS:
-        if( dvd->isImageFile ) {
-            return DVDOpenVOBUDF( dvd, titlenum, 1 );
-        } else {
-            return DVDOpenVOBPath( dvd, titlenum, 1 );
-        }
-        break;
-    case DVD_READ_TITLE_VOBS:
-        if( titlenum =3D=3D 0 ) return 0;
-        if( dvd->isImageFile ) {
-            return DVDOpenVOBUDF( dvd, titlenum, 0 );
-        } else {
-            return DVDOpenVOBPath( dvd, titlenum, 0 );
-        }
-        break;
-    default:
-        LOG_ERROR( stderr, "libdvdread: Invalid domain for file open.\n"=
 );
-        return NULL;
+  switch( domain ) {
+  case DVD_READ_INFO_FILE:
+    if( titlenum =3D=3D 0 ) {
+      sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
+    } else {
+      sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
     }
-   =20
+    break;
+  case DVD_READ_INFO_BACKUP_FILE:
+    if( titlenum =3D=3D 0 ) {
+      sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
+    } else {
+      sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
+    }
+    break;
+  case DVD_READ_MENU_VOBS:
     if( dvd->isImageFile ) {
-        return DVDOpenFileUDF( dvd, filename );
+      return DVDOpenVOBUDF( dvd, titlenum, 1 );
     } else {
-        return DVDOpenFilePath( dvd, filename );
+      return DVDOpenVOBPath( dvd, titlenum, 1 );
     }
+    break;
+  case DVD_READ_TITLE_VOBS:
+    if( titlenum =3D=3D 0 ) return 0;
+    if( dvd->isImageFile ) {
+      return DVDOpenVOBUDF( dvd, titlenum, 0 );
+    } else {
+      return DVDOpenVOBPath( dvd, titlenum, 0 );
+    }
+    break;
+  default:
+    if(dvd->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
+    }
+    errno =3D EINVAL;
+    return NULL;
+  }
+   =20
+  if( dvd->isImageFile ) {
+    return DVDOpenFileUDF( dvd, filename );
+  } else {
+    return DVDOpenFilePath( dvd, filename );
+  }
 }
=20
 void DVDCloseFile( dvd_file_t *dvd_file )
 {
-    int i;
+  int i;
=20
-    if( dvd_file ) {
-        if( dvd_file->dvd->isImageFile ) {
-	    ;
-	} else {
-            for( i =3D 0; i < 9; ++i ) {
-                if( dvd_file->title_devs[ i ] ) {
-                    dvdinput_close( dvd_file->title_devs[i] );
-                }
-            }
+  if( dvd_file ) {
+    if( dvd_file->dvd->isImageFile ) {
+      ;
+    } else {
+      for( i =3D 0; i < 9; ++i ) {
+        if( dvd_file->title_devs[ i ] ) {
+          dvdinput_close( dvd_file->title_devs[i] );
         }
+      }
+    }
=20
-        free( dvd_file );
-        dvd_file =3D 0;
+    free( dvd_file );
+    dvd_file =3D 0;
+  }
+}
+
+static int DVDFileStatVOBUDF(dvd_reader_t *dvd, int title,=20
+                             int menu, dvd_stat_t *statbuf)
+{
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
+  uint32_t size;
+  off_t tot_size;
+  off_t parts_size[9];
+  int nr_parts =3D 0;
+  int n;
+=20
+  if( title =3D=3D 0 ) {
+    sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
+  } else {
+    sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 =
);
+  }
+  if(!UDFFindFile( dvd, filename, &size )) {
+    return -1;
+  }
+  tot_size =3D size;
+  nr_parts =3D 1;
+  parts_size[0] =3D size;
+
+  if( !menu ) {
+    int cur;
+
+    for( cur =3D 2; cur < 10; cur++ ) {
+      sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
+      if( !UDFFindFile( dvd, filename, &size ) ) {
+        break;
+      }
+      parts_size[nr_parts] =3D size;
+      tot_size +=3D size;
+      nr_parts++;
     }
+  }
+ =20
+  statbuf->size =3D tot_size;
+  statbuf->nr_parts =3D nr_parts;
+  for(n =3D 0; n < nr_parts; n++) {
+    statbuf->parts_size[n] =3D parts_size[n];
+  }
+  return 0;
 }
=20
-/* Internal, but used from dvd_udf.c */
+
+static int DVDFileStatVOBPath( dvd_reader_t *dvd, int title,
+                                       int menu, dvd_stat_t *statbuf )
+{
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
+  char full_path[ PATH_MAX + 1 ];
+  struct stat fileinfo;
+  off_t tot_size;
+  off_t parts_size[9];
+  int nr_parts =3D 0;
+  int n;
+
+=20
+   =20
+  if( title =3D=3D 0 ) {
+    sprintf( filename, "VIDEO_TS.VOB" );
+  } else {
+    sprintf( filename, "VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
+  }
+  if( !findDVDFile( dvd, filename, full_path ) ) {
+    return -1;
+  }
+ =20
+  if( stat( full_path, &fileinfo ) < 0 ) {
+    if(dvd->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+    }
+    return -1;
+  }
+ =20
+
+  tot_size =3D fileinfo.st_size;
+  nr_parts =3D 1;
+  parts_size[0] =3D fileinfo.st_size;
+
+  if( !menu ) {
+    int cur;
+   =20
+    for( cur =3D 2; cur < 10; cur++ ) {
+
+      sprintf( filename, "VTS_%02d_%d.VOB", title, cur );
+      if( !findDVDFile( dvd, filename, full_path ) ) {
+        break;
+      }
+
+      if( stat( full_path, &fileinfo ) < 0 ) {
+        if(dvd->verbose >=3D 1) {
+          fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+        }
+        break;
+      }
+     =20
+      parts_size[nr_parts] =3D fileinfo.st_size;
+      tot_size +=3D parts_size[nr_parts];
+      nr_parts++;
+    }
+  }
+
+  statbuf->size =3D tot_size;
+  statbuf->nr_parts =3D nr_parts;
+  for(n =3D 0; n < nr_parts; n++) {
+    statbuf->parts_size[n] =3D parts_size[n];
+  }
+  return 0;
+}
+
+
+int DVDFileStat(dvd_reader_t *dvd, int titlenum,=20
+                dvd_read_domain_t domain, dvd_stat_t *statbuf)
+{
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
+  char full_path[ PATH_MAX + 1 ];
+  struct stat fileinfo;
+  uint32_t size;
+
+  /* Check arguments. */
+  if( dvd =3D=3D NULL || titlenum < 0 ) {
+    errno =3D EINVAL;
+    return -1;
+  }
+
+  switch( domain ) {
+  case DVD_READ_INFO_FILE:
+    if( titlenum =3D=3D 0 ) {
+      sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
+    } else {
+      sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
+    }
+    break;
+  case DVD_READ_INFO_BACKUP_FILE:
+    if( titlenum =3D=3D 0 ) {
+      sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
+    } else {
+      sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
+    }
+    break;
+  case DVD_READ_MENU_VOBS:
+    if( dvd->isImageFile ) {
+      return DVDFileStatVOBUDF( dvd, titlenum, 1, statbuf );
+    } else {
+      return DVDFileStatVOBPath( dvd, titlenum, 1, statbuf );
+    }
+    break;
+  case DVD_READ_TITLE_VOBS:
+    if( titlenum =3D=3D 0 ) {
+      return -1;
+    }
+    if( dvd->isImageFile ) {
+      return DVDFileStatVOBUDF( dvd, titlenum, 0, statbuf );
+    } else {
+      return DVDFileStatVOBPath( dvd, titlenum, 0, statbuf );
+    }
+    break;
+  default:
+    if(dvd->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Invalid domain for file stat.\n" );
+    }
+    errno =3D EINVAL;
+    return -1;
+  }
+ =20
+  if( dvd->isImageFile ) {
+    if( UDFFindFile( dvd, filename, &size ) ) {
+      statbuf->size =3D size;
+      statbuf->nr_parts =3D 1;
+      statbuf->parts_size[0] =3D size;
+      return 0;
+    }
+  } else {
+    if( findDVDFile( dvd, filename, full_path ) )  {
+      if( stat( full_path, &fileinfo ) < 0 ) {
+        if(dvd->verbose >=3D 1) {
+          fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
+        }
+      } else {
+        statbuf->size =3D fileinfo.st_size;
+        statbuf->nr_parts =3D 1;
+        statbuf->parts_size[0] =3D statbuf->size;
+        return 0;
+      }
+    }
+  }
+  return -1;
+}
+
+/**
+ * Internal, but used from dvd_udf.c=20
+ *
+ * @param device A read handle.
+ * @param lb_number Logical block number to start read from.
+ * @param block_count Number of logical blocks to read.
+ * @param data Pointer to buffer where read data should be stored.
+ *             This buffer must be large enough to hold lb_number*2048 b=
ytes.
+ *             The pointer must be aligned to the logical block size whe=
n
+ *             reading from a raw/O_DIRECT device.
+ * @param encrypted 0 if no decryption shall be performed,
+ *                  1 if decryption shall be performed
+ * @param return Returns number of blocks read on success, negative on e=
rror
+ */
 int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
-			 size_t block_count, unsigned char *data,=20
-			 int encrypted )
+                      size_t block_count, unsigned char *data,=20
+                      int encrypted )
 {
-   int ret;
+  int ret;
=20
-   if( !device->dev ) {
-     	LOG_ERROR( stderr, "libdvdread: Fatal error in block read.\n" );
-	return 0;
-   }
+  if( !device->dev ) {
+    if(device->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
+    }
+    return 0;
+  }
=20
-   ret =3D dvdinput_seek( device->dev, (int) lb_number );
-   if( ret !=3D (int) lb_number ) {
-     	LOG_ERROR( stderr, "libdvdread: Can't seek to block %u\n", lb_numb=
er );
-	return 0;
-   }
+  ret =3D dvdinput_seek( device->dev, (int) lb_number );
+  if( ret !=3D (int) lb_number ) {
+    if(device->verbose >=3D 1) {
+      fprintf( stderr,
+               "libdvdread: UDFReadBlocksRaw: Can't seek to block %u\n",
+               lb_number );
+    }
+    return 0;
+  }
=20
-   return dvdinput_read( device->dev, (char *) data,=20
-			 (int) block_count, encrypted );
+  return dvdinput_read( device->dev, (char *) data,=20
+                        (int) block_count, encrypted );
 }
=20
-/* This is using a single input and starting from 'dvd_file->lb_start' o=
ffset.
+/**
+ * This is using a single input and starting from 'dvd_file->lb_start' o=
ffset.
  *
  * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset'
  * into the buffer located at 'data' and if 'encrypted' is set
  * descramble the data if it's encrypted.  Returning either an
- * negative error or the number of blocks read. */
+ * negative error or the number of blocks read.
+ *
+ * @param data Pointer to buffer where read data should be placed.
+ *             This buffer must be large enough to hold block_count*2048=
 bytes.
+ *             The pointer must be aligned to 2048 bytes when reading fr=
om
+ *             a raw/O_DIRECT device.
+ * @return Returns the number of blocks read on success or a negative er=
ror.
+ */
 static int DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
-			     size_t block_count, unsigned char *data,
-			     int encrypted )
+                             size_t block_count, unsigned char *data,
+                             int encrypted )
 {
-    return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
-			     block_count, data, encrypted );
+  return UDFReadBlocksRaw( dvd_file->dvd, dvd_file->lb_start + offset,
+                           block_count, data, encrypted );
 }
=20
-/* This is using possibly several inputs and starting from an offset of =
'0'.
- *
+/**
+ * This is using possibly several inputs and starting from an offset of =
'0'.
+ * data must be aligned to logical block size (2048 bytes) of the device
+ * for raw/O_DIRECT devices to work
  * Reads 'block_count' blocks from 'dvd_file' at block offset 'offset'
  * into the buffer located at 'data' and if 'encrypted' is set
  * descramble the data if it's encrypted.  Returning either an
- * negative error or the number of blocks read. */
+ * negative error or the number of blocks read.
+ *
+ * @param dvd_file A file read handle.
+ * @param offset Block offset from start of file.
+ * @return Returns number of blocks read on success, negative on error.
+ */
 static int DVDReadBlocksPath( dvd_file_t *dvd_file, unsigned int offset,
-			      size_t block_count, unsigned char *data,
-			      int encrypted )
+                              size_t block_count, unsigned char *data,
+                              int encrypted )
 {
-    int i;
-    int ret, ret2, off;
+  int i;
+  int ret, ret2, off;
=20
-    ret =3D 0;
-    ret2 =3D 0;
-    for( i =3D 0; i < 9; ++i ) {
-      if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */
+  ret =3D 0;
+  ret2 =3D 0;
+  for( i =3D 0; i < 9; ++i ) {
+    if( !dvd_file->title_sizes[ i ] ) return 0; /* Past end of file */
=20
-        if( offset < dvd_file->title_sizes[ i ] ) {
-            if( ( offset + block_count ) <=3D dvd_file->title_sizes[ i ]=
 ) {
-		off =3D dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
-                if( off < 0 || off !=3D (int)offset ) {
-		    LOG_ERROR( stderr, "libdvdread: Can't seek to block %d\n",=20
-			     offset );
-		    return off < 0 ? off : 0;
-		}
-                ret =3D dvdinput_read( dvd_file->title_devs[ i ], data,
-				     (int)block_count, encrypted );
-                break;
-            } else {
-                size_t part1_size =3D dvd_file->title_sizes[ i ] - offse=
t;
-		/* FIXME: Really needs to be a while loop.
-                 * (This is only true if you try and read >1GB at a time=
) */
-	=09
-                /* Read part 1 */
-                off =3D dvdinput_seek( dvd_file->title_devs[ i ], (int)o=
ffset );
-                if( off < 0 || off !=3D (int)offset ) {
-		    LOG_ERROR( stderr, "libdvdread: Can't seek to block %d\n",=20
-			     offset );
-		    return off < 0 ? off : 0;
-		}
-                ret =3D dvdinput_read( dvd_file->title_devs[ i ], data,
-				     (int)part1_size, encrypted );
-		if( ret < 0 ) return ret;
-		/* FIXME: This is wrong if i is the last file in the set.=20
-                 * also error from this read will not show in ret. */
-	=09
-		/* Does the next part exist? If not then return now. */
-		if( !dvd_file->title_devs[ i + 1 ] ) return ret;
+    if( offset < dvd_file->title_sizes[ i ] ) {
+      if( ( offset + block_count ) <=3D dvd_file->title_sizes[ i ] ) {
+        off =3D dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
+        if( off < 0 || off !=3D (int)offset ) {
+          if(dvd_file->dvd->verbose >=3D 1) {
+            fprintf( stderr, "libdvdread: DVDReadBlocksPath1: Can't seek=
 to block %d\n",=20
+                     offset );
+          }
+          return off < 0 ? off : 0;
+        }
+        ret =3D dvdinput_read( dvd_file->title_devs[ i ], data,
+                             (int)block_count, encrypted );
+        break;
+      } else {
+        size_t part1_size =3D dvd_file->title_sizes[ i ] - offset;
+        /* FIXME: Really needs to be a while loop.
+         * (This is only true if you try and read >1GB at a time) */
+               =20
+        /* Read part 1 */
+        off =3D dvdinput_seek( dvd_file->title_devs[ i ], (int)offset );
+        if( off < 0 || off !=3D (int)offset ) {
+          if(dvd_file->dvd->verbose >=3D 1) {
+            fprintf( stderr, "libdvdread: DVDReadBlocksPath2: Can't seek=
 to block %d\n",=20
+                     offset );
+          }
+          return off < 0 ? off : 0;
+        }
+        ret =3D dvdinput_read( dvd_file->title_devs[ i ], data,
+                             (int)part1_size, encrypted );
+        if( ret < 0 ) return ret;
+        /* FIXME: This is wrong if i is the last file in the set.=20
+         * also error from this read will not show in ret. */
+               =20
+        /* Does the next part exist? If not then return now. */
+        if( !dvd_file->title_devs[ i + 1 ] ) return ret;
=20
-                /* Read part 2 */
-                off =3D dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 =
);
-                if( off < 0 || off !=3D 0 ) {
-		    LOG_ERROR( stderr, "libdvdread: Can't seek to block %d\n",=20
-			     0 );
-		    return off < 0 ? off : 0;
-		}
-                ret2 =3D dvdinput_read( dvd_file->title_devs[ i + 1 ],=20
-				      data + ( part1_size
-					       * (int64_t)DVD_VIDEO_LB_LEN ),
-				      (int)(block_count - part1_size),
-				      encrypted );
-                if( ret2 < 0 ) return ret2;
-		break;
-            }
-        } else {
-            offset -=3D dvd_file->title_sizes[ i ];
+        /* Read part 2 */
+        off =3D dvdinput_seek( dvd_file->title_devs[ i + 1 ], 0 );
+        if( off < 0 || off !=3D 0 ) {
+          if(dvd_file->dvd->verbose >=3D 1) {
+            fprintf( stderr, "libdvdread: DVDReadBlocksPath3: Can't seek=
 to block %d\n", 0 );
+          }
+          return off < 0 ? off : 0;
         }
+        ret2 =3D dvdinput_read( dvd_file->title_devs[ i + 1 ],=20
+                              data + ( part1_size
+                                       * (int64_t)DVD_VIDEO_LB_LEN ),
+                              (int)(block_count - part1_size),
+                              encrypted );
+        if( ret2 < 0 ) return ret2;
+        break;
+      }
+    } else {
+      offset -=3D (unsigned int)dvd_file->title_sizes[ i ];
     }
+  }
=20
-    return ret + ret2;
+  return ret + ret2;
 }
=20
-/* This is broken reading more than 2Gb at a time is ssize_t is 32-bit. =
*/
+/**
+ * This is broken reading more than 2Gb at a time if ssize_t is 32-bit.
+ */
 ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,=20
-		       size_t block_count, unsigned char *data )
+                       size_t block_count, unsigned char *data )
 {
-    int ret;
+  int ret;
    =20
-    /* Check arguments. */
-    if( dvd_file =3D=3D NULL || offset < 0 || data =3D=3D NULL )
-      return -1;
+  /* Check arguments. */
+  if( dvd_file =3D=3D NULL || offset < 0 || data =3D=3D NULL )
+    return -1;
    =20
-    /* Hack, and it will still fail for multiple opens in a threaded app=
 ! */
-    if( dvd_file->dvd->css_title !=3D dvd_file->css_title ) {
-      dvd_file->dvd->css_title =3D dvd_file->css_title;
-      if( dvd_file->dvd->isImageFile ) {
-	dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start );
-      }=20
-      /* Here each vobu has it's own dvdcss handle, so no need to update=
=20
-      else {
-	dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_start );
-      }*/
-    }
-   =20
+  /* Hack, and it will still fail for multiple opens in a threaded app !=
 */
+  if( dvd_file->dvd->css_title !=3D dvd_file->css_title ) {
+    dvd_file->dvd->css_title =3D dvd_file->css_title;
     if( dvd_file->dvd->isImageFile ) {
-	ret =3D DVDReadBlocksUDF( dvd_file, (uint32_t)offset,=20
-				block_count, data, DVDINPUT_READ_DECRYPT );
-    } else {
-	ret =3D DVDReadBlocksPath( dvd_file, (unsigned int)offset,=20
-				 block_count, data, DVDINPUT_READ_DECRYPT );
-    }
+      dvdinput_title( dvd_file->dvd->dev, (int)dvd_file->lb_start );
+    }=20
+    /* Here each vobu has it's own dvdcss handle, so no need to update=20
+       else {
+       dvdinput_title( dvd_file->title_devs[ 0 ], (int)dvd_file->lb_star=
t );
+       }*/
+  }
    =20
-    return (ssize_t)ret;
+  if( dvd_file->dvd->isImageFile ) {
+    ret =3D DVDReadBlocksUDF( dvd_file, (uint32_t)offset,=20
+                            block_count, data, DVDINPUT_READ_DECRYPT );
+  } else {
+    ret =3D DVDReadBlocksPath( dvd_file, (unsigned int)offset,=20
+                             block_count, data, DVDINPUT_READ_DECRYPT );
+  }
+   =20
+  return (ssize_t)ret;
 }
=20
-int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
+int DVDFileSeek( dvd_file_t *dvd_file, int offset )
 {
-    /* Check arguments. */
-    if( dvd_file =3D=3D NULL || offset < 0 )
-       return -1;
+  /* Check arguments. */
+  if( dvd_file =3D=3D NULL || offset < 0 )
+    return -1;
    =20
-    if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) {
-       return -1;
-    }
-    dvd_file->seek_pos =3D (uint32_t) offset;
-    return offset;
+  if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) {
+    return -1;
+  }
+  dvd_file->seek_pos =3D (uint32_t) offset;
+  return offset;
 }
=20
+#ifndef HAVE_UINTPTR_T
+#warning "Assuming that (unsigned long) can hold (void *)"
+typedef unsigned long uintptr_t;
+#endif
+
+#define DVD_ALIGN(ptr) (void *)((((uintptr_t)(ptr)) + (DVD_VIDEO_LB_LEN-=
1)) \
+                                / DVD_VIDEO_LB_LEN * DVD_VIDEO_LB_LEN)
+
 ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size=
 )
 {
-    unsigned char *secbuf;
-    unsigned int numsec, seek_sector, seek_byte;
-    int ret;
+  unsigned char *secbuf_start;
+  unsigned char *secbuf; //must be aligned to 2048-bytes for raw/O_DIREC=
T
+  unsigned int numsec, seek_sector, seek_byte;
+  int ret;
    =20
-    /* Check arguments. */
-    if( dvd_file =3D=3D NULL || data =3D=3D NULL )
-      return -1;
+  /* Check arguments. */
+  if( dvd_file =3D=3D NULL || data =3D=3D NULL ) {
+    errno =3D EINVAL;
+    return -1;
+  }
+  seek_sector =3D dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
+  seek_byte   =3D dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
=20
-    seek_sector =3D dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
-    seek_byte   =3D dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
+  numsec =3D ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) +
+    ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 );
=20
-    numsec =3D ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) +
-      ( ( ( seek_byte + byte_size ) % DVD_VIDEO_LB_LEN ) ? 1 : 0 );
-   =20
-    secbuf =3D (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
-    if( !secbuf ) {
-	LOG_ERROR( stderr, "libdvdread: Can't allocate memory "=20
-		 "for file read!\n" );
-        return 0;
-    }
-   =20
-    if( dvd_file->dvd->isImageFile ) {
-	ret =3D DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector,=20
-				(size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
-    } else {
-	ret =3D DVDReadBlocksPath( dvd_file, seek_sector,=20
-				 (size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
-    }
+  /* must align to 2048 bytes if we are reading from raw/O_DIRECT */
+  secbuf_start =3D (unsigned char *) malloc( (numsec+1) * DVD_VIDEO_LB_L=
EN );
+  if( !secbuf_start ) {
+    /* errno will be set to ENOMEM by malloc */
+    return -1;
+  }
=20
-    if( ret !=3D (int) numsec ) {
-        free( secbuf );
-        return ret < 0 ? ret : 0;
-    }
+  secbuf =3D DVD_ALIGN(secbuf_start);
=20
-    memcpy( data, &(secbuf[ seek_byte ]), byte_size );
-    free( secbuf );
+  if( dvd_file->dvd->isImageFile ) {
+    ret =3D DVDReadBlocksUDF( dvd_file, (uint32_t) seek_sector,=20
+                            (size_t) numsec, secbuf, DVDINPUT_NOFLAGS );
+  } else {
+    ret =3D DVDReadBlocksPath( dvd_file, seek_sector,=20
+                             (size_t) numsec, secbuf, DVDINPUT_NOFLAGS )=
;
+  }
=20
-    dvd_file->seek_pos +=3D byte_size;
-    return byte_size;
+  if( ret !=3D (int) numsec ) {
+    free( secbuf_start );
+    return ret < 0 ? ret : 0;
+  }
+
+  memcpy( data, &(secbuf[ seek_byte ]), byte_size );
+  free( secbuf_start );
+
+  dvd_file->seek_pos +=3D (unsigned int)byte_size;
+  return byte_size;
 }
=20
 ssize_t DVDFileSize( dvd_file_t *dvd_file )
 {
-    /* Check arguments. */
-    if( dvd_file =3D=3D NULL )
-      return -1;
+  /* Check arguments. */
+  if( dvd_file =3D=3D NULL )
+    return -1;
    =20
-    return dvd_file->filesize;
+  return dvd_file->filesize;
 }
=20
 int DVDDiscID( dvd_reader_t *dvd, unsigned char *discid )
 {
-    struct md5_ctx ctx;
-    int title;
+  struct md5_ctx ctx;
+  int title;
+  int nr_of_files =3D 0;
+  int tmp_errno;
+  int nofiles_errno =3D ENOENT;
+  /* Check arguments. */
+  if( dvd =3D=3D NULL || discid =3D=3D NULL ) {
+    errno =3D EINVAL;
+    return -1;
+  }
+  /* Go through the first 10 IFO:s, in order,=20
+   * and md5sum them, i.e  VIDEO_TS.IFO and VTS_0?_0.IFO */
+  md5_init_ctx( &ctx );
+  for( title =3D 0; title < 10; title++ ) {
+    dvd_file_t *dvd_file =3D DVDOpenFile( dvd, title, DVD_READ_INFO_FILE=
 );
+    if( dvd_file !=3D NULL ) {
+      ssize_t bytes_read;
+      size_t file_size =3D dvd_file->filesize * DVD_VIDEO_LB_LEN;
+      char *buffer =3D malloc( file_size );
=20
-    /* Check arguments. */
-    if( dvd =3D=3D NULL || discid =3D=3D NULL )
-      return 0;
-   =20
-    /* Go through the first 10 IFO:s, in order,=20
-     * and md5sum them, i.e  VIDEO_TS.IFO and VTS_0?_0.IFO */
-    md5_init_ctx( &ctx );
-    for( title =3D 0; title < 10; title++ ) {
-	dvd_file_t *dvd_file =3D DVDOpenFile( dvd, title, DVD_READ_INFO_FILE );
-	if( dvd_file !=3D NULL ) {
-	    ssize_t bytes_read;
-	    size_t file_size =3D dvd_file->filesize * DVD_VIDEO_LB_LEN;
-	    char *buffer =3D malloc( file_size );
-	   =20
-	    if( buffer =3D=3D NULL ) {
-		LOG_ERROR( stderr, "libdvdread: DVDDiscId, failed to "
-			 "allocate memory for file read!\n" );
-		return -1;
-	    }
-	    bytes_read =3D DVDReadBytes( dvd_file, buffer, file_size );
-	    if( bytes_read !=3D file_size ) {
-		LOG_ERROR( stderr, "libdvdread: DVDDiscId read returned %d bytes"
-			 ", wanted %d\n", bytes_read, file_size );
-		DVDCloseFile( dvd_file );
-		return -1;
-	    }
-	   =20
-	    md5_process_bytes( buffer, file_size,  &ctx );
-	   =20
-	    DVDCloseFile( dvd_file );
-	    free( buffer );
-	}
+      nr_of_files++;
+
+      if( buffer =3D=3D NULL ) {
+        /* errno will be set to ENOMEM by malloc */
+        return -1;
+      }
+
+      bytes_read =3D DVDReadBytes( dvd_file, buffer, file_size );
+      if( bytes_read !=3D file_size ) {
+        tmp_errno =3D errno;
+        if(dvd->verbose >=3D 1) {
+          fprintf( stderr, "libdvdread: DVDDiscId read returned %d bytes=
"
+                   ", wanted %d\n", (int)bytes_read, (int)file_size );
+        }
+        free(buffer);
+        DVDCloseFile( dvd_file );
+        errno =3D tmp_errno;
+        return -1;
+      }
+           =20
+      md5_process_bytes( buffer, file_size,  &ctx );
+           =20
+      DVDCloseFile( dvd_file );
+      free( buffer );
+    } else {
+      if(errno !=3D ENOENT) {
+        nofiles_errno =3D errno;
+      }
     }
-    md5_finish_ctx( &ctx, discid );
-   =20
-    return 0;
+  }
+  md5_finish_ctx( &ctx, discid );
+  if(nr_of_files =3D=3D 0) {
+    errno =3D nofiles_errno;
+    return -1;
+  }
+  return 0;
 }
=20
=20
 int DVDISOVolumeInfo( dvd_reader_t *dvd,
-		      char *volid, unsigned int volid_size,
-		      unsigned char *volsetid, unsigned int volsetid_size )
+                      char *volid, unsigned int volid_size,
+                      unsigned char *volsetid, unsigned int volsetid_siz=
e )
 {
-  unsigned char *buffer;
+  unsigned char *buffer; /* must be aligned to 2048 for raw/O_DIRECT */
+  unsigned char *buffer_start;=20
   int ret;
=20
   /* Check arguments. */
-  if( dvd =3D=3D NULL )
-    return 0;
+  if( dvd =3D=3D NULL ) {
+    errno =3D EINVAL;
+    return -1;
+  }
  =20
   if( dvd->dev =3D=3D NULL ) {
     /* No block access, so no ISO... */
+    errno =3D EINVAL;
     return -1;
   }
  =20
-  buffer =3D malloc( DVD_VIDEO_LB_LEN );
-  if( buffer =3D=3D NULL ) {
-    LOG_ERROR( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
-	     "allocate memory for file read!\n" );
+  buffer_start =3D malloc( 2 * DVD_VIDEO_LB_LEN );
+  if( buffer_start =3D=3D NULL ) {
     return -1;
   }
=20
+  buffer =3D DVD_ALIGN(buffer_start);
+ =20
   ret =3D UDFReadBlocksRaw( dvd, 16, 1, buffer, 0 );
   if( ret !=3D 1 ) {
-    LOG_ERROR( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
-	     "read ISO9660 Primary Volume Descriptor!\n" );
+    if(dvd->verbose >=3D 1) {
+      fprintf( stderr, "libdvdread: DVDISOVolumeInfo, failed to "
+               "read ISO9660 Primary Volume Descriptor!\n" );
+    }
+    free(buffer_start);
     return -1;
   }
  =20
@@ -1104,7 +1577,7 @@
     unsigned int n;
     for(n =3D 0; n < 32; n++) {
       if(buffer[40+n] =3D=3D 0x20) {
-	break;
+        break;
       }
     }
    =20
@@ -1122,13 +1595,15 @@
     }
     memcpy(volsetid, &buffer[190], volsetid_size);
   }
+  free(buffer_start);
+
   return 0;
 }
=20
=20
 int DVDUDFVolumeInfo( dvd_reader_t *dvd,
-		      char *volid, unsigned int volid_size,
-		      unsigned char *volsetid, unsigned int volsetid_size )
+                      char *volid, unsigned int volid_size,
+                      unsigned char *volsetid, unsigned int volsetid_siz=
e )
 {
   int ret;
   /* Check arguments. */

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.h	2007-01-22 11:2=
1:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_reader.h	2007-01-28 16:4=
8:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #ifndef DVD_READER_H_INCLUDED
 #define DVD_READER_H_INCLUDED
=20
@@ -20,9 +21,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 =
 USA
  */
-
-#include <inttypes.h>
+
+#include <inttypes.h>	// include local inttypes for WIN32
 #include <sys/types.h>
+#ifdef _WIN32
+typedef SSIZE_T ssize_t;
+#endif
=20
 /**
  * The DVD access interface.
@@ -32,10 +36,11 @@
  */
=20
 /**
- * The current version.
+ * The current version. (0.9.4 =3D> 904, 1.2.3 =3D> 10203)
  */
-#define DVDREAD_VERSION 904
+#define DVDREAD_VERSION 907
=20
+
 /**
  * The length of one Logical Block of a DVD.
  */
@@ -61,6 +66,12 @@
 typedef struct dvd_file_s dvd_file_t;
=20
 /**
+ * Returns the compiled version. (DVDREAD_VERSION as an int)
+ */
+int DVDVersion(void);
+
+
+/**
  * Opens a block device of a DVD-ROM file, or an image file, or a direct=
ory
  * name for a mounted DVD or HD copy of a DVD.
  *
@@ -81,6 +92,10 @@
  * @return If successful a a read handle is returned. Otherwise 0 is ret=
urned.
  *
  * dvd =3D DVDOpen(path);
+ *
+ * Threads: this function uses chdir() and getcwd().
+ * The current working directory is global to all threads,
+ * so using chdir/getcwd in another thread could give unexpected results=
.
  */
 dvd_reader_t *DVDOpen( const char * );
=20
@@ -96,18 +111,83 @@
 void DVDClose( dvd_reader_t * );
=20
 /**
+ * Initializes libdvdread to be used with multithreading apps.
+ *
+ * You must call this function before using any other functions of libdv=
dread
+ * if you are going to use libdvdread in multiple threads in your progra=
m.
+ * If you are not using threads, or using libdvdread from just one threa=
d,
+ * you do not need to call this, but you are allowed to do so anyway.
  *=20
+ * There are several restrictions on how you can use libdvdread in
+ * multithreading apps, see further documentation.
+ *
+ * If you have called DVDFinish() you need to call DVDInit again to use
+ * libdvdread in multiple threads.
+ *
+ * DVDInit(void);
  */
+void DVDInit(void);
+
+/**
+ * frees any dlopened objects.
+ *
+ * You must DVDClose all handles opened with DVDOpen before calling this=
.
+ * Use this function if you need to close the dlopened libs and any othe=
r
+ * objects that have been dynamically allocated by libdvdread.
+ *=20
+ * DVDFinish(void);
+ */
+void DVDFinish(void);
+
+/**
+ *=20
+ */
 typedef enum {
   DVD_READ_INFO_FILE,        /**< VIDEO_TS.IFO  or VTS_XX_0.IFO (title) =
*/
   DVD_READ_INFO_BACKUP_FILE, /**< VIDEO_TS.BUP  or VTS_XX_0.BUP (title) =
*/
   DVD_READ_MENU_VOBS,        /**< VIDEO_TS.VOB  or VTS_XX_0.VOB (title) =
*/
   DVD_READ_TITLE_VOBS        /**< VTS_XX_[1-9].VOB (title).  All files i=
n=20
-				  the title set are opened and read as a
-				  single file. */
+                                the title set are opened and read as a
+                                single file. */
 } dvd_read_domain_t;
=20
 /**
+ *
+ */
+typedef struct {
+  off_t size;          /**< Total size of file in bytes */
+  int nr_parts;           /**< Number of file parts */
+  off_t parts_size[9]; /**< Size of each part in bytes */
+} dvd_stat_t;
+
+/**
+ * Stats a file on the DVD given the title number and domain.
+ * The information about the file is stored in a dvd_stat_t
+ * which contains information about the size of the file and
+ * the number of parts in case of a multipart file and the respective
+ * sizes of the parts.
+ * A multipart file is for instance VTS_02_1.VOB, VTS_02_2.VOB, VTS_02_3=
.VOB
+ * The size of VTS_02_1.VOB will be stored in stat->parts_size[0],
+ * VTS_02_2.VOB in stat->parts_size[1], ...
+ * The total size (sum of all parts) is stored in stat->size and
+ * stat->nr_parts will hold the number of parts.
+ * Only DVD_READ_TITLE_VOBS (VTS_??_[1-9].VOB) can be multipart files.
+ *=20
+ * This function is only of use if you want to get the size of each file
+ * in the filesystem. These sizes are not needed to use any other
+ * functions in libdvdread.=20
+ *
+ * @param dvd  A dvd read handle.
+ * @param titlenum Which Video Title Set should be used, VIDEO_TS is 0.
+ * @param domain Which domain.=20
+ * @param stat Pointer to where the result is stored.
+ * @return If successful 0, otherwise -1.
+ *
+ * int DVDFileStat(dvd, titlenum, domain, stat);
+ */
+int DVDFileStat(dvd_reader_t *, int, dvd_read_domain_t, dvd_stat_t *);
+ =20
+/**
  * Opens a file on the DVD given the title number and domain.
  *
  * If the title number is 0, the video manager information is opened
@@ -142,6 +222,8 @@
  * @param offset Block offset from the start of the file to start readin=
g at.
  * @param block_count Number of block to read.
  * @param data Pointer to a buffer to write the data into.
+ *             It must be aligned to the logical block size of the devic=
e when
+ *             reading from a raw/O_DIRECT device (2048 bytes for DVD)
  * @return Returns number of blocks read on success, -1 on error.
  *
  * blocks_read =3D DVDReadBlocks(dvd_file, offset, block_count, data);
@@ -175,7 +257,7 @@
  * bytes_read =3D DVDReadBytes(dvd_file, data, bytes);
  */
 ssize_t DVDReadBytes( dvd_file_t *, void *, size_t );
-
+ =20
 /**
  * Returns the file size in blocks.
  *
@@ -185,7 +267,7 @@
  * blocks =3D DVDFileSize(dvd_file);
  */
 ssize_t DVDFileSize( dvd_file_t * );
-
+ =20
 /**
  * Get a unique 128 bit disc ID.
  * This is the MD5 sum of VIDEO_TS.IFO and the VTS_0?_0.IFO files
@@ -220,7 +302,7 @@
  * @return 0 on success, -1 on error.
  */
 int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int,
-		      unsigned char *, unsigned int );
+                      unsigned char *, unsigned int );
=20
 /**
  * Get the ISO9660 VolumeIdentifier and VolumeSetIdentifier
@@ -244,7 +326,7 @@
  * @return 0 on success, -1 on error.
  */
 int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int,
-		      unsigned char *, unsigned int );
+                      unsigned char *, unsigned int );
=20
 /**
  * Sets the level of caching that is done when reading from a device
@@ -259,7 +341,7 @@
  * @return The level of caching.
  */
 int DVDUDFCacheLevel( dvd_reader_t *, int );
-
+ =20
 #ifdef __cplusplus
 };
 #endif

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.c	2007-01-22 11:21:1=
6 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.c	2007-01-28 16:48:1=
1 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * This code is based on dvdudf by:
  *   Christian Wolff <scarabaeus at convergence.de>.
@@ -33,28 +34,181 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
+
+#if defined(WIN32)
+#include "posix.h"
 #endif
 #include <sys/types.h>
 #include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
+#if defined(HAVE_UNISTD_H)
 #include <unistd.h>
 #endif
+#include <errno.h>
+
+#if defined(HAVE_INTTYPES_H)
 #include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
=20
 #include "dvd_reader.h"
 #include "dvd_udf.h"
+#include "dvdread_internal.h"
=20
+#ifndef EMEDIUMTYPE
+#define EMEDIUMTYPE ENOENT
+#endif
+
+#ifndef HAVE_UINTPTR_T
+#warning "Assuming that (unsigned long) can hold (void *)"
+typedef unsigned long uintptr_t;
+#endif
+
+#define DVD_ALIGN(ptr) (void *)((((uintptr_t)(ptr)) + (DVD_VIDEO_LB_LEN-=
1)) \
+                                / DVD_VIDEO_LB_LEN * DVD_VIDEO_LB_LEN)
+
+typedef struct {
+  void *start;
+  void *aligned;
+} dvdalign_ptrs_t;
+
+typedef struct {
+  dvdalign_ptrs_t *ptrs;
+  uint32_t ptrs_in_use;
+  uint32_t ptrs_max;
+} dvdalign_t;
+
+extern void *GetAlignHandle(dvd_reader_t *device);
+extern void SetAlignHandle(dvd_reader_t *device, void *align);
+
+/**
+ * Allocates aligned memory (for use with reads from raw/O_DIRECT device=
s).
+ * This memory must be freed with dvdalign_free()
+ * The size of the memory that is allocate is num_lbs*2048 bytes.
+ * The memory will be suitably aligned for use with
+ * block reads from raw/O_DIRECT device.
+ * @param num_lbs Number of logical blocks (2048 bytes) to allocate.
+ * @return Returns pointer to allocated memory, or NULL on failure
+ * This isn't supposed to be fast/efficient, if that is needed
+ * this function should be rewritten to use posix_memalign or similar.
+ * It's just needed for aligning memory for small block reads from
+ * raw/O_DIRECT devices.=20
+ * We assume that 2048 is enough alignment for all systems at the moment=
.
+ * Not thread safe. Only use this from one thread.
+ * Depends on sizeof(unsigned long) being at least as large as sizeof(vo=
id *)
+ */
+static void *dvdalign_lbmalloc(dvd_reader_t *device, uint32_t num_lbs)
+{
+  void *m;
+  uint32_t n;
+  dvdalign_t *a;
+ =20
+  m =3D malloc((num_lbs+1)*DVD_VIDEO_LB_LEN);
+  if(m =3D=3D NULL) {
+    return m;
+  }
+  a =3D (dvdalign_t *)GetAlignHandle(device);
+  if(a =3D=3D NULL) {
+    a =3D malloc(sizeof(dvdalign_t));
+    if(a =3D=3D NULL) {
+      return a;
+    }
+    a->ptrs =3D NULL;
+    a->ptrs_in_use =3D 0;
+    a->ptrs_max =3D 0;
+    SetAlignHandle(device, (void *)a);
+  }
+ =20
+  if(a->ptrs_in_use >=3D a->ptrs_max) {
+    a->ptrs =3D realloc(a->ptrs, (a->ptrs_max+10)*sizeof(dvdalign_ptrs_t=
));
+    if(a->ptrs =3D=3D NULL) {
+      free(m);
+      return NULL;
+    }
+    a->ptrs_max+=3D10;
+    for(n =3D a->ptrs_in_use; n < a->ptrs_max; n++) {
+      a->ptrs[n].start =3D NULL;
+      a->ptrs[n].aligned =3D NULL;
+    }
+    n =3D a->ptrs_in_use;
+  } else {
+    for(n =3D 0; n < a->ptrs_max; n++) {
+      if(a->ptrs[n].start =3D=3D NULL) {
+        break;
+      }
+    }
+  }
+
+  a->ptrs[n].start =3D m;
+  a->ptrs[n].aligned =3D DVD_ALIGN(m);
+
+  a->ptrs_in_use++;
+
+  /* If this function starts to be used too much print a warning.
+     Either there is a memory leak somewhere or we need to rewrite this =
to
+     a more efficient version.
+  */
+  if(a->ptrs_in_use > 50) {
+    if(dvdread_verbose(device) >=3D 0) {
+      fprintf(stderr, "libdvdread: dvdalign_lbmalloc(), more allocs than=
 supposed: %u\n", a->ptrs_in_use);
+    }
+  }
+
+  return  a->ptrs[n].aligned;
+}
+
+/**
+ * Frees memory allocated with dvdalign_lbmemory()=20
+ * @param ptr Pointer to memory space to free
+ * Not thread safe.
+ */
+static void dvdalign_lbfree(dvd_reader_t *device, void *ptr)
+{
+  uint32_t n;
+  dvdalign_t *a;
+
+  a =3D (dvdalign_t *)GetAlignHandle(device);
+  if(a && a->ptrs) {
+    for(n =3D 0; n < a->ptrs_max; n++) {
+      if(a->ptrs[n].aligned =3D=3D ptr) {
+        free(a->ptrs[n].start);
+        a->ptrs[n].start =3D NULL;
+        a->ptrs[n].aligned =3D NULL;
+        a->ptrs_in_use--;
+        if(a->ptrs_in_use =3D=3D 0) {
+          free(a->ptrs);
+          a->ptrs =3D NULL;
+          a->ptrs_max =3D 0;
+          free(a);
+          a =3D NULL;
+          SetAlignHandle(device, (void *)a);
+        }
+        return;
+      }
+    }
+  }
+  if(dvdread_verbose(device) >=3D 0) {
+    fprintf(stderr, "libdvdread: dvdalign_lbfree(), error trying to free=
 mem: %08lx (%u)\n", (unsigned long)ptr, a ? a->ptrs_in_use : 0);
+  }
+}
+
+
 /* Private but located in/shared with dvd_reader.c */
 extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number,
-				size_t block_count, unsigned char *data,=20
-				int encrypted );
+                             size_t block_count, unsigned char *data,=20
+                             int encrypted );
=20
-/* It's required to either fail or deliver all the blocks asked for. */
+/** @internal
+ * Its required to either fail or deliver all the blocks asked for.=20
+ *
+ * @param data Pointer to a buffer where data is returned. This must be =
large
+ *   enough to hold lb_number*2048 bytes.
+ *   It must be aligned to system specific (2048) logical blocks size wh=
en
+ *   reading from raw/O_DIRECT device.
+ */
 static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
-			 size_t block_count, unsigned char *data,=20
-			 int encrypted )
+                         size_t block_count, unsigned char *data,=20
+                         int encrypted )
 {
   int ret;
   size_t count =3D block_count;
@@ -82,21 +236,21 @@
 #endif
=20
 struct Partition {
-    int valid;
-    char VolumeDesc[128];
-    uint16_t Flags;
-    uint16_t Number;
-    char Contents[32];
-    uint32_t AccessType;
-    uint32_t Start;
-    uint32_t Length;
+  int valid;
+  char VolumeDesc[128];
+  uint16_t Flags;
+  uint16_t Number;
+  char Contents[32];
+  uint32_t AccessType;
+  uint32_t Start;
+  uint32_t Length;
 };
=20
 struct AD {
-    uint32_t Location;
-    uint32_t Length;
-    uint8_t  Flags;
-    uint16_t Partition;
+  uint32_t Location;
+  uint32_t Length;
+  uint8_t  Flags;
+  uint16_t Partition;
 };
=20
 struct extent_ad {
@@ -147,12 +301,24 @@
 extern void *GetUDFCacheHandle(dvd_reader_t *device);
 extern void SetUDFCacheHandle(dvd_reader_t *device, void *cache);
=20
-void FreeUDFCache(void *cache)
+
+void FreeUDFCache(dvd_reader_t *device, void *cache)
 {
+  int n;
+ =20
   struct udf_cache *c =3D (struct udf_cache *)cache;
   if(c =3D=3D NULL) {
     return;
   }
+
+  for(n =3D 0; n < c->lb_num; n++) {
+    if(c->lbs[n].data) {
+      /* free data */
+      dvdalign_lbfree(device, c->lbs[n].data);
+    }
+  }
+  c->lb_num =3D 0;
+
   if(c->lbs) {
     free(c->lbs);
   }
@@ -164,7 +330,7 @@
=20
=20
 static int GetUDFCache(dvd_reader_t *device, UDFCacheType type,
-		       uint32_t nr, void *data)
+                       uint32_t nr, void *data)
 {
   int n;
   struct udf_cache *c;
@@ -207,16 +373,16 @@
   case LBUDFCache:
     for(n =3D 0; n < c->lb_num; n++) {
       if(c->lbs[n].lb =3D=3D nr) {
-      *(uint8_t **)data =3D c->lbs[n].data;
-      return 1;
+        *(uint8_t **)data =3D c->lbs[n].data;
+        return 1;
       }
     }
     break;
   case MapCache:
     for(n =3D 0; n < c->map_num; n++) {
       if(c->maps[n].lbn =3D=3D nr) {
-       *(struct icbmap *)data =3D c->maps[n];
-       return 1;
+        *(struct icbmap *)data =3D c->maps[n];
+        return 1;
       }
     }
     break;
@@ -228,7 +394,7 @@
 }
=20
 static int SetUDFCache(dvd_reader_t *device, UDFCacheType type,
-		       uint32_t nr, void *data)
+                       uint32_t nr, void *data)
 {
   int n;
   struct udf_cache *c;
@@ -241,7 +407,7 @@
  =20
   if(c =3D=3D NULL) {
     c =3D calloc(1, sizeof(struct udf_cache));   =20
-    //    LOG_ERROR( stderr, "calloc: %d\n", sizeof(struct udf_cache)); =
  =20
+    //    fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache));   =20
     if(c =3D=3D NULL) {
       return 0;
     }
@@ -269,18 +435,18 @@
   case LBUDFCache:
     for(n =3D 0; n < c->lb_num; n++) {
       if(c->lbs[n].lb =3D=3D nr) {
-       /* replace with new data */
-       c->lbs[n].data =3D *(uint8_t **)data;
-       c->lbs[n].lb =3D nr;
-       return 1;
+        /* replace with new data */
+        c->lbs[n].data =3D *(uint8_t **)data;
+        c->lbs[n].lb =3D nr;
+        return 1;
       }
     }
     c->lb_num++;
     c->lbs =3D realloc(c->lbs, c->lb_num * sizeof(struct lbudf));
     /*
-    LOG_ERROR( stderr, "realloc lb: %d * %d =3D %d\n",
-	    c->lb_num, sizeof(struct lbudf),
-	    c->lb_num * sizeof(struct lbudf));
+      fprintf(stderr, "realloc lb: %d * %d =3D %d\n",
+      c->lb_num, sizeof(struct lbudf),
+      c->lb_num * sizeof(struct lbudf));
     */
     if(c->lbs =3D=3D NULL) {
       c->lb_num =3D 0;
@@ -292,18 +458,18 @@
   case MapCache:
     for(n =3D 0; n < c->map_num; n++) {
       if(c->maps[n].lbn =3D=3D nr) {
-       /* replace with new data */
-       c->maps[n] =3D *(struct icbmap *)data;
-       c->maps[n].lbn =3D nr;
-       return 1;
+        /* replace with new data */
+        c->maps[n] =3D *(struct icbmap *)data;
+        c->maps[n].lbn =3D nr;
+        return 1;
       }
     }
     c->map_num++;
     c->maps =3D realloc(c->maps, c->map_num * sizeof(struct icbmap));
     /*
-    LOG_ERROR( stderr, "realloc maps: %d * %d =3D %d\n",
-	    c->map_num, sizeof(struct icbmap),
-	    c->map_num * sizeof(struct icbmap));
+      fprintf(stderr, "realloc maps: %d * %d =3D %d\n",
+      c->map_num, sizeof(struct icbmap),
+      c->map_num * sizeof(struct icbmap));
     */
     if(c->maps =3D=3D NULL) {
       c->map_num =3D 0;
@@ -323,94 +489,94 @@
 /* For direct data access, LSB first */
 #define GETN1(p) ((uint8_t)data[p])
 #define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8))
-#define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \
-		  | ((uint32_t)data[(p) + 2] << 16))
-#define GETN4(p) ((uint32_t)data[p] \
-		  | ((uint32_t)data[(p) + 1] << 8) \
-		  | ((uint32_t)data[(p) + 2] << 16) \
-		  | ((uint32_t)data[(p) + 3] << 24))
+#define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8)    =
\
+                  | ((uint32_t)data[(p) + 2] << 16))
+#define GETN4(p) ((uint32_t)data[p]                     \
+                  | ((uint32_t)data[(p) + 1] << 8)      \
+                  | ((uint32_t)data[(p) + 2] << 16)     \
+                  | ((uint32_t)data[(p) + 3] << 24))
 /* This is wrong with regard to endianess */
 #define GETN(p, n, target) memcpy(target, &data[p], n)
=20
 static int Unicodedecode( uint8_t *data, int len, char *target )=20
 {
-    int p =3D 1, i =3D 0;
+  int p =3D 1, i =3D 0;
=20
-    if( ( data[ 0 ] =3D=3D 8 ) || ( data[ 0 ] =3D=3D 16 ) ) do {
-        if( data[ 0 ] =3D=3D 16 ) p++;  /* Ignore MSB of unicode16 */
-        if( p < len ) {
-            target[ i++ ] =3D data[ p++ ];
-        }
-    } while( p < len );
+  if( ( data[ 0 ] =3D=3D 8 ) || ( data[ 0 ] =3D=3D 16 ) ) do {
+    if( data[ 0 ] =3D=3D 16 ) p++;  /* Ignore MSB of unicode16 */
+    if( p < len ) {
+      target[ i++ ] =3D data[ p++ ];
+    }
+  } while( p < len );
=20
-    target[ i ] =3D '\0';
-    return 0;
+  target[ i ] =3D '\0';
+  return 0;
 }
=20
 static int UDFDescriptor( uint8_t *data, uint16_t *TagID )=20
 {
-    *TagID =3D GETN2(0);
-    // TODO: check CRC 'n stuff
-    return 0;
+  *TagID =3D GETN2(0);
+  // TODO: check CRC 'n stuff
+  return 0;
 }
=20
 static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Locat=
ion )=20
 {
-    *Length   =3D GETN4(0);
-    *Location =3D GETN4(4);
-    return 0;
+  *Length   =3D GETN4(0);
+  *Location =3D GETN4(4);
+  return 0;
 }
=20
 static int UDFShortAD( uint8_t *data, struct AD *ad,=20
-		       struct Partition *partition )=20
+                       struct Partition *partition )=20
 {
-    ad->Length =3D GETN4(0);
-    ad->Flags =3D ad->Length >> 30;
-    ad->Length &=3D 0x3FFFFFFF;
-    ad->Location =3D GETN4(4);
-    ad->Partition =3D partition->Number; // use number of current partit=
ion
-    return 0;
+  ad->Length =3D GETN4(0);
+  ad->Flags =3D ad->Length >> 30;
+  ad->Length &=3D 0x3FFFFFFF;
+  ad->Location =3D GETN4(4);
+  ad->Partition =3D partition->Number; // use number of current partitio=
n
+  return 0;
 }
=20
 static int UDFLongAD( uint8_t *data, struct AD *ad )
 {
-    ad->Length =3D GETN4(0);
-    ad->Flags =3D ad->Length >> 30;
-    ad->Length &=3D 0x3FFFFFFF;
-    ad->Location =3D GETN4(4);
-    ad->Partition =3D GETN2(8);
-    //GETN(10, 6, Use);
-    return 0;
+  ad->Length =3D GETN4(0);
+  ad->Flags =3D ad->Length >> 30;
+  ad->Length &=3D 0x3FFFFFFF;
+  ad->Location =3D GETN4(4);
+  ad->Partition =3D GETN2(8);
+  //GETN(10, 6, Use);
+  return 0;
 }
=20
 static int UDFExtAD( uint8_t *data, struct AD *ad )
 {
-    ad->Length =3D GETN4(0);
-    ad->Flags =3D ad->Length >> 30;
-    ad->Length &=3D 0x3FFFFFFF;
-    ad->Location =3D GETN4(12);
-    ad->Partition =3D GETN2(16);
-    //GETN(10, 6, Use);
-    return 0;
+  ad->Length =3D GETN4(0);
+  ad->Flags =3D ad->Length >> 30;
+  ad->Length &=3D 0x3FFFFFFF;
+  ad->Location =3D GETN4(12);
+  ad->Partition =3D GETN2(16);
+  //GETN(10, 6, Use);
+  return 0;
 }
=20
 static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags )
 {
-    *FileType =3D GETN1(11);
-    *Flags =3D GETN2(18);
-    return 0;
+  *FileType =3D GETN1(11);
+  *Flags =3D GETN2(18);
+  return 0;
 }
=20
=20
 static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Numbe=
r,
-			 char *Contents, uint32_t *Start, uint32_t *Length )
+                         char *Contents, uint32_t *Start, uint32_t *Leng=
th )
 {
-    *Flags =3D GETN2(20);
-    *Number =3D GETN2(22);
-    GETN(24, 32, Contents);
-    *Start =3D GETN4(188);
-    *Length =3D GETN4(192);
-    return 0;
+  *Flags =3D GETN2(20);
+  *Number =3D GETN2(22);
+  GETN(24, 32, Contents);
+  *Start =3D GETN4(188);
+  *Length =3D GETN4(192);
+  return 0;
 }
=20
 /**
@@ -419,66 +585,66 @@
  */
 static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor )
 {
-    uint32_t lbsize, MT_L, N_PM;
-    Unicodedecode(&data[84], 128, VolumeDescriptor);
-    lbsize =3D GETN4(212);  // should be 2048
-    MT_L =3D GETN4(264);    // should be 6
-    N_PM =3D GETN4(268);    // should be 1
-    if (lbsize !=3D DVD_VIDEO_LB_LEN) return 1;
-    return 0;
+  uint32_t lbsize, MT_L, N_PM;
+  Unicodedecode(&data[84], 128, VolumeDescriptor);
+  lbsize =3D GETN4(212);  // should be 2048
+  MT_L =3D GETN4(264);    // should be 6
+  N_PM =3D GETN4(268);    // should be 1
+  if (lbsize !=3D DVD_VIDEO_LB_LEN) return 1;
+  return 0;
 }
=20
 static int UDFFileEntry( uint8_t *data, uint8_t *FileType,=20
-			 struct Partition *partition, struct AD *ad )
+                         struct Partition *partition, struct AD *ad )
 {
-    uint16_t flags;
-    uint32_t L_EA, L_AD;
-    unsigned int p;
+  uint16_t flags;
+  uint32_t L_EA, L_AD;
+  unsigned int p;
=20
-    UDFICB( &data[ 16 ], FileType, &flags );
+  UDFICB( &data[ 16 ], FileType, &flags );
   =20
-    /* Init ad for an empty file (i.e. there isn't a AD, L_AD =3D=3D 0 )=
 */
-    ad->Length =3D GETN4( 60 ); // Really 8 bytes a 56
-    ad->Flags =3D 0;
-    ad->Location =3D 0; // what should we put here?=20
-    ad->Partition =3D partition->Number; // use number of current partit=
ion
+  /* Init ad for an empty file (i.e. there isn't a AD, L_AD =3D=3D 0 ) *=
/
+  ad->Length =3D GETN4( 60 ); // Really 8 bytes a 56
+  ad->Flags =3D 0;
+  ad->Location =3D 0; // what should we put here?=20
+  ad->Partition =3D partition->Number; // use number of current partitio=
n
=20
-    L_EA =3D GETN4( 168 );
-    L_AD =3D GETN4( 172 );
-    p =3D 176 + L_EA;
-    while( p < 176 + L_EA + L_AD ) {
-        switch( flags & 0x0007 ) {
-            case 0: UDFShortAD( &data[ p ], ad, partition ); p +=3D 8;  =
break;
-            case 1: UDFLongAD( &data[ p ], ad );  p +=3D 16; break;
-            case 2: UDFExtAD( &data[ p ], ad );   p +=3D 20; break;
-            case 3:
-                switch( L_AD ) {
-                    case 8:  UDFShortAD( &data[ p ], ad, partition ); br=
eak;
-                    case 16: UDFLongAD( &data[ p ], ad );  break;
-                    case 20: UDFExtAD( &data[ p ], ad );   break;
-                }
-                p +=3D L_AD;
-                break;
-            default:
-                p +=3D L_AD; break;
-        }
+  L_EA =3D GETN4( 168 );
+  L_AD =3D GETN4( 172 );
+  p =3D 176 + L_EA;
+  while( p < 176 + L_EA + L_AD ) {
+    switch( flags & 0x0007 ) {
+    case 0: UDFShortAD( &data[ p ], ad, partition ); p +=3D 8;  break;
+    case 1: UDFLongAD( &data[ p ], ad );  p +=3D 16; break;
+    case 2: UDFExtAD( &data[ p ], ad );   p +=3D 20; break;
+    case 3:
+      switch( L_AD ) {
+      case 8:  UDFShortAD( &data[ p ], ad, partition ); break;
+      case 16: UDFLongAD( &data[ p ], ad );  break;
+      case 20: UDFExtAD( &data[ p ], ad );   break;
+      }
+      p +=3D L_AD;
+      break;
+    default:
+      p +=3D L_AD; break;
     }
-    return 0;
+  }
+  return 0;
 }
=20
 static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristic=
s,
-			      char *FileName, struct AD *FileICB )
+                              char *FileName, struct AD *FileICB )
 {
-    uint8_t L_FI;
-    uint16_t L_IU;
+  uint8_t L_FI;
+  uint16_t L_IU;
=20
-    *FileCharacteristics =3D GETN1(18);
-    L_FI =3D GETN1(19);
-    UDFLongAD(&data[20], FileICB);
-    L_IU =3D GETN2(36);
-    if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName);
-    else FileName[0] =3D '\0';
-    return 4 * ((38 + L_FI + L_IU + 3) / 4);
+  *FileCharacteristics =3D GETN1(18);
+  L_FI =3D GETN1(19);
+  UDFLongAD(&data[20], FileICB);
+  L_IU =3D GETN2(36);
+  if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName);
+  else FileName[0] =3D '\0';
+  return 4 * ((38 + L_FI + L_IU + 3) / 4);
 }
=20
 /**
@@ -489,39 +655,46 @@
  * return 1 on success, 0 on error;
  */
 static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *File=
Type,
-		      struct Partition *partition, struct AD *File )=20
+                      struct Partition *partition, struct AD *File )=20
 {
-    uint8_t LogBlock[DVD_VIDEO_LB_LEN];
-    uint32_t lbnum;
-    uint16_t TagID;
-    struct icbmap tmpmap;
+  uint8_t *LogBlock;
+  uint32_t lbnum;
+  uint16_t TagID;
+  struct icbmap tmpmap;
=20
-    lbnum =3D partition->Start + ICB.Location;
-    tmpmap.lbn =3D lbnum;
-    if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) {
-      *FileType =3D tmpmap.filetype;
-      *File =3D tmpmap.file;
-      return 1;
+  lbnum =3D partition->Start + ICB.Location;
+  tmpmap.lbn =3D lbnum;
+  if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) {
+    *FileType =3D tmpmap.filetype;
+    *File =3D tmpmap.file;
+    return 1;
+  }
+
+  LogBlock =3D dvdalign_lbmalloc(device, 1);
+  if(!LogBlock) {
+    return 0;
+  }
+   =20
+  do {
+    if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <=3D 0 ) {
+      TagID =3D 0;
+    } else {
+      UDFDescriptor( LogBlock, &TagID );
     }
=20
-    do {
-        if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <=3D 0 ) {
-            TagID =3D 0;
-        } else {
-            UDFDescriptor( LogBlock, &TagID );
-        }
-
-        if( TagID =3D=3D 261 ) {
-            UDFFileEntry( LogBlock, FileType, partition, File );
-           tmpmap.file =3D *File;
-           tmpmap.filetype =3D *FileType;
-           SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap);
-            return 1;
-        };
-    } while( ( lbnum <=3D partition->Start + ICB.Location + ( ICB.Length=
 - 1 )
+    if( TagID =3D=3D 261 ) {
+      UDFFileEntry( LogBlock, FileType, partition, File );
+      tmpmap.file =3D *File;
+      tmpmap.filetype =3D *FileType;
+      SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap);
+      dvdalign_lbfree(device, LogBlock);
+      return 1;
+    };
+  } while( ( lbnum <=3D partition->Start + ICB.Location + ( ICB.Length -=
 1 )
              / DVD_VIDEO_LB_LEN ) && ( TagID !=3D 261 ) );
=20
-    return 0;
+  dvdalign_lbfree(device, LogBlock);
+  return 0;
 }
=20
 /**
@@ -532,121 +705,124 @@
  */
 static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileNa=
me,
                        struct Partition *partition, struct AD *FileICB,
-		       int cache_file_info)=20
+                       int cache_file_info)=20
 {
-    char filename[ MAX_UDF_FILE_NAME_LEN ];
-    uint8_t directory[ 2 * DVD_VIDEO_LB_LEN ];
-    uint32_t lbnum;
-    uint16_t TagID;
-    uint8_t filechar;
-    unsigned int p;
-    uint8_t *cached_dir =3D NULL;
-    uint32_t dir_lba;
-    struct AD tmpICB;
-    int found =3D 0;
-    int in_cache =3D 0;
+  char filename[ MAX_UDF_FILE_NAME_LEN ];
+  uint8_t *directory;
+  uint32_t lbnum;
+  uint16_t TagID;
+  uint8_t filechar;
+  unsigned int p;
+  uint8_t *cached_dir =3D NULL;
+  uint32_t dir_lba;
+  struct AD tmpICB;
+  int found =3D 0;
+  int in_cache =3D 0;
=20
-    /* Scan dir for ICB of file */
-    lbnum =3D partition->Start + Dir.Location;
+  /* Scan dir for ICB of file */
+  lbnum =3D partition->Start + Dir.Location;
    =20
-    if(DVDUDFCacheLevel(device, -1) > 0) {
-      /* caching */
+  if(DVDUDFCacheLevel(device, -1) > 0) {
+    /* caching */
      =20
-      if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
-	dir_lba =3D (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
-	if((cached_dir =3D malloc(dir_lba * DVD_VIDEO_LB_LEN)) =3D=3D NULL) {
-	  return 0;
-	}
-	if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <=3D 0 ) {
-	  free(cached_dir);
-	  cached_dir =3D NULL;
-	}
-	/*
-	if(cached_dir) {
-	  LOG_ERROR( stderr, "malloc dir: %d\n",
-		  dir_lba * DVD_VIDEO_LB_LEN);
-	}
-	*/
-	SetUDFCache(device, LBUDFCache, lbnum, &cached_dir);
-      } else {
-	in_cache =3D 1;
+    if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) {
+      dir_lba =3D (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN;
+      if((cached_dir =3D dvdalign_lbmalloc(device, dir_lba)) =3D=3D NULL=
) {
+        return 0;
       }
-     =20
-      if(cached_dir =3D=3D NULL) {
-	return 0;
+      if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <=3D 0 ) =
{
+        dvdalign_lbfree(device, cached_dir);
+        cached_dir =3D NULL;
       }
+      SetUDFCache(device, LBUDFCache, lbnum, &cached_dir);
+    } else {
+      in_cache =3D 1;
+    }
      =20
-      p =3D 0;
+    if(cached_dir =3D=3D NULL) {
+      return 0;
+    }
      =20
-      while( p < Dir.Length ) {
-        UDFDescriptor( &cached_dir[ p ], &TagID );
-        if( TagID =3D=3D 257 ) {
-	  p +=3D UDFFileIdentifier( &cached_dir[ p ], &filechar,
-				  filename, &tmpICB );
-	  if(cache_file_info && !in_cache) {
-	    uint8_t tmpFiletype;
-	    struct AD tmpFile;
-	   =20
-	    if( !strcasecmp( FileName, filename ) ) {
-	      *FileICB =3D tmpICB;
-	      found =3D 1;
-	     =20
-	    }
-	    UDFMapICB(device, tmpICB, &tmpFiletype,
-		      partition, &tmpFile);
-	  } else {
-	    if( !strcasecmp( FileName, filename ) ) {
-	      *FileICB =3D tmpICB;
-	      return 1;
-	    }
-	  }
+    p =3D 0;
+     =20
+    while( p < Dir.Length ) {
+      UDFDescriptor( &cached_dir[ p ], &TagID );
+      if( TagID =3D=3D 257 ) {
+        p +=3D UDFFileIdentifier( &cached_dir[ p ], &filechar,
+                                filename, &tmpICB );
+        if(cache_file_info && !in_cache) {
+          uint8_t tmpFiletype;
+          struct AD tmpFile;
+           =20
+          if( !strcasecmp( FileName, filename ) ) {
+            *FileICB =3D tmpICB;
+            found =3D 1;
+             =20
+          }
+          UDFMapICB(device, tmpICB, &tmpFiletype,
+                    partition, &tmpFile);
         } else {
-	  if(cache_file_info && (!in_cache) && found) {
-	    return 1;
-	  }
-	  return 0;
+          if( !strcasecmp( FileName, filename ) ) {
+            *FileICB =3D tmpICB;
+            return 1;
+          }
         }
+      } else {
+        if(cache_file_info && (!in_cache) && found) {
+          return 1;
+        }
+        return 0;
       }
-      if(cache_file_info && (!in_cache) && found) {
-	return 1;
-      }
-      return 0;
     }
+    if(cache_file_info && (!in_cache) && found) {
+      return 1;
+    }
+    return 0;
+  }
=20
-    if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <=3D 0 ) {
+  directory =3D dvdalign_lbmalloc(device, 2);
+  if(!directory) {
+    return 0;
+  }
+  if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <=3D 0 ) {
+    dvdalign_lbfree(device, directory);
+    return 0;
+  }
+
+  p =3D 0;
+  while( p < Dir.Length ) {
+    if( p > DVD_VIDEO_LB_LEN ) {
+      ++lbnum;
+      p -=3D DVD_VIDEO_LB_LEN;
+      Dir.Length -=3D DVD_VIDEO_LB_LEN;
+      if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <=3D 0 ) {
+        dvdalign_lbfree(device, directory);
         return 0;
+      }
     }
-
-    p =3D 0;
-    while( p < Dir.Length ) {
-        if( p > DVD_VIDEO_LB_LEN ) {
-            ++lbnum;
-            p -=3D DVD_VIDEO_LB_LEN;
-            Dir.Length -=3D DVD_VIDEO_LB_LEN;
-            if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <=3D 0 ) =
{
-                return 0;
-            }
-        }
-        UDFDescriptor( &directory[ p ], &TagID );
-        if( TagID =3D=3D 257 ) {
-            p +=3D UDFFileIdentifier( &directory[ p ], &filechar,
-                                    filename, FileICB );
-            if( !strcasecmp( FileName, filename ) ) {
-                return 1;
-            }
-        } else {
-            return 0;
-        }
+    UDFDescriptor( &directory[ p ], &TagID );
+    if( TagID =3D=3D 257 ) {
+      p +=3D UDFFileIdentifier( &directory[ p ], &filechar,
+                              filename, FileICB );
+      if( !strcasecmp( FileName, filename ) ) {
+        dvdalign_lbfree(device, directory);
+        return 1;
+      }
+    } else {
+      dvdalign_lbfree(device, directory);
+      return 0;
     }
+  }
=20
-    return 0;
+  dvdalign_lbfree(device, directory);
+  return 0;
 }
=20
=20
 static int UDFGetAVDP( dvd_reader_t *device,
-		       struct avdp_t *avdp)
+                       struct avdp_t *avdp)
 {
-  uint8_t Anchor[ DVD_VIDEO_LB_LEN ];
+  uint8_t *Anchor;
   uint32_t lbnum, MVDS_location, MVDS_length;
   uint16_t TagID;
   uint32_t lastsector;
@@ -656,12 +832,16 @@
   if(GetUDFCache(device, AVDPCache, 0, avdp)) {
     return 1;
   }
-
+ =20
   /* Find Anchor */
   lastsector =3D 0;
   lbnum =3D 256;   /* Try #1, prime anchor */
   terminate =3D 0;
  =20
+  Anchor =3D dvdalign_lbmalloc(device, 1);
+  if(!Anchor) {
+    return 0;
+  }
   for(;;) {
     if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) {
       UDFDescriptor( Anchor, &TagID );
@@ -670,24 +850,29 @@
     }
     if (TagID !=3D 2) {
       /* Not an anchor */
-      if( terminate ) return 0; /* Final try failed */
+      if( terminate ) {
+        dvdalign_lbfree(device, Anchor);
+        errno =3D EMEDIUMTYPE;
+        return 0; /* Final try failed */
+      }=20
      =20
       if( lastsector ) {
-=09
-	/* We already found the last sector.  Try #3, alternative
-	 * backup anchor.  If that fails, don't try again.
-	 */
-	lbnum =3D lastsector;
-	terminate =3D 1;
+        /* We already found the last sector.  Try #3, alternative
+         * backup anchor.  If that fails, don't try again.
+         */
+        lbnum =3D lastsector;
+        terminate =3D 1;
       } else {
-	/* TODO: Find last sector of the disc (this is optional). */
-	if( lastsector ) {
-	  /* Try #2, backup anchor */
-	  lbnum =3D lastsector - 256;
-	} else {
-	  /* Unable to find last sector */
-	  return 0;
-	}
+        /* TODO: Find last sector of the disc (this is optional). */
+        if( lastsector ) {
+          /* Try #2, backup anchor */
+          lbnum =3D lastsector - 256;
+        } else {
+          /* Unable to find last sector */
+          dvdalign_lbfree(device, Anchor);
+          errno =3D EMEDIUMTYPE;
+          return 0;
+        }
       }
     } else {
       /* It's an anchor! We can leave */
@@ -706,6 +891,7 @@
  =20
   SetUDFCache(device, AVDPCache, 0, avdp);
  =20
+  dvdalign_lbfree(device, Anchor);
   return 1;
 }
=20
@@ -715,146 +901,173 @@
  *   part: structure to fill with the partition information
  */
 static int UDFFindPartition( dvd_reader_t *device, int partnum,
-			     struct Partition *part )=20
+                             struct Partition *part )=20
 {
-    uint8_t LogBlock[ DVD_VIDEO_LB_LEN ];
-    uint32_t lbnum, MVDS_location, MVDS_length;
-    uint16_t TagID;
-    int i, volvalid;
-    struct avdp_t avdp;
+  uint8_t *LogBlock;
+  uint32_t lbnum, MVDS_location, MVDS_length;
+  uint16_t TagID;
+  int i, volvalid;
+  struct avdp_t avdp;
=20
    =20
-    if(!UDFGetAVDP(device, &avdp)) {
-      return 0;
-    }
+  if(!UDFGetAVDP(device, &avdp)) {
+    return 0;
+  }
=20
-    /* Main volume descriptor */
-    MVDS_location =3D avdp.mvds.location;
-    MVDS_length =3D avdp.mvds.length;
+  LogBlock =3D dvdalign_lbmalloc(device, 1);
+  if(!LogBlock) {
+    return 0;
+  }
+  /* Main volume descriptor */
+  MVDS_location =3D avdp.mvds.location;
+  MVDS_length =3D avdp.mvds.length;
=20
-    part->valid =3D 0;
-    volvalid =3D 0;
-    part->VolumeDesc[ 0 ] =3D '\0';
-    i =3D 1;
+  part->valid =3D 0;
+  volvalid =3D 0;
+  part->VolumeDesc[ 0 ] =3D '\0';
+  i =3D 1;
+  do {
+    /* Find Volume Descriptor */
+    lbnum =3D MVDS_location;
     do {
-        /* Find Volume Descriptor */
-        lbnum =3D MVDS_location;
-        do {
=20
-            if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <=3D 0 )=
 {
-                TagID =3D 0;
-            } else {
-                UDFDescriptor( LogBlock, &TagID );
-            }
+      if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <=3D 0 ) {
+        TagID =3D 0;
+      } else {
+        UDFDescriptor( LogBlock, &TagID );
+      }
=20
-            if( ( TagID =3D=3D 5 ) && ( !part->valid ) ) {
-                /* Partition Descriptor */
-                UDFPartition( LogBlock, &part->Flags, &part->Number,
-                              part->Contents, &part->Start, &part->Lengt=
h );
-                part->valid =3D ( partnum =3D=3D part->Number );
-            } else if( ( TagID =3D=3D 6 ) && ( !volvalid ) ) {
-                /* Logical Volume Descriptor */
-                if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { =20
-                    /* TODO: sector size wrong! */
-                } else {
-                    volvalid =3D 1;
-                }
-            }
+      if( ( TagID =3D=3D 5 ) && ( !part->valid ) ) {
+        /* Partition Descriptor */
+        UDFPartition( LogBlock, &part->Flags, &part->Number,
+                      part->Contents, &part->Start, &part->Length );
+        part->valid =3D ( partnum =3D=3D part->Number );
+      } else if( ( TagID =3D=3D 6 ) && ( !volvalid ) ) {
+        /* Logical Volume Descriptor */
+        if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { =20
+          /* TODO: sector size wrong! */
+        } else {
+          volvalid =3D 1;
+        }
+      }
=20
-        } while( ( lbnum <=3D MVDS_location + ( MVDS_length - 1 )
-                 / DVD_VIDEO_LB_LEN ) && ( TagID !=3D 8 )
-                 && ( ( !part->valid ) || ( !volvalid ) ) );
+    } while( ( lbnum <=3D MVDS_location + ( MVDS_length - 1 )
+               / DVD_VIDEO_LB_LEN ) && ( TagID !=3D 8 )
+             && ( ( !part->valid ) || ( !volvalid ) ) );
=20
-        if( ( !part->valid) || ( !volvalid ) ) {
-	  /* Backup volume descriptor */
-	  MVDS_location =3D avdp.mvds.location;
-	  MVDS_length =3D avdp.mvds.length;
-        }
-    } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );
+    if( ( !part->valid) || ( !volvalid ) ) {
+      /* Backup volume descriptor */
+      MVDS_location =3D avdp.mvds.location;
+      MVDS_length =3D avdp.mvds.length;
+    }
+  } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) );
=20
-    /* We only care for the partition, not the volume */
-    return part->valid;
+  dvdalign_lbfree(device, LogBlock);
+  /* We only care for the partition, not the volume */
+  return part->valid;
 }
=20
 uint32_t UDFFindFile( dvd_reader_t *device, char *filename,
-		      uint32_t *filesize )
+                      uint32_t *filesize )
 {
-    uint8_t LogBlock[ DVD_VIDEO_LB_LEN ];
-    uint32_t lbnum;
-    uint16_t TagID;
-    struct Partition partition;
-    struct AD RootICB, File, ICB;
-    char tokenline[ MAX_UDF_FILE_NAME_LEN ];
-    char *token;
-    uint8_t filetype;
-
+  uint8_t *LogBlock;
+  uint32_t lbnum;
+  uint16_t TagID;
+  struct Partition partition;
+  struct AD RootICB, File, ICB;
+  char tokenline[ MAX_UDF_FILE_NAME_LEN ];
+  char *token;
+  uint8_t filetype;
+ =20
+  if(filesize) {
     *filesize =3D 0;
-    tokenline[0] =3D '\0';
-    strcat( tokenline, filename );
+  }
+  tokenline[0] =3D '\0';
+  strcat( tokenline, filename );
=20
    =20
-    if(!(GetUDFCache(device, PartitionCache, 0, &partition) &&
-        GetUDFCache(device, RootICBCache, 0, &RootICB))) {
-      /* Find partition, 0 is the standard location for DVD Video.*/
-      if( !UDFFindPartition( device, 0, &partition ) ) return 0;
-      SetUDFCache(device, PartitionCache, 0, &partition);
-     =20
-      /* Find root dir ICB */
-      lbnum =3D partition.Start;
-      do {
-        if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <=3D 0 ) {
-            TagID =3D 0;
-        } else {
-            UDFDescriptor( LogBlock, &TagID );
-        }
+  if(!(GetUDFCache(device, PartitionCache, 0, &partition) &&
+       GetUDFCache(device, RootICBCache, 0, &RootICB))) {
+    /* Find partition, 0 is the standard location for DVD Video.*/
+    if( !UDFFindPartition( device, 0, &partition ) ) {
+      return 0;
+    }
+    SetUDFCache(device, PartitionCache, 0, &partition);
+   =20
+    LogBlock =3D dvdalign_lbmalloc(device, 1);
+    if(!LogBlock) {
+      return 0;
+    }
+    /* Find root dir ICB */
+    lbnum =3D partition.Start;
+    do {
+      if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <=3D 0 ) {
+        TagID =3D 0;
+      } else {
+        UDFDescriptor( LogBlock, &TagID );
+      }
=20
-        /* File Set Descriptor */
-        if( TagID =3D=3D 256 ) {  // File Set Descriptor
-            UDFLongAD( &LogBlock[ 400 ], &RootICB );
-        }
+      /* File Set Descriptor */
+      if( TagID =3D=3D 256 ) {  // File Set Descriptor
+        UDFLongAD( &LogBlock[ 400 ], &RootICB );
+      }
     } while( ( lbnum < partition.Start + partition.Length )
              && ( TagID !=3D 8 ) && ( TagID !=3D 256 ) );
=20
+    dvdalign_lbfree(device, LogBlock);
+     =20
     /* Sanity checks. */
-    if( TagID !=3D 256 ) return 0;
-    if( RootICB.Partition !=3D 0 ) return 0;
+    if( TagID !=3D 256 ) {
+      return 0;
+    }
+    if( RootICB.Partition !=3D 0 ) {
+      return 0;
+    }
     SetUDFCache(device, RootICBCache, 0, &RootICB);
-    }
+  }
=20
-    /* Find root dir */
-    if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) re=
turn 0;
-    if( filetype !=3D 4 ) return 0;  /* Root dir should be dir */
-
-    {
-      int cache_file_info =3D 0;
-      /* Tokenize filepath */
-      token =3D strtok(tokenline, "/");
+  /* Find root dir */
+  if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) {
+    return 0;
+  }
+  if( filetype !=3D 4 ) {
+    return 0;  /* Root dir should be dir */
+  }
+  {
+    int cache_file_info =3D 0;
+    /* Tokenize filepath */
+    token =3D strtok(tokenline, "/");
+   =20
+    while( token !=3D NULL ) {
      =20
-      while( token !=3D NULL ) {
-      =20
-        if( !UDFScanDir( device, File, token, &partition, &ICB,
-                        cache_file_info)) {
-         return 0;
-       }
-        if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) {
-         return 0;
-       }
-       if(!strcmp(token, "VIDEO_TS")) {
-         cache_file_info =3D 1;
-       }
-        token =3D strtok( NULL, "/" );
+      if( !UDFScanDir( device, File, token, &partition, &ICB,
+                       cache_file_info)) {
+        return 0;
       }
-    }=20
+      if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) {
+        return 0;
+      }
+      if(!strcmp(token, "VIDEO_TS")) {
+        cache_file_info =3D 1;
+      }
+      token =3D strtok( NULL, "/" );
+    }
+  }=20
=20
-    /* Sanity check. */
-    if( File.Partition !=3D 0 ) return 0;
-  =20
+  /* Sanity check. */
+  if( File.Partition !=3D 0 ) {
+    return 0;
+  }
+
+  if(filesize) {
     *filesize =3D File.Length;
-    /* Hack to not return partition.Start for empty files. */
-    if( !File.Location )
-      return 0;
-    else
-      return partition.Start + File.Location;
+  }
+  /* Hack to not return partition.Start for empty files. */
+  if( !File.Location ) {
+    return 0;
+  } else {
+    return partition.Start + File.Location;
+  }
 }
=20
=20
@@ -863,10 +1076,11 @@
  * Gets a Descriptor .
  * Returns 1 if descriptor found, 0 on error.
  * id, tagid of descriptor
- * bufsize, size of BlockBuf (must be >=3D DVD_VIDEO_LB_LEN).
+ * bufsize, size of BlockBuf (must be >=3D DVD_VIDEO_LB_LEN)
+ * and aligned for raw/O_DIRECT read.
  */
 static int UDFGetDescriptor( dvd_reader_t *device, int id,
-			     uint8_t *descriptor, int bufsize)=20
+                             uint8_t *descriptor, int bufsize)=20
 {
   uint32_t lbnum, MVDS_location, MVDS_length;
   struct avdp_t avdp;
@@ -897,18 +1111,18 @@
     do {
      =20
       if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <=3D 0 ) {
-	TagID =3D 0;
+        TagID =3D 0;
       } else {
-	UDFDescriptor( descriptor, &TagID );
+        UDFDescriptor( descriptor, &TagID );
       }
      =20
       if( (TagID =3D=3D id) && ( !desc_found ) ) {
-	/* Descriptor */
-	desc_found =3D 1;
+        /* Descriptor */
+        desc_found =3D 1;
       }
     } while( ( lbnum <=3D MVDS_location + ( MVDS_length - 1 )
-	       / DVD_VIDEO_LB_LEN ) && ( TagID !=3D 8 )
-	     && ( !desc_found) );
+               / DVD_VIDEO_LB_LEN ) && ( TagID !=3D 8 )
+             && ( !desc_found) );
    =20
     if( !desc_found ) {
       /* Backup volume descriptor */
@@ -916,6 +1130,7 @@
       MVDS_length =3D avdp.rvds.length;
     }
   } while( i-- && ( !desc_found )  );
+
  =20
   return desc_found;
 }
@@ -923,20 +1138,27 @@
=20
 static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd)
 {
-  uint8_t pvd_buf[DVD_VIDEO_LB_LEN];
+  uint8_t *pvd_buf;
  =20
   if(GetUDFCache(device, PVDCache, 0, pvd)) {
     return 1;
   }
-
-  if(!UDFGetDescriptor( device, 1, pvd_buf, sizeof(pvd_buf))) {
+ =20
+  pvd_buf =3D dvdalign_lbmalloc(device, 1);
+  if(!pvd_buf) {
     return 0;
   }
+  if(!UDFGetDescriptor( device, 1, pvd_buf, 1*DVD_VIDEO_LB_LEN)) {
+    dvdalign_lbfree(device, pvd_buf);
+    return 0;
+  }
  =20
   memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32);
   memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128);
   SetUDFCache(device, PVDCache, 0, pvd);
  =20
+  dvdalign_lbfree(device, pvd_buf);
+
   return 1;
 }
=20
@@ -947,7 +1169,7 @@
  * returns the size of buffer needed for all data
  */
 int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid,
-			   unsigned int volid_size)
+                           unsigned int volid_size)
 {
   struct pvd_t pvd;
   unsigned int volid_len;
@@ -980,7 +1202,7 @@
  * or 0 on error
  */
 int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid,
-			      unsigned int volsetid_size)
+                              unsigned int volsetid_size)
 {
   struct pvd_t pvd;
=20

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.h	2007-01-22 11:21:1=
6 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvd_udf.h	2007-01-28 16:48:1=
1 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #ifndef DVD_UDF_H_INCLUDED
 #define DVD_UDF_H_INCLUDED
=20
@@ -31,7 +32,11 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
=20
+#if defined(HAVE_INTTYPES_H)
 #include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
=20
 #include "dvd_reader.h"
=20
@@ -45,14 +50,16 @@
  * absolute pathname on the UDF filesystem, starting with '/'.  For exam=
ple,
  * '/VIDEO_TS/VTS_01_1.IFO'.  On success, filesize will be set to the si=
ze of
  * the file in bytes.
+ * This implementation relies on that the file size is less than 2^32
+ * A DVD file can at most be 2^30 (-2048 ?).
  */
 uint32_t UDFFindFile( dvd_reader_t *device, char *filename, uint32_t *si=
ze );
-
-void FreeUDFCache(void *cache);
+ =20
+void FreeUDFCache(dvd_reader_t *device, void *cache);
 int UDFGetVolumeIdentifier(dvd_reader_t *device,
-			   char *volid, unsigned int volid_size);
+                           char *volid, unsigned int volid_size);
 int UDFGetVolumeSetIdentifier(dvd_reader_t *device,
-			      uint8_t *volsetid, unsigned int volsetid_size);
+                              uint8_t *volsetid, unsigned int volsetid_s=
ize);
 #ifdef __cplusplus
 };
 #endif

Added: trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread.proj	2007-01-22 11:2=
1:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread.proj	2007-01-28 16:4=
8:11 UTC (rev 1270)
@@ -0,0 +1,35 @@
+#include "*/*.proj"
+
+LIB dvdread
+{
+  USE(TARGET_WIN) c99msvc
+  USE(TARGET_WIN) posixmsvc
+  DEFINE STDC_HEADERS
+
+  SOURCE cmd_print.c
+  SOURCE dvd_input.c
+  SOURCE dvd_reader.c
+  SOURCE dvd_udf.c
+  SOURCE ifo_print.c
+  SOURCE ifo_read.c
+  SOURCE md5.c
+  SOURCE nav_print.c
+  SOURCE nav_read.c
+
+  HEADER bswap.h
+  HEADER cmd_print.h
+  HEADER dvd_input.h
+  HEADER dvd_reader.h
+  HEADER dvd_udf.h
+  HEADER dvdread_internal.h
+  HEADER ifo_print.h
+  HEADER ifo_read.h
+  HEADER ifo_types.h
+  HEADER md5.h
+  HEADER nav_print.h
+  HEADER nav_read.h
+  HEADER nav_types.h
+ =20
+  INCLUDE(TARGET_WIN) ../win32
+  INCLUDE ..
+}

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread_internal.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread_internal.h	2007-01-2=
2 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/dvdread_internal.h	2007-01-2=
8 16:48:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #ifndef DVDREAD_INTERNAL_H
 #define DVDREAD_INTERNAL_H
=20
@@ -2,9 +3,14 @@
=20
-#define CHECK_VALUE(arg) \
- if(!(arg)) { \
-   fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" \
-                   "\n*** for %s ***\n\n", \
-                   __FILE__, __LINE__, # arg ); \
- }
+#define CHECK_VALUE(arg)                                                =
\
+  if(!(arg)) {                                                          =
\
+    fprintf(stderr, "\n*** libdvdread: CHECK_VALUE failed in %s:%i ***" =
\
+            "\n*** for %s ***\n\n",                                     =
\
+            __FILE__, __LINE__, # arg );                                =
\
+  }
=20
+
+int get_verbose(void);
+int dvdread_verbose(dvd_reader_t *dvd);
+dvd_reader_t *device_of_file(dvd_file_t *file);
+
 #endif /* DVDREAD_INTERNAL_H */

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_print.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_print.c	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_print.c	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*=20
  * Copyright (C) 2000, 2001, 2002, 2003
  *               Bj=F6rn Englund <d4bjorn at dtek.chalmers.se>,=20
@@ -21,22 +22,25 @@
 #include "config.h"
=20
 #include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#include <stdlib.h>
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
 #endif
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#include <inttypes.h>
 #include <string.h>
 #include <ctype.h>
=20
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
 #include "ifo_types.h"
 #include "ifo_read.h"
 #include "ifo_print.h"
+#include "cmd_print.h"
 #include "dvdread_internal.h"
-
+
 /* Put this in some other file / package?  It's used in nav_print too. *=
/
 static void ifoPrint_time(dvd_time_t *dtime) {
   const char *rate;
@@ -46,10 +50,10 @@
   CHECK_VALUE((dtime->frame_u&0xf) < 0xa);
  =20
   printf("%02x:%02x:%02x.%02x",=20
-	 dtime->hour,
-	 dtime->minute,
-	 dtime->second,
-	 dtime->frame_u & 0x3f);
+         dtime->hour,
+         dtime->minute,
+         dtime->second,
+         dtime->frame_u & 0x3f);
   switch((dtime->frame_u & 0xc0) >> 6) {
   case 1:
     rate =3D "25.00";
@@ -68,20 +72,6 @@
   printf(" @ %s fps", rate);
 }
=20
-/* Put this in some other file / package?  It's used in nav_print too.
-   Possibly also by the vm / navigator. */
-static void ifoPrint_CMD(int row, vm_cmd_t *command) {
-  int i;
-
-  printf("(%03d) ", row + 1);
-  for(i=3D0;i<8;i++)
-    printf("%02x ", command->bytes[i]);
-  printf("| ");
-
-  //vmcmd(command);
-  printf("\n");
-}
-
 static void ifoPrint_video_attributes(video_attr_t *attr) {
  =20
   /* The following test is shorter but not correct ISO C,
@@ -164,14 +154,14 @@
   }
=20
   switch(attr->bit_rate) {
-    case 0:
-      printf("Variable Bit Rate ");
-      break;
-    case 1:
-      printf("Constant Bit Rate ");
-      break;
-    default:
-      printf("(please send a bug report)");
+  case 0:
+    printf("Variable Bit Rate ");
+    break;
+  case 1:
+    printf("Constant Bit Rate ");
+    break;
+  default:
+    printf("(please send a bug report)");
   }
  =20
   {
@@ -262,6 +252,9 @@
   case 1:
     printf("%c%c (%c) ", attr->lang_code>>8, attr->lang_code & 0xff,
            attr->lang_extension ? attr->lang_extension : ' ');
+    if(attr->lang_extension) {
+      printf("(please send a bug report) lang_extension !=3D 0");
+    }
     break;
   default:
     printf("(please send a bug report) ");
@@ -281,33 +274,65 @@
     printf("(please send a bug report) ");
   }
  =20
-  switch(attr->quantization) {
-  case 0:
-    printf("16bit ");
+  switch(attr->audio_format) {
+  case 0: //ac3
+    if(attr->quantization !=3D 3) {
+      printf("(please send a bug report) ac3 quant/drc not 3 (%d)",
+             attr->quantization);
+    }
     break;
-  case 1:
-    printf("20bit ");
+  case 2: //mpeg 1 or mpeg 2 without extension stream
+  case 3: //mpeg 2 with extension stream
+    switch(attr->quantization) {
+    case 0: //no drc
+      printf("no drc ");
+      break;
+    case 1:
+      printf("drc ");
+      break;
+    default:
+      printf("(please send a bug report) mpeg reserved quant/drc  (%d)",
+             attr->quantization);
+      break;
+    }
     break;
-  case 2:
-    printf("24bit ");
+  case 4:
+    switch(attr->quantization) {
+    case 0:
+      printf("16bit ");
+      break;
+    case 1:
+      printf("20bit ");
+      break;
+    case 2:
+      printf("24bit ");
+      break;
+    case 3:
+      printf("(please send a bug report) lpcm reserved quant/drc  (%d)",
+             attr->quantization);
+      break;
+    }
     break;
-  case 3:
-    printf("drc ");
+  case 6: //dts
+    if(attr->quantization !=3D 3) {
+      printf("(please send a bug report) dts quant/drc not 3 (%d)",
+             attr->quantization);
+    }
     break;
   default:
-    printf("(please send a bug report) ");
+    break;
   }
- =20
+
   switch(attr->sample_frequency) {
   case 0:
     printf("48kHz ");
     break;
   case 1:
-    printf("??kHz ");
+    printf("96kHz ");
     break;
   default:
     printf("sample_frequency %i (please send a bug report) ",=20
-	   attr->sample_frequency);
+           attr->sample_frequency);
   }
  =20
   printf("%dCh ", attr->channels + 1);
@@ -383,15 +408,14 @@
       printf("%02x%02x ", attr->lang_code >> 8, attr->lang_code & 0xff);
     }
   } else {
-      printf("lang not specified ");
+    printf("lang not specified ");
   }
  =20
   printf("%d ", attr->zero1);
   printf("%d ", attr->zero2);
-  printf("%d ", attr->code_extension);
+  printf("%d ", attr->lang_extension);
  =20
-  /* Is this correct?  should it not be subp_code_ext here instead? */
-  switch(attr->lang_extension) {
+  switch(attr->code_extension) {
   case 0:
     printf("Not specified ");
     break;
@@ -522,8 +546,8 @@
   printf("Last Sector of VMG: %08x\n", vmgi_mat->vmg_last_sector);
   printf("Last Sector of VMGI: %08x\n", vmgi_mat->vmgi_last_sector);
   printf("Specification version number: %01x.%01x\n",=20
-	 vmgi_mat->specification_version >> 4,=20
-	 vmgi_mat->specification_version & 0xf);
+         vmgi_mat->specification_version >> 4,=20
+         vmgi_mat->specification_version & 0xf);
   /* Byte 2 of 'VMG Category' (00xx0000) is the Region Code */
   printf("VMG Category: %08x\n", vmgi_mat->vmg_category);
   printf("VMG Number of Volumes: %i\n", vmgi_mat->vmg_nr_of_volumes);
@@ -535,7 +559,7 @@
   printf("%08x\n", (uint32_t)vmgi_mat->vmg_pos_code);
   printf("End byte of VMGI_MAT: %08x\n", vmgi_mat->vmgi_last_byte);
   printf("Start byte of First Play PGC FP PGC: %08x\n",=20
-	 vmgi_mat->first_play_pgc);
+         vmgi_mat->first_play_pgc);
   printf("Start sector of VMGM_VOBS: %08x\n", vmgi_mat->vmgm_vobs);
   printf("Start sector of TT_SRPT: %08x\n", vmgi_mat->tt_srpt);
   printf("Start sector of VMGM_PGCI_UT: %08x\n", vmgi_mat->vmgm_pgci_ut)=
;
@@ -544,19 +568,19 @@
   printf("Start sector of TXTDT_MG: %08x\n", vmgi_mat->txtdt_mgi);
   printf("Start sector of VMGM_C_ADT: %08x\n", vmgi_mat->vmgm_c_adt);
   printf("Start sector of VMGM_VOBU_ADMAP: %08x\n",=20
-	 vmgi_mat->vmgm_vobu_admap);
+         vmgi_mat->vmgm_vobu_admap);
   printf("Video attributes of VMGM_VOBS: ");
   ifoPrint_video_attributes(&vmgi_mat->vmgm_video_attr);
   printf("\n");
   printf("VMGM Number of Audio attributes: %i\n",=20
-	 vmgi_mat->nr_of_vmgm_audio_streams);
+         vmgi_mat->nr_of_vmgm_audio_streams);
   if(vmgi_mat->nr_of_vmgm_audio_streams > 0) {
     printf("\tstream %i status: ", 1);
     ifoPrint_audio_attributes(&vmgi_mat->vmgm_audio_attr);
     printf("\n");
   }
   printf("VMGM Number of Sub-picture attributes: %i\n",=20
-	 vmgi_mat->nr_of_vmgm_subp_streams);
+         vmgi_mat->nr_of_vmgm_subp_streams);
   if(vmgi_mat->nr_of_vmgm_subp_streams > 0) {
     printf("\tstream %2i status: ", 1);
     ifoPrint_subp_attributes(&vmgi_mat->vmgm_subp_attr);
@@ -572,8 +596,8 @@
   printf("Last Sector of VTS: %08x\n", vtsi_mat->vts_last_sector);
   printf("Last Sector of VTSI: %08x\n", vtsi_mat->vtsi_last_sector);
   printf("Specification version number: %01x.%01x\n",=20
-	 vtsi_mat->specification_version>>4,=20
-	 vtsi_mat->specification_version&0xf);
+         vtsi_mat->specification_version>>4,=20
+         vtsi_mat->specification_version&0xf);
   printf("VTS Category: %08x\n", vtsi_mat->vts_category);
   printf("End byte of VTSI_MAT: %08x\n", vtsi_mat->vtsi_last_byte);
   printf("Start sector of VTSM_VOBS:  %08x\n", vtsi_mat->vtsm_vobs);
@@ -592,7 +616,7 @@
   printf("\n");
  =20
   printf("VTSM Number of Audio attributes: %i\n",=20
-	 vtsi_mat->nr_of_vtsm_audio_streams);
+         vtsi_mat->nr_of_vtsm_audio_streams);
   if(vtsi_mat->nr_of_vtsm_audio_streams > 0) {
     printf("\tstream %i status: ", 1);
     ifoPrint_audio_attributes(&vtsi_mat->vtsm_audio_attr);
@@ -600,7 +624,7 @@
   }
  =20
   printf("VTSM Number of Sub-picture attributes: %i\n",=20
-	 vtsi_mat->nr_of_vtsm_subp_streams);
+         vtsi_mat->nr_of_vtsm_subp_streams);
   if(vtsi_mat->nr_of_vtsm_subp_streams > 0) {
     printf("\tstream %2i status: ", 1);
     ifoPrint_subp_attributes(&vtsi_mat->vtsm_subp_attr);
@@ -612,7 +636,7 @@
   printf("\n");
  =20
   printf("VTS Number of Audio attributes: %i\n",=20
-	 vtsi_mat->nr_of_vts_audio_streams);
+         vtsi_mat->nr_of_vts_audio_streams);
   for(i =3D 0; i < vtsi_mat->nr_of_vts_audio_streams; i++) {
     printf("\tstream %i status: ", i);
     ifoPrint_audio_attributes(&vtsi_mat->vts_audio_attr[i]);
@@ -620,7 +644,7 @@
   }
  =20
   printf("VTS Number of Subpicture attributes: %i\n",=20
-	 vtsi_mat->nr_of_vts_subp_streams);
+         vtsi_mat->nr_of_vts_subp_streams);
   for(i =3D 0; i < vtsi_mat->nr_of_vts_subp_streams; i++) {
     printf("\tstream %2i status: ", i);
     ifoPrint_subp_attributes(&vtsi_mat->vts_subp_attr[i]);
@@ -641,17 +665,17 @@
  =20
   printf("Number of Pre commands: %i\n", cmd_tbl->nr_of_pre);
   for(i =3D 0; i < cmd_tbl->nr_of_pre; i++) {
-    ifoPrint_CMD(i, &cmd_tbl->pre_cmds[i]);
+    cmdPrint_CMD(i, &cmd_tbl->pre_cmds[i]);
   }
=20
   printf("Number of Post commands: %i\n", cmd_tbl->nr_of_post);
   for(i =3D 0; i < cmd_tbl->nr_of_post; i++) {
-    ifoPrint_CMD(i, &cmd_tbl->post_cmds[i]);
+    cmdPrint_CMD(i, &cmd_tbl->post_cmds[i]);
   }
=20
   printf("Number of Cell commands: %i\n", cmd_tbl->nr_of_cell);
   for(i =3D 0; i < cmd_tbl->nr_of_cell; i++) {
-    ifoPrint_CMD(i, &cmd_tbl->cell_cmds[i]);
+    cmdPrint_CMD(i, &cmd_tbl->cell_cmds[i]);
   }
 }
=20
@@ -688,28 +712,28 @@
       const char *s;
       switch(cell_playback[i].block_mode) {
       case 0:
-	s =3D "not a"; break;
+        s =3D "not a"; break;
       case 1:
-	s =3D "the first"; break;
+        s =3D "the first"; break;
       case 2:
       default:
-	s =3D ""; break;
+        s =3D ""; break;
       case 3:
-	s =3D "last"; break;
+        s =3D "last"; break;
       }
       printf("%s cell in the block ", s);
      =20
       switch(cell_playback[i].block_type) {
       case 0:
-	printf("not part of the block ");
-	break;
+        printf("not part of the block ");
+        break;
       case 1:
-	printf("angle block ");
-	break;
+        printf("angle block ");
+        break;
       case 2:
       case 3:
-	printf("(send bug repport) ");
-	break;
+        printf("(send bug repport) ");
+        break;
       }
     }
     if(cell_playback[i].seamless_play)
@@ -729,11 +753,11 @@
       printf("cell command %d", cell_playback[i].cell_cmd_nr);
    =20
     printf("\n\tStart sector: %08x\tFirst ILVU end  sector: %08x\n",=20
-	   cell_playback[i].first_sector,=20
-	   cell_playback[i].first_ilvu_end_sector);
+           cell_playback[i].first_sector,=20
+           cell_playback[i].first_ilvu_end_sector);
     printf("\tEnd   sector: %08x\tLast VOBU start sector: %08x\n",=20
-	   cell_playback[i].last_sector,=20
-	   cell_playback[i].last_vobu_start_sector);
+           cell_playback[i].last_sector,=20
+           cell_playback[i].last_vobu_start_sector);
   }
 }
=20
@@ -747,7 +771,7 @@
  =20
   for(i=3D0;i<nr;i++) {
     printf("Cell: %3i has VOB ID: %3i, Cell ID: %3i\n", i + 1,=20
-	   cell_position[i].vob_id_nr, cell_position[i].cell_nr);
+           cell_position[i].vob_id_nr, cell_position[i].cell_nr);
   }
 }
=20
@@ -755,6 +779,11 @@
 void ifoPrint_PGC(pgc_t *pgc) {
   int i;
  =20
+  if(pgc =3D=3D NULL) {
+    printf("Error: No PGC present\n");
+    return;
+  }
+
   printf("Number of Programs: %i\n", pgc->nr_of_programs);
   printf("Number of Cells: %i\n", pgc->nr_of_cells);
   /* Check that time is 0:0:0:0 also if nr_of_programs=3D=3D0 */
@@ -765,17 +794,17 @@
   printf("Prohibited user operations: ");
   ifoPrint_USER_OPS(&pgc->prohibited_ops);
  =20
-    for(i =3D 0; i < 8; i++) {
-      if(pgc->audio_control[i] & 0x8000) { /* The 'is present' bit */
-	printf("Audio stream %i control: %04x\n",=20
-	       i, pgc->audio_control[i]);
-      }
+  for(i =3D 0; i < 8; i++) {
+    if(pgc->audio_control[i] & 0x8000) { /* The 'is present' bit */
+      printf("Audio stream %i control: %04x\n",=20
+             i, pgc->audio_control[i]);
     }
+  }
  =20
   for(i =3D 0; i < 32; i++) {
     if(pgc->subp_control[i] & 0x80000000) { /* The 'is present' bit */
       printf("Subpicture stream %2i control: %08x\n",=20
-	     i, pgc->subp_control[i]);
+             i, pgc->subp_control[i]);
     }
   }
  =20
@@ -810,36 +839,36 @@
   int i;
  =20
   printf("Number of TitleTrack search pointers: %i\n",
-	 tt_srpt->nr_of_srpts);
+         tt_srpt->nr_of_srpts);
   for(i=3D0;i<tt_srpt->nr_of_srpts;i++) {
     printf("Title Track index %i\n", i + 1);
     printf("\tTitle set number (VTS): %i",=20
-	   tt_srpt->title[i].title_set_nr);
+           tt_srpt->title[i].title_set_nr);
     printf("\tVTS_TTN: %i\n", tt_srpt->title[i].vts_ttn);
     printf("\tNumber of PTTs: %i\n", tt_srpt->title[i].nr_of_ptts);
     printf("\tNumber of angles: %i\n",=20
-	   tt_srpt->title[i].nr_of_angles);
+           tt_srpt->title[i].nr_of_angles);
     printf("\tTitle playback type: %s%s%s%s%s%s%s\n",
-	   tt_srpt->title[i].pb_ty.multi_or_random_pgc_title ?=20
-	   " One Random PGC Title or Multi PGC Title" :=20
-	   " One Sequential PGC Title",
-	   tt_srpt->title[i].pb_ty.jlc_exists_in_cell_cmd ?
-	   "" : ", No Link/Jump/Call exists in Cell command",
-	   tt_srpt->title[i].pb_ty.jlc_exists_in_prepost_cmd ?
-	   "" : ", No Link/Jump/Call exists in Pre- and/or Post-command",
-	   tt_srpt->title[i].pb_ty.jlc_exists_in_button_cmd ?
-	   "" : ", No Link/Jump/Call exists in Button command",
-	   tt_srpt->title[i].pb_ty.jlc_exists_in_tt_dom ?
-	   "" : ", No Link/Jump/Call exists in TT_DOM",
-	   tt_srpt->title[i].pb_ty.chapter_search_or_play ?
-	   ", UOP1 (TT_Play and PTT_Search) prohibited" : "",
-	   tt_srpt->title[i].pb_ty.title_or_time_play ?
-	   ", UOP0 (Time_Play and Time_Search) prohibited" : ""
-	   );   =20
+           tt_srpt->title[i].pb_ty.multi_or_random_pgc_title ?=20
+           " One Random PGC Title or Multi PGC Title" :=20
+           " One Sequential PGC Title",
+           tt_srpt->title[i].pb_ty.jlc_exists_in_cell_cmd ?
+           "" : ", No Link/Jump/Call exists in Cell command",
+           tt_srpt->title[i].pb_ty.jlc_exists_in_prepost_cmd ?
+           "" : ", No Link/Jump/Call exists in Pre- and/or Post-command"=
,
+           tt_srpt->title[i].pb_ty.jlc_exists_in_button_cmd ?
+           "" : ", No Link/Jump/Call exists in Button command",
+           tt_srpt->title[i].pb_ty.jlc_exists_in_tt_dom ?
+           "" : ", No Link/Jump/Call exists in TT_DOM",
+           tt_srpt->title[i].pb_ty.chapter_search_or_play ?
+           ", UOP1 (TT_Play and PTT_Search) prohibited" : "",
+           tt_srpt->title[i].pb_ty.title_or_time_play ?
+           ", UOP0 (Time_Play and Time_Search) prohibited" : ""
+           );   =20
     printf("\tParental ID field: %04x\n",
-	   tt_srpt->title[i].parental_id);
+           tt_srpt->title[i].parental_id);
     printf("\tTitle set starting sector %08x\n",=20
-	   tt_srpt->title[i].title_set_sector);
+           tt_srpt->title[i].title_set_sector);
   }
 }
=20
@@ -847,16 +876,16 @@
 void ifoPrint_VTS_PTT_SRPT(vts_ptt_srpt_t *vts_ptt_srpt) {
   int i, j;
   printf(" nr_of_srpts %i last byte %i\n",=20
-	 vts_ptt_srpt->nr_of_srpts,=20
-	 vts_ptt_srpt->last_byte);
+         vts_ptt_srpt->nr_of_srpts,=20
+         vts_ptt_srpt->last_byte);
   for(i=3D0;i<vts_ptt_srpt->nr_of_srpts;i++) {
     printf("\nVTS_PTT number %d has a offset %d relative to VTS_PTT_SRPT=
\n",=20
-				i + 1, vts_ptt_srpt->ttu_offset[i]);
+           i + 1, vts_ptt_srpt->ttu_offset[i]);
     for(j=3D0;j<vts_ptt_srpt->title[i].nr_of_ptts;j++) {
       printf("VTS_PTT_SRPT - Title %3i part %3i: PGC: %3i PG: %3i\n",
-	     i + 1, j + 1,=20
-	     vts_ptt_srpt->title[i].ptt[j].pgcn,
-	     vts_ptt_srpt->title[i].ptt[j].pgn );
+             i + 1, j + 1,=20
+             vts_ptt_srpt->title[i].ptt[j].pgcn,
+             vts_ptt_srpt->title[i].ptt[j].pgn );
     }
   }
 }
@@ -873,18 +902,18 @@
    =20
     printf("Start byte: %i\n", ptl_mait->countries[i].pf_ptl_mai_start_b=
yte);
     printf("Parental Masks for country: %c%c\n",
-	   ptl_mait->countries[i].country_code >> 8,
-	   ptl_mait->countries[i].country_code & 0xff);
+           ptl_mait->countries[i].country_code >> 8,
+           ptl_mait->countries[i].country_code & 0xff);
    =20
     for(vts =3D 0; vts <=3D ptl_mait->nr_of_vtss; vts++) {
       if( vts =3D=3D 0 ) {
-	printf("VMG    ");=20
+        printf("VMG    ");=20
       } else {
-	printf("VTS %2d ", vts);
+        printf("VTS %2d ", vts);
       }
       for(level =3D 0; level < 8; level++) {
-	printf("%d: %04x  ", level,
-	       ptl_mait->countries[i].pf_ptl_mai[vts][level] );
+        printf("%d: %04x  ", level,
+               ptl_mait->countries[i].pf_ptl_mai[vts][level] );
       }
       printf("\n");
     }
@@ -907,9 +936,9 @@
     for(j =3D 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) {
       unsigned int ac_time =3D timeunit * (j + 1);
       printf("Time: %2i:%02i:%02i  VOBU Sector: 0x%08x %s\n",=20
-	     ac_time / (60 * 60), (ac_time / 60) % 60, ac_time % 60,
-	     vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff,
-	     (vts_tmapt->tmap[i].map_ent[j] >> 31) ? "discontinuity" : "");
+             ac_time / (60 * 60), (ac_time / 60) % 60, ac_time % 60,
+             vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff,
+             (vts_tmapt->tmap[i].map_ent[j] >> 31) ? "discontinuity" : "=
");
     }
   }
 }
@@ -919,14 +948,14 @@
  =20
   printf("Number of VOBs in this VOBS: %i\n", c_adt->nr_of_vobs);
   //entries =3D c_adt->nr_of_vobs;
-  entries =3D (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(c_adt_t);
+  entries =3D (c_adt->last_byte + 1 - C_ADT_SIZE)/sizeof(cell_adr_t);
  =20
   for(i =3D 0; i < entries; i++) {
     printf("VOB ID: %3i, Cell ID: %3i   ",=20
-	   c_adt->cell_adr_table[i].vob_id, c_adt->cell_adr_table[i].cell_id);
+           c_adt->cell_adr_table[i].vob_id, c_adt->cell_adr_table[i].cel=
l_id);
     printf("Sector (first): 0x%08x   (last): 0x%08x\n",
-	   c_adt->cell_adr_table[i].start_sector,=20
-	   c_adt->cell_adr_table[i].last_sector);
+           c_adt->cell_adr_table[i].start_sector,=20
+           c_adt->cell_adr_table[i].last_sector);
   }
 }
=20
@@ -937,7 +966,7 @@
   entries =3D (vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE)/4;
   for(i =3D 0; i < entries; i++) {
     printf("VOBU %5i  First sector: 0x%08x\n", i + 1,
-	   vobu_admap->vobu_start_sectors[i]);
+           vobu_admap->vobu_start_sectors[i]);
   }
 }
=20
@@ -960,9 +989,9 @@
   printf("Number of Menu Language Units (PGCI_LU): %3i\n", pgci_ut->nr_o=
f_lus);
   for(i =3D 0; i < pgci_ut->nr_of_lus; i++) {
     printf("\nMenu Language Code: %c%c (%c)\n",
-	   pgci_ut->lu[i].lang_code >> 8,
-	   pgci_ut->lu[i].lang_code & 0xff,
-	   pgci_ut->lu[i].lang_extension ? pgci_ut->lu[i].lang_extension :' ');
+           pgci_ut->lu[i].lang_code >> 8,
+           pgci_ut->lu[i].lang_code & 0xff,
+           pgci_ut->lu[i].lang_extension ? pgci_ut->lu[i].lang_extension=
 :' ');
     printf("Menu Existence: %02x\n", pgci_ut->lu[i].exists);
     ifoPrint_PGCIT(pgci_ut->lu[i].pgcit);
   }
@@ -978,14 +1007,14 @@
   ifoPrint_video_attributes(&vts_attributes->vtsm_vobs_attr);
   printf("\n");
   printf("Number of Audio streams: %i\n",=20
-	 vts_attributes->nr_of_vtsm_audio_streams);
+         vts_attributes->nr_of_vtsm_audio_streams);
   if(vts_attributes->nr_of_vtsm_audio_streams > 0) {
     printf("\tstream %i attributes: ", 1);
     ifoPrint_audio_attributes(&vts_attributes->vtsm_audio_attr);
     printf("\n");
   }
   printf("Number of Subpicture streams: %i\n",=20
-	 vts_attributes->nr_of_vtsm_subp_streams);
+         vts_attributes->nr_of_vtsm_subp_streams);
   if(vts_attributes->nr_of_vtsm_subp_streams > 0) {
     printf("\tstream %2i attributes: ", 1);
     ifoPrint_subp_attributes(&vts_attributes->vtsm_subp_attr);
@@ -996,7 +1025,7 @@
   ifoPrint_video_attributes(&vts_attributes->vtstt_vobs_video_attr);
   printf("\n");
   printf("Number of Audio streams: %i\n",=20
-	 vts_attributes->nr_of_vtstt_audio_streams);
+         vts_attributes->nr_of_vtstt_audio_streams);
   for(i =3D 0; i < vts_attributes->nr_of_vtstt_audio_streams; i++) {
     printf("\tstream %i attributes: ", i);
     ifoPrint_audio_attributes(&vts_attributes->vtstt_audio_attr[i]);
@@ -1004,7 +1033,7 @@
   }
  =20
   printf("Number of Subpicture streams: %i\n",=20
-	 vts_attributes->nr_of_vtstt_subp_streams);
+         vts_attributes->nr_of_vtstt_subp_streams);
   for(i =3D 0; i < vts_attributes->nr_of_vtstt_subp_streams; i++) {
     printf("\tstream %2i attributes: ", i);   =20
     ifoPrint_subp_attributes(&vts_attributes->vtstt_subp_attr[i]);
@@ -1020,7 +1049,7 @@
   for(i =3D 0; i < vts_atrt->nr_of_vtss; i++) {
     printf("\nVideo Title Set %i\n", i + 1);
     printf("  offset %d relative to VMG_VTS_ATRT\n",=20
-	   vts_atrt->vts_atrt_offsets[i]);
+           vts_atrt->vts_atrt_offsets[i]);
     ifoPrint_VTS_ATTRIBUTES(&vts_atrt->vts[i]);
   }
 }
@@ -1031,7 +1060,9 @@
=20
   ifohandle =3D ifoOpen(dvd, title);
   if(!ifohandle) {
-    LOG_ERROR( stderr, "Can't open info file for title %d\n", title );
+    if(dvdread_verbose(dvd) >=3D 0) {
+      fprintf(stderr, "Can't open info file for title %d\n", title);
+    }
     return;
   }
  =20
@@ -1042,7 +1073,11 @@
     ifoPrint_VMGI_MAT(ifohandle->vmgi_mat);
=20
     printf("\nFirst Play PGC\n--------------\n");
-    ifoPrint_PGC(ifohandle->first_play_pgc);
+    if(ifohandle->first_play_pgc) {
+      ifoPrint_PGC(ifohandle->first_play_pgc);
+    } else {
+      printf("No First Play PGC present\n");
+    }
=20
     printf("\nTitle Track search pointer table\n");
     printf(  "------------------------------------------------\n");

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_read.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_read.c	2007-01-22 11:21:=
16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_read.c	2007-01-28 16:48:=
11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2000, 2001, 2002, 2003
  *               Bj=F6rn Englund <d4bjorn at dtek.chalmers.se>,=20
@@ -22,8 +23,15 @@
=20
 #include <stdio.h>
 #include <stdlib.h>
+
+#if defined(HAVE_INTTYPES_H)
 #include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
 #include <string.h>
+#include <errno.h>
=20
 #include "bswap.h"
 #include "ifo_types.h"
@@ -36,19 +44,19 @@
 #endif
=20
 #ifndef NDEBUG
-#define CHECK_ZERO0(arg) \
-  if(arg !=3D 0) { \
-    LOG_ERROR( stderr, "*** Zero check failed in %s:%i\n    for %s =3D 0=
x%x\n", \
-            __FILE__, __LINE__, # arg, arg); \
+#define CHECK_ZERO0(arg)                                                =
\
+  if(arg !=3D 0) {                                                      =
  \
+    fprintf(stderr, "*** Zero check failed in %s:%i\n    for %s =3D 0x%x=
\n", \
+            __FILE__, __LINE__, # arg, arg);                            =
\
   }
-#define CHECK_ZERO(arg) \
-  if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) { \
-    unsigned int i_CZ; \
-    LOG_ERROR( stderr, "*** Zero check failed in %s:%i\n    for %s =3D 0=
x", \
-            __FILE__, __LINE__, # arg ); \
-    for(i_CZ =3D 0; i_CZ < sizeof(arg); i_CZ++) \
-      LOG_ERROR( stderr, "%02x", *((uint8_t *)&arg + i_CZ)); \
-    LOG_ERROR( stderr, "\n"); \
+#define CHECK_ZERO(arg)                                                 =
\
+  if(memcmp(my_friendly_zeros, &arg, sizeof(arg))) {                    =
\
+    unsigned int i_CZ;                                                  =
\
+    fprintf(stderr, "*** Zero check failed in %s:%i\n    for %s =3D 0x",=
  \
+            __FILE__, __LINE__, # arg );                                =
\
+    for(i_CZ =3D 0; i_CZ < sizeof(arg); i_CZ++)                         =
  \
+      fprintf(stderr, "%02x", *((uint8_t *)&arg + i_CZ));               =
\
+    fprintf(stderr, "\n");                                              =
\
   }
 static const uint8_t my_friendly_zeros[2048];
 #else
@@ -63,7 +71,7 @@
 static int ifoRead_PGC(ifo_handle_t *ifofile, pgc_t *pgc, unsigned int o=
ffset);
 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,=20
                                    pgc_command_tbl_t *cmd_tbl,=20
-				   unsigned int offset);
+                                   unsigned int offset);
 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,=20
                                    pgc_program_map_t *program_map,=20
                                    unsigned int nr, unsigned int offset)=
;
@@ -80,7 +88,7 @@
                                   unsigned int sector);
 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,=20
                                        vobu_admap_t *vobu_admap,=20
-				       unsigned int sector);
+                                       unsigned int sector);
 static int ifoRead_PGCIT_internal(ifo_handle_t *ifofile, pgcit_t *pgcit,=
=20
                                   unsigned int offset);
=20
@@ -88,6 +96,11 @@
 static void ifoFree_PGC_COMMAND_TBL(pgc_command_tbl_t *cmd_tbl);
 static void ifoFree_PGCIT_internal(pgcit_t *pgcit);
=20
+static ifo_handle_t *ifoOpen_File(ifo_handle_t *ifofile, int title,=20
+                                  char *suffix);
+static ifo_handle_t *ifoOpenVMGI_File(ifo_handle_t *ifofile, char *suffi=
x);
+static ifo_handle_t *ifoOpenVTSI_File(ifo_handle_t *ifofile, int title,
+                                      char *suffix);
=20
 static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) =
{
   return (DVDFileSeek(dvd_file, (int)offset) =3D=3D (int)offset);
@@ -99,21 +112,52 @@
=20
   ifofile =3D (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
   if(!ifofile)
-    return 0;
+    return NULL;
=20
   memset(ifofile, 0, sizeof(ifo_handle_t));
=20
   ifofile->file =3D DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
-  if(!ifofile->file) /* Should really catch any error and try to fallbac=
k */
-    ifofile->file =3D DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE)=
;
-  if(!ifofile->file) {
+  if(!ifoOpen_File(ifofile, title, "IFO")) {
     if(title) {
-      LOG_ERROR( stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n"=
, title);
+      if(dvdread_verbose(dvd) >=3D 1) {
+        fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n",=20
+                title, "IFO");
+      }
     } else {
-      LOG_ERROR( stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n");
+      if(dvdread_verbose(dvd) >=3D 1) {
+        fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.%s.\n", "I=
FO");
+      }
     }
+    /* lower functions free the pointer, reallocate */
+    ifofile =3D (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
+    if(!ifofile)
+      return NULL;
+
+    memset(ifofile, 0, sizeof(ifo_handle_t));
+
+    ifofile->file =3D DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE)=
;
+    if(!ifoOpen_File(ifofile, title, "BUP")) {
+      if(title) {
+        if(dvdread_verbose(dvd) >=3D 1) {
+          fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n"=
,=20
+                  title, "BUP");
+        }
+      } else {
+        if(dvdread_verbose(dvd) >=3D 1) {
+          fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.%s.\n", =
"BUP");
+        }
+      }
+      return NULL;
+    }
+  }
+  return ifofile;
+}
+
+static ifo_handle_t *ifoOpen_File(ifo_handle_t *ifofile, int title,=20
+                                  char *suffix) {
+  if(!ifofile->file) {
     free(ifofile);
-    return 0;
+    return NULL;
   }
=20
   /* First check if this is a VMGI file. */
@@ -121,9 +165,12 @@
=20
     /* These are both mandatory. */
     if(!ifoRead_FP_PGC(ifofile) || !ifoRead_TT_SRPT(ifofile)) {
-      LOG_ERROR( stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IF=
O).\n");
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+        fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s)=
.\n",
+                suffix);
+      }
       ifoClose(ifofile);
-      return 0;
+      return NULL;
     }
=20
     ifoRead_PGCI_UT(ifofile);
@@ -131,9 +178,12 @@
=20
     /* This is also mandatory. */
     if(!ifoRead_VTS_ATRT(ifofile)) {
-      LOG_ERROR( stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IF=
O).\n");
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+        fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s)=
.\n",
+                suffix);
+      }
       ifoClose(ifofile);
-      return 0;
+      return NULL;
     }
=20
     ifoRead_TXTDT_MGI(ifofile);
@@ -146,36 +196,44 @@
   if(ifoRead_VTS(ifofile)) {
=20
     if(!ifoRead_VTS_PTT_SRPT(ifofile) || !ifoRead_PGCIT(ifofile)) {
-      LOG_ERROR( stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO)=
.\n",
-              title);
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+        fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.%s).\=
n",
+                title, suffix);
+      }
       ifoClose(ifofile);
-      return 0;
+      return NULL;
     }
=20
-
     ifoRead_PGCI_UT(ifofile);
     ifoRead_VTS_TMAPT(ifofile);
     ifoRead_C_ADT(ifofile);
     ifoRead_VOBU_ADMAP(ifofile);
=20
     if(!ifoRead_TITLE_C_ADT(ifofile) || !ifoRead_TITLE_VOBU_ADMAP(ifofil=
e)) {
-      LOG_ERROR( stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.IFO)=
.\n",
-              title);
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+        fprintf(stderr, "libdvdread: Invalid title IFO (VTS_%02d_0.%s).\=
n",
+                title, suffix);
+      }
       ifoClose(ifofile);
-      return 0;
+      return NULL;
     }
=20
     return ifofile;
   }
=20
   if(title) {
-    LOG_ERROR( stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0=
.IFO).\n",
-	    title, title);
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+      fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.=
%s).\n",
+              title, title, suffix);
+    }
   } else {
-    LOG_ERROR( stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.IFO).=
\n");
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+      fprintf(stderr, "libdvdread: Invalid IFO for VMGM (VIDEO_TS.%s).\n=
",=20
+              suffix);
+    }
   }
   ifoClose(ifofile);
-  return 0;
+  return NULL;
 }
=20
=20
@@ -184,25 +242,50 @@
=20
   ifofile =3D (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
   if(!ifofile)
-    return 0;
+    return NULL;
=20
   memset(ifofile, 0, sizeof(ifo_handle_t));
=20
   ifofile->file =3D DVDOpenFile(dvd, 0, DVD_READ_INFO_FILE);
-  if(!ifofile->file) /* Should really catch any error and try to fallbac=
k */
+  if(!ifoOpenVMGI_File(ifofile, "IFO")) {
+    if(dvdread_verbose(dvd) >=3D 1) {
+      fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.IFO: %s\n",
+              strerror(errno));
+    }
+
+    /* lower functions free the pointer, reallocate */
+    ifofile =3D (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
+    if(!ifofile)
+      return NULL;
+
+    memset(ifofile, 0, sizeof(ifo_handle_t));
+
     ifofile->file =3D DVDOpenFile(dvd, 0, DVD_READ_INFO_BACKUP_FILE);
+    if(!ifoOpenVMGI_File(ifofile, "BUP"))
+      if(dvdread_verbose(dvd) >=3D 1) {
+        fprintf(stderr, "libdvdread: Can't open file VIDEO_TS.BUP: %s\n"=
,
+                strerror(errno));
+      }
+      return NULL;
+  }
+  return ifofile;
+}
+
+static ifo_handle_t *ifoOpenVMGI_File(ifo_handle_t *ifofile, char *suffi=
x) {
   if(!ifofile->file) {
-    LOG_ERROR( stderr, "libdvdread: Can't open file VIDEO_TS.IFO.\n");
     free(ifofile);
-    return 0;
+    return NULL;
   }
=20
   if(ifoRead_VMG(ifofile))
     return ifofile;
=20
-  LOG_ERROR( stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.IFO).\=
n");
+  if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+    fprintf(stderr, "libdvdread: Invalid main menu IFO (VIDEO_TS.%s).\n"=
,=20
+            suffix);
+  }
   ifoClose(ifofile);
-  return 0;
+  return NULL;
 }
=20
=20
@@ -211,33 +294,57 @@
  =20
   ifofile =3D (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
   if(!ifofile)
-    return 0;
+    return NULL;
=20
   memset(ifofile, 0, sizeof(ifo_handle_t));
  =20
   if(title <=3D 0 || title > 99) {
-    LOG_ERROR( stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", =
title);
+    if(dvdread_verbose(dvd) >=3D 0) {
+      fprintf(stderr, "libdvdread: ifoOpenVTSI invalid title (%d).\n", t=
itle);
+    }
     free(ifofile);
-    return 0;
+    errno =3D EINVAL;
+    return NULL;
   }
    =20
   ifofile->file =3D DVDOpenFile(dvd, title, DVD_READ_INFO_FILE);
-  if(!ifofile->file) /* Should really catch any error and try to fallbac=
k */
+  if(!ifoOpenVTSI_File(ifofile, title, "IFO")) {
+    if(dvdread_verbose(dvd) >=3D 1) {
+      fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", ti=
tle, "IFO");
+    }
+    /* lower functions free the pointer, reallocate */
+    ifofile =3D (ifo_handle_t *)malloc(sizeof(ifo_handle_t));
+    if(!ifofile)
+      return NULL;
+
+    memset(ifofile, 0, sizeof(ifo_handle_t));
+
     ifofile->file =3D DVDOpenFile(dvd, title, DVD_READ_INFO_BACKUP_FILE)=
;
+    if(!ifoOpenVTSI_File(ifofile, title, "BUP"))
+      if(dvdread_verbose(dvd) >=3D 1) {
+        fprintf(stderr, "libdvdread: Can't open file VTS_%02d_0.%s.\n", =
title, "BUP");
+      }
+      return NULL;
+  }
+  return ifofile;
+}
+
+static ifo_handle_t *ifoOpenVTSI_File(ifo_handle_t* ifofile, int title, =
char *suffix) {
   if(!ifofile->file) {
-    LOG_ERROR( stderr, "libdvdread: Can't open file VTS_%02d_0.IFO.\n", =
title);
     free(ifofile);
-    return 0;
+    return NULL;
   }
=20
   ifoRead_VTS(ifofile);
   if(ifofile->vtsi_mat)
     return ifofile;
=20
-  LOG_ERROR( stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.I=
FO).\n",
-          title, title);
+  if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 0) {
+    fprintf(stderr, "libdvdread: Invalid IFO for title %d (VTS_%02d_0.%s=
).\n",
+            title, title, suffix);
+  }
   ifoClose(ifofile);
-  return 0;
+  return NULL;
 }
=20
=20
@@ -341,12 +448,12 @@
   CHECK_VALUE(vmgi_mat->vmg_nr_of_title_sets !=3D 0);
   CHECK_VALUE(vmgi_mat->vmgi_last_byte >=3D 341);
   CHECK_VALUE(vmgi_mat->vmgi_last_byte / DVD_BLOCK_LEN <=3D=20
-         vmgi_mat->vmgi_last_sector);
+              vmgi_mat->vmgi_last_sector);
   /* It seems that first_play_pgc is optional. */
   CHECK_VALUE(vmgi_mat->first_play_pgc < vmgi_mat->vmgi_last_byte);
   CHECK_VALUE(vmgi_mat->vmgm_vobs =3D=3D 0 ||=20
-        (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector &&
-         vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector));
+              (vmgi_mat->vmgm_vobs > vmgi_mat->vmgi_last_sector &&
+               vmgi_mat->vmgm_vobs < vmgi_mat->vmg_last_sector));
   CHECK_VALUE(vmgi_mat->tt_srpt <=3D vmgi_mat->vmgi_last_sector);
   CHECK_VALUE(vmgi_mat->vmgm_pgci_ut <=3D vmgi_mat->vmgi_last_sector);
   CHECK_VALUE(vmgi_mat->ptl_mait <=3D vmgi_mat->vmgi_last_sector);
@@ -436,11 +543,11 @@
   CHECK_VALUE(vtsi_mat->vtsi_last_sector*2 <=3D vtsi_mat->vts_last_secto=
r);
   CHECK_VALUE(vtsi_mat->vtsi_last_byte/DVD_BLOCK_LEN <=3D vtsi_mat->vtsi=
_last_sector);
   CHECK_VALUE(vtsi_mat->vtsm_vobs =3D=3D 0 ||=20
-       (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector &&
-         vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector));
+              (vtsi_mat->vtsm_vobs > vtsi_mat->vtsi_last_sector &&
+               vtsi_mat->vtsm_vobs < vtsi_mat->vts_last_sector));
   CHECK_VALUE(vtsi_mat->vtstt_vobs =3D=3D 0 ||=20
-        (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector &&
-         vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector));
+              (vtsi_mat->vtstt_vobs > vtsi_mat->vtsi_last_sector &&
+               vtsi_mat->vtstt_vobs < vtsi_mat->vts_last_sector));
   CHECK_VALUE(vtsi_mat->vts_ptt_srpt <=3D vtsi_mat->vtsi_last_sector);
   CHECK_VALUE(vtsi_mat->vts_pgcit <=3D vtsi_mat->vtsi_last_sector);
   CHECK_VALUE(vtsi_mat->vtsm_pgci_ut <=3D vtsi_mat->vtsi_last_sector);
@@ -476,10 +583,11 @@
=20
 static int ifoRead_PGC_COMMAND_TBL(ifo_handle_t *ifofile,=20
                                    pgc_command_tbl_t *cmd_tbl,=20
-				   unsigned int offset) {
- =20
+                                   unsigned int offset) {
+  unsigned int total;
+
   memset(cmd_tbl, 0, sizeof(pgc_command_tbl_t));
- =20
+
   if(!DVDFileSeek_(ifofile->file, offset))
     return 0;
=20
@@ -489,9 +597,13 @@
   B2N_16(cmd_tbl->nr_of_pre);
   B2N_16(cmd_tbl->nr_of_post);
   B2N_16(cmd_tbl->nr_of_cell);
+  B2N_16(cmd_tbl->last_byte);
+ =20
+  total =3D cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_ce=
ll;
+  CHECK_VALUE(PGC_COMMAND_TBL_SIZE + total * COMMAND_DATA_SIZE=20
+              <=3D cmd_tbl->last_byte + 1U);
+  CHECK_VALUE(total <=3D 255);
=20
-  CHECK_VALUE(cmd_tbl->nr_of_pre + cmd_tbl->nr_of_post + cmd_tbl->nr_of_=
cell<=3D 255);
-    =20
   if(cmd_tbl->nr_of_pre !=3D 0) {
     unsigned int pre_cmds_size  =3D cmd_tbl->nr_of_pre * COMMAND_DATA_SI=
ZE;
     cmd_tbl->pre_cmds =3D (vm_cmd_t *)malloc(pre_cmds_size);
@@ -503,18 +615,18 @@
       return 0;
     }
   }
- =20
+
   if(cmd_tbl->nr_of_post !=3D 0) {
     unsigned int post_cmds_size =3D cmd_tbl->nr_of_post * COMMAND_DATA_S=
IZE;
     cmd_tbl->post_cmds =3D (vm_cmd_t *)malloc(post_cmds_size);
     if(!cmd_tbl->post_cmds) {
       if(cmd_tbl->pre_cmds)=20
-	free(cmd_tbl->pre_cmds);
+        free(cmd_tbl->pre_cmds);
       return 0;
     }
     if(!(DVDReadBytes(ifofile->file, cmd_tbl->post_cmds, post_cmds_size)=
)) {
       if(cmd_tbl->pre_cmds)=20
-	free(cmd_tbl->pre_cmds);
+        free(cmd_tbl->pre_cmds);
       free(cmd_tbl->post_cmds);
       return 0;
     }
@@ -525,16 +637,16 @@
     cmd_tbl->cell_cmds =3D (vm_cmd_t *)malloc(cell_cmds_size);
     if(!cmd_tbl->cell_cmds) {
       if(cmd_tbl->pre_cmds)
-	free(cmd_tbl->pre_cmds);
+        free(cmd_tbl->pre_cmds);
       if(cmd_tbl->post_cmds)
-	free(cmd_tbl->post_cmds);
+        free(cmd_tbl->post_cmds);
       return 0;
     }
     if(!(DVDReadBytes(ifofile->file, cmd_tbl->cell_cmds, cell_cmds_size)=
)) {
       if(cmd_tbl->pre_cmds)=20
-	free(cmd_tbl->pre_cmds);
+        free(cmd_tbl->pre_cmds);
       if(cmd_tbl->post_cmds)=20
-	free(cmd_tbl->post_cmds);
+        free(cmd_tbl->post_cmds);
       free(cmd_tbl->cell_cmds);
       return 0;
     }
@@ -561,7 +673,7 @@
=20
 static int ifoRead_PGC_PROGRAM_MAP(ifo_handle_t *ifofile,=20
                                    pgc_program_map_t *program_map,=20
-				   unsigned int nr, unsigned int offset) {
+                                   unsigned int nr, unsigned int offset)=
 {
   unsigned int size =3D nr * sizeof(pgc_program_map_t);
=20
   if(!DVDFileSeek_(ifofile->file, offset))
@@ -593,9 +705,9 @@
    =20
     /* Changed < to <=3D because this was false in the movie 'Pi'. */
     CHECK_VALUE(cell_playback[i].last_vobu_start_sector <=3D=20
-           cell_playback[i].last_sector);
+                cell_playback[i].last_sector);
     CHECK_VALUE(cell_playback[i].first_sector <=3D=20
-           cell_playback[i].last_vobu_start_sector);
+                cell_playback[i].last_vobu_start_sector);
   }
=20
   return 1;
@@ -685,6 +797,8 @@
   }
  =20
   if(pgc->program_map_offset !=3D 0) {
+    if(pgc->nr_of_programs !=3D 0) {
+
     pgc->program_map =3D malloc(pgc->nr_of_programs * sizeof(pgc_program=
_map_t));
     if(!pgc->program_map) {
       ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
@@ -696,43 +810,56 @@
       free(pgc->program_map);
       return 0;
     }
+    } else {
+      pgc->program_map =3D NULL;
+    }
   } else {
     pgc->program_map =3D NULL;
   }
  =20
   if(pgc->cell_playback_offset !=3D 0) {
+    if(pgc->nr_of_cells !=3D 0) {
+
     pgc->cell_playback =3D malloc(pgc->nr_of_cells * sizeof(cell_playbac=
k_t));
     if(!pgc->cell_playback) {
       ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
       if(pgc->program_map)
-	free(pgc->program_map);
+        free(pgc->program_map);
       return 0;
     }
     if(!ifoRead_CELL_PLAYBACK_TBL(ifofile, pgc->cell_playback,=20
-				  pgc->nr_of_cells,
+                                  pgc->nr_of_cells,
                                   offset + pgc->cell_playback_offset)) {
       ifoFree_PGC_COMMAND_TBL(pgc->command_tbl);
       if(pgc->program_map)
-	free(pgc->program_map);
+        free(pgc->program_map);
       free(pgc->cell_playback);
       return 0;
     }
+    } else {
+      pgc->cell_playback =3D NULL;
+    }
   } else {
     pgc->cell_playback =3D NULL;
   }
  =20
   if(pgc->cell_position_offset !=3D 0) {
+    if(pgc->nr_of_cells !=3D 0) {
+
     pgc->cell_position =3D malloc(pgc->nr_of_cells * sizeof(cell_positio=
n_t));
     if(!pgc->cell_position) {
       ifoFree_PGC(pgc);
       return 0;
     }
     if(!ifoRead_CELL_POSITION_TBL(ifofile, pgc->cell_position,=20
-				  pgc->nr_of_cells,
+                                  pgc->nr_of_cells,
                                   offset + pgc->cell_position_offset)) {
       ifoFree_PGC(pgc);
       return 0;
     }
+    } else {
+      pgc->cell_position =3D NULL;
+    }
   } else {
     pgc->cell_position =3D NULL;
   }
@@ -793,7 +920,8 @@
=20
 int ifoRead_TT_SRPT(ifo_handle_t *ifofile) {
   tt_srpt_t *tt_srpt;
-  int i, info_length;
+  int i;
+  unsigned info_length;
=20
   if(!ifofile)
     return 0;
@@ -814,7 +942,9 @@
   ifofile->tt_srpt =3D tt_srpt;
  =20
   if(!(DVDReadBytes(ifofile->file, tt_srpt, TT_SRPT_SIZE))) {
-    LOG_ERROR( stderr, "libdvdread: Unable to read read TT_SRPT.\n");
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
+    }
     free(tt_srpt);
     return 0;
   }
@@ -831,7 +961,9 @@
     return 0;
   }
   if(!(DVDReadBytes(ifofile->file, tt_srpt->title, info_length))) {
-    LOG_ERROR( stderr, "libdvdread: Unable to read read TT_SRPT.\n");
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: Unable to read read TT_SRPT.\n");
+    }
     ifoFree_TT_SRPT(ifofile);
     return 0;
   }
@@ -846,7 +978,7 @@
   CHECK_ZERO(tt_srpt->zero_1);
   CHECK_VALUE(tt_srpt->nr_of_srpts !=3D 0);
   CHECK_VALUE(tt_srpt->nr_of_srpts < 100); // ??
-  CHECK_VALUE((int)tt_srpt->nr_of_srpts * sizeof(title_info_t) <=3D info=
_length);
+  CHECK_VALUE(tt_srpt->nr_of_srpts * sizeof(title_info_t) <=3D info_leng=
th);
  =20
   for(i =3D 0; i < tt_srpt->nr_of_srpts; i++) {
     CHECK_VALUE(tt_srpt->title[i].pb_ty.zero_1 =3D=3D 0);
@@ -868,7 +1000,7 @@
             tt_srpt->nr_of_srpts * sizeof(title_info_t),=20
             my_friendly_zeros,=20
             info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t))) =
{
-    LOG_ERROR( stderr, "VMG_PTT_SRPT slack is !=3D 0, ");
+    fprintf(stderr, "VMG_PTT_SRPT slack is !=3D 0, ");
     hexdump((uint8_t *)tt_srpt->title +=20
             tt_srpt->nr_of_srpts * sizeof(title_info_t),=20
             info_length - tt_srpt->nr_of_srpts * sizeof(title_info_t));
@@ -895,7 +1027,6 @@
   vts_ptt_srpt_t *vts_ptt_srpt;
   int info_length, i, j;
   uint32_t *data;
-  uint8_t *data_8;
=20
   if(!ifofile)
     return 0;
@@ -907,7 +1038,7 @@
     return 0;
    =20
   if(!DVDFileSeek_(ifofile->file,
-		   ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN))
+                   ifofile->vtsi_mat->vts_ptt_srpt * DVD_BLOCK_LEN))
     return 0;
=20
   vts_ptt_srpt =3D (vts_ptt_srpt_t *)malloc(sizeof(vts_ptt_srpt_t));
@@ -917,7 +1048,9 @@
   ifofile->vts_ptt_srpt =3D vts_ptt_srpt;
=20
   if(!(DVDReadBytes(ifofile->file, vts_ptt_srpt, VTS_PTT_SRPT_SIZE))) {
-    LOG_ERROR( stderr, "libdvdread: Unable to read PTT search table.\n")=
;
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
+    }
     free(vts_ptt_srpt);
     return 0;
   }
@@ -938,7 +1071,9 @@
     return 0;
   }
   if(!(DVDReadBytes(ifofile->file, data, info_length))) {
-    LOG_ERROR( stderr, "libdvdread: Unable to read PTT search table.\n")=
;
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: Unable to read PTT search table.\n");
+    }
     free(vts_ptt_srpt);
     free(data);
     ifofile->vts_ptt_srpt =3D 0;
@@ -988,11 +1123,10 @@
     for(j =3D 0; j < vts_ptt_srpt->title[i].nr_of_ptts; j++) {
       /* The assert placed here because of Magic Knight Rayearth Daybrea=
k */
       CHECK_VALUE(data[i] + sizeof(ptt_info_t) <=3D vts_ptt_srpt->last_b=
yte + 1);
-	  data_8 =3D data;
       vts_ptt_srpt->title[i].ptt[j].pgcn=20
-        =3D *(uint16_t*)(&data_8[data[i] + 4*j - VTS_PTT_SRPT_SIZE]);
+        =3D *(uint16_t*)(((char *)data) + data[i] + 4*j - VTS_PTT_SRPT_S=
IZE);
       vts_ptt_srpt->title[i].ptt[j].pgn=20
-        =3D *(uint16_t*)(&data_8[data[i] + 4*j + 2 - VTS_PTT_SRPT_SIZE])=
;
+        =3D *(uint16_t*)(((char *)data) + data[i] + 4*j + 2 - VTS_PTT_SR=
PT_SIZE);
     }
   }
  =20
@@ -1071,7 +1205,7 @@
   CHECK_VALUE(ptl_mait->nr_of_vtss !=3D 0);
   CHECK_VALUE(ptl_mait->nr_of_vtss < 100); // ?? =20
   CHECK_VALUE(ptl_mait->nr_of_countries * PTL_MAIT_COUNTRY_SIZE=20
-	      <=3D ptl_mait->last_byte + 1 - PTL_MAIT_SIZE);
+              <=3D ptl_mait->last_byte + 1 - PTL_MAIT_SIZE);
  =20
   info_length =3D ptl_mait->nr_of_countries * sizeof(ptl_mait_country_t)=
;
   ptl_mait->countries =3D (ptl_mait_country_t *)malloc(info_length);
@@ -1083,7 +1217,9 @@
  =20
   for(i =3D 0; i < ptl_mait->nr_of_countries; i++) {
     if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_C=
OUNTRY_SIZE))) {
-      LOG_ERROR( stderr, "libdvdread: Unable to read PTL_MAIT.\n");
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+        fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
+      }
       free(ptl_mait->countries);
       free(ptl_mait);
       ifofile->ptl_mait =3D 0;
@@ -1099,17 +1235,19 @@
   for(i =3D 0; i < ptl_mait->nr_of_countries; i++) {
     CHECK_ZERO(ptl_mait->countries[i].zero_1);
     CHECK_ZERO(ptl_mait->countries[i].zero_2);   =20
-    CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte
-		+ 8*2 * (ptl_mait->nr_of_vtss + 1) <=3D ptl_mait->last_byte + 1);
+    CHECK_VALUE(ptl_mait->countries[i].pf_ptl_mai_start_byte +
+                16U * (ptl_mait->nr_of_vtss + 1) <=3D ptl_mait->last_byt=
e + 1U);
   }
=20
   for(i =3D 0; i < ptl_mait->nr_of_countries; i++) {
     uint16_t *pf_temp;
    =20
     if(!DVDFileSeek_(ifofile->file,=20
-		     ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
+                     ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
                      + ptl_mait->countries[i].pf_ptl_mai_start_byte)) {
-      LOG_ERROR( stderr, "libdvdread: Unable to seak PTL_MAIT table.\n")=
;
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+        fprintf(stderr, "libdvdread: Unable to seak PTL_MAIT table.\n");
+      }
       free(ptl_mait->countries);
       free(ptl_mait);
       return 0;
@@ -1118,30 +1256,32 @@
     pf_temp =3D (uint16_t *)malloc(info_length);
     if(!pf_temp) {
       for(j =3D 0; j < i ; j++) {
-         free(ptl_mait->countries[j].pf_ptl_mai);
+        free(ptl_mait->countries[j].pf_ptl_mai);
       }
       free(ptl_mait->countries);
       free(ptl_mait);
       return 0;
     }
     if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) {
-       LOG_ERROR( stderr, "libdvdread: Unable to read PTL_MAIT table.\n"=
);
-       free(pf_temp);
-       for(j =3D 0; j < i ; j++) {
-	  free(ptl_mait->countries[j].pf_ptl_mai);
-       }
-       free(ptl_mait->countries);
-       free(ptl_mait);
-       return 0;
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+        fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n");
+      }
+      free(pf_temp);
+      for(j =3D 0; j < i ; j++) {
+        free(ptl_mait->countries[j].pf_ptl_mai);
+      }
+      free(ptl_mait->countries);
+      free(ptl_mait);
+      return 0;
     }
     for (j =3D 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) {
-        B2N_16(pf_temp[j]);
+      B2N_16(pf_temp[j]);
     }
     ptl_mait->countries[i].pf_ptl_mai =3D (pf_level_t *)malloc(info_leng=
th);
     if(!ptl_mait->countries[i].pf_ptl_mai) {
       free(pf_temp);
       for(j =3D 0; j < i ; j++) {
-	free(ptl_mait->countries[j].pf_ptl_mai);
+        free(ptl_mait->countries[j].pf_ptl_mai);
       }
       free(ptl_mait->countries);
       free(ptl_mait);
@@ -1150,10 +1290,10 @@
     { /* Transpose the array so we can use C indexing. */
       int level, vts;
       for(level =3D 0; level < 8; level++) {
-	for(vts =3D 0; vts <=3D ptl_mait->nr_of_vtss; vts++) {
-	  ptl_mait->countries[i].pf_ptl_mai[vts][level] =3D
-	    pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts];
-	}
+        for(vts =3D 0; vts <=3D ptl_mait->nr_of_vtss; vts++) {
+          ptl_mait->countries[i].pf_ptl_mai[vts][level] =3D
+            pf_temp[(7-level)*(ptl_mait->nr_of_vtss+1) + vts];
+        }
       }
       free(pf_temp);
     }
@@ -1169,7 +1309,7 @@
  =20
   if(ifofile->ptl_mait) {
     for(i =3D 0; i < ifofile->ptl_mait->nr_of_countries; i++) {
-       free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
+      free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
     }
     free(ifofile->ptl_mait->countries);
     free(ifofile->ptl_mait);
@@ -1190,9 +1330,9 @@
   if(!ifofile->vtsi_mat)
     return 0;
=20
-  if(ifofile->vtsi_mat->vts_tmapt =3D=3D 0) { /* optional(?) */
+  /* Seems to be optional, at least when there are no OneSequencial Titl=
es */
+  if(ifofile->vtsi_mat->vts_tmapt =3D=3D 0) {
     ifofile->vts_tmapt =3D NULL;
-    fprintf(stderr,"Please send bug report - no VTS_TMAPT ?? \n");
     return 1;
   }
  =20
@@ -1208,7 +1348,9 @@
   ifofile->vts_tmapt =3D vts_tmapt;
  =20
   if(!(DVDReadBytes(ifofile->file, vts_tmapt, VTS_TMAPT_SIZE))) {
-    LOG_ERROR( stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
+    }
     free(vts_tmapt);
     ifofile->vts_tmapt =3D NULL;
     return 0;
@@ -1231,7 +1373,9 @@
   vts_tmapt->tmap_offset =3D vts_tmap_srp;
  =20
   if(!(DVDReadBytes(ifofile->file, vts_tmap_srp, info_length))) {
-    LOG_ERROR( stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: Unable to read VTS_TMAPT.\n");
+    }
     free(vts_tmap_srp);
     free(vts_tmapt);
     ifofile->vts_tmapt =3D NULL;
@@ -1239,7 +1383,7 @@
   }
=20
   for (i =3D 0; i < vts_tmapt->nr_of_tmaps; i++) {
-     B2N_32(vts_tmap_srp[i]);=20
+    B2N_32(vts_tmap_srp[i]);=20
   }
=20
  =20
@@ -1262,7 +1406,9 @@
     }
=20
     if(!(DVDReadBytes(ifofile->file, &vts_tmapt->tmap[i], VTS_TMAP_SIZE)=
)) {
-      LOG_ERROR( stderr, "libdvdread: Unable to read VTS_TMAP.\n");
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+        fprintf(stderr, "libdvdread: Unable to read VTS_TMAP.\n");
+      }
       ifoFree_VTS_TMAPT(ifofile);
       return 0;
     }
@@ -1284,7 +1430,9 @@
     }
=20
     if(!(DVDReadBytes(ifofile->file, vts_tmapt->tmap[i].map_ent, info_le=
ngth))) {
-      LOG_ERROR( stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n");
+      if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+        fprintf(stderr, "libdvdread: Unable to read VTS_TMAP_ENT.\n");
+      }
       ifoFree_VTS_TMAPT(ifofile);
       return 0;
     }
@@ -1305,7 +1453,7 @@
   if(ifofile->vts_tmapt) { =20
     for(i =3D 0; i < ifofile->vts_tmapt->nr_of_tmaps; i++)
       if(ifofile->vts_tmapt->tmap[i].map_ent)
-	free(ifofile->vts_tmapt->tmap[i].map_ent);
+        free(ifofile->vts_tmapt->tmap[i].map_ent);
     free(ifofile->vts_tmapt->tmap);
     free(ifofile->vts_tmapt->tmap_offset);
     free(ifofile->vts_tmapt);
@@ -1395,7 +1543,9 @@
      Enemy of the State region 2 (de) has Titles where nr_of_vobs field
      is to high, they high ones are never referenced though. */
   if(info_length / sizeof(cell_adr_t) < c_adt->nr_of_vobs) {
-    LOG_ERROR( stderr, "libdvdread: *C_ADT nr_of_vobs > avaiable info en=
tries\n");
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: *C_ADT nr_of_vobs > avaiable info ent=
ries\n");
+    }
     c_adt->nr_of_vobs =3D info_length / sizeof(cell_adr_t);
   }
  =20
@@ -1419,7 +1569,7 @@
     CHECK_VALUE(c_adt->cell_adr_table[i].vob_id <=3D c_adt->nr_of_vobs);
     CHECK_VALUE(c_adt->cell_adr_table[i].cell_id > 0);
     CHECK_VALUE(c_adt->cell_adr_table[i].start_sector <=20
-	   c_adt->cell_adr_table[i].last_sector);
+                c_adt->cell_adr_table[i].last_sector);
   }
=20
   return 1;
@@ -1506,7 +1656,7 @@
=20
 static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile,=20
                                        vobu_admap_t *vobu_admap,=20
-				       unsigned int sector) {
+                                       unsigned int sector) {
   unsigned int i;
   int info_length;
=20
@@ -1530,7 +1680,7 @@
   }
   if(info_length &&=20
      !(DVDReadBytes(ifofile->file,=20
-		    vobu_admap->vobu_start_sectors, info_length))) {
+                    vobu_admap->vobu_start_sectors, info_length))) {
     free(vobu_admap->vobu_start_sectors);
     return 0;
   }
@@ -1627,8 +1777,8 @@
   }
   ptr =3D data;
   for(i =3D 0; i < pgcit->nr_of_pgci_srp; i++) {
-    memcpy(&pgcit->pgci_srp[i], ptr, PGCI_LU_SIZE);
-    ptr +=3D PGCI_LU_SIZE;
+    memcpy(&pgcit->pgci_srp[i], ptr, PGCI_SRP_SIZE);
+    ptr +=3D PGCI_SRP_SIZE;
     B2N_16(pgcit->pgci_srp[i].ptl_id_mask);
     B2N_32(pgcit->pgci_srp[i].pgc_start_byte);
     CHECK_VALUE(pgcit->pgci_srp[i].unknown1 =3D=3D 0);
@@ -1646,6 +1796,8 @@
         ifoFree_PGC(pgcit->pgci_srp[j].pgc);
         free(pgcit->pgci_srp[j].pgc);
       }
+      free(pgcit->pgci_srp);
+      pgcit->pgci_srp =3D NULL;
       return 0;
     }
     if(!ifoRead_PGC(ifofile, pgcit->pgci_srp[i].pgc,=20
@@ -1656,6 +1808,7 @@
         free(pgcit->pgci_srp[j].pgc);
       }
       free(pgcit->pgci_srp);
+      pgcit->pgci_srp =3D NULL;
       return 0;
     }
   }
@@ -1666,10 +1819,10 @@
 static void ifoFree_PGCIT_internal(pgcit_t *pgcit) {
   if(pgcit) {
     int i;
-	for(i =3D 0; i < pgcit->nr_of_pgci_srp; i++) {
+    for(i =3D 0; i < pgcit->nr_of_pgci_srp; i++) {
       ifoFree_PGC(pgcit->pgci_srp[i].pgc);
       free(pgcit->pgci_srp[i].pgc);
-	}
+    }
     free(pgcit->pgci_srp);
   }
 }
@@ -1753,7 +1906,7 @@
     free(data);
     free(pgci_ut);
     ifofile->pgci_ut =3D 0;
-   return 0;
+    return 0;
   }
   ptr =3D data;
   for(i =3D 0; i < pgci_ut->nr_of_lus; i++) {
@@ -1767,7 +1920,7 @@
   for(i =3D 0; i < pgci_ut->nr_of_lus; i++) {
     // Maybe this is only defined for v1.1 and later titles?
     /* If the bits in 'lu[i].exists' are enumerated abcd efgh then:
-            VTS_x_yy.IFO        VIDEO_TS.IFO
+       VTS_x_yy.IFO        VIDEO_TS.IFO
        a =3D=3D 0x83 "Root"         0x82 "Title"
        b =3D=3D 0x84 "Subpicture"
        c =3D=3D 0x85 "Audio"
@@ -1917,7 +2070,7 @@
   CHECK_VALUE(vts_atrt->nr_of_vtss !=3D 0);
   CHECK_VALUE(vts_atrt->nr_of_vtss < 100); //??
   CHECK_VALUE((uint32_t)vts_atrt->nr_of_vtss * (4 + VTS_ATTRIBUTES_MIN_S=
IZE) +=20
-         VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
+              VTS_ATRT_SIZE < vts_atrt->last_byte + 1);
=20
   info_length =3D vts_atrt->nr_of_vtss * sizeof(uint32_t);
   data =3D (uint32_t *)malloc(info_length);
@@ -1995,7 +2148,7 @@
     return 1;
=20
   if(!DVDFileSeek_(ifofile->file,=20
-		   ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
+                   ifofile->vmgi_mat->txtdt_mgi * DVD_BLOCK_LEN))
     return 0;
  =20
   txtdt_mgi =3D (txtdt_mgi_t *)malloc(sizeof(txtdt_mgi_t));
@@ -2005,13 +2158,15 @@
   ifofile->txtdt_mgi =3D txtdt_mgi;
=20
   if(!(DVDReadBytes(ifofile->file, txtdt_mgi, TXTDT_MGI_SIZE))) {
-    LOG_ERROR( stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
+    if(dvdread_verbose(device_of_file(ifofile->file)) >=3D 1) {
+      fprintf(stderr, "libdvdread: Unable to read TXTDT_MGI.\n");
+    }
     free(txtdt_mgi);
     ifofile->txtdt_mgi =3D 0;
     return 0;
   }
=20
-  // LOG_ERROR( stderr, "-- Not done yet --\n");
+  // fprintf(stderr, "-- Not done yet --\n");
   return 1;
 }
=20

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_types.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_types.h	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/ifo_types.h	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #ifndef IFO_TYPES_H_INCLUDED
 #define IFO_TYPES_H_INCLUDED
=20
@@ -20,9 +21,17 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 =
 USA
  */
=20
-#include <inttypes.h>
 #include <dvdread/dvd_reader.h>
=20
+#if defined(__BEOS__)
+#if !defined(_INTTYPES_H_) && !defined(_INTTYPES_H) && !defined(_STDINT_=
H_) && !defined(_STDINT_H)
+#error "Must include <inttypes.h> or <stdint.h> before any libdvdread he=
ader."
+#endif
+#elif defined(WIN32) && !defined(HAVE_INTTYPES_H) && !defined(HAVE_STDIN=
T_H)
+#error "Must include <inttypes.h> or <stdint.h> before any libdvdread he=
ader."
+#elif !defined(WIN32) && (!defined(UINT8_MAX) || !defined(UINT16_MAX) ||=
 !defined(INT32_MAX))
+#error "Must include <inttypes.h> or <stdint.h> before any libdvdread he=
ader."
+#endif
=20
 #undef ATTRIBUTE_PACKED
 #undef PRAGMA_PACK_BEGIN=20
@@ -68,41 +77,49 @@
 typedef struct {
   uint8_t bytes[8];
 } ATTRIBUTE_PACKED vm_cmd_t;
-#define COMMAND_DATA_SIZE 8
+#define COMMAND_DATA_SIZE 8U
=20
+/* This typedefs are needed for MSVC compatiblity */
+/* Thanks robux ;) */
+#undef BITFIELD_TYPE
+#if defined(_MSC_VER)
+#define BITFIELD_TYPE char
+#else
+#define BITFIELD_TYPE int
+#endif
=20
 /**
  * Video Attributes.
  */
 typedef struct {
 #ifdef WORDS_BIGENDIAN
-  unsigned char mpeg_version         : 2;
-  unsigned char video_format         : 2;
-  unsigned char display_aspect_ratio : 2;
-  unsigned char permitted_df         : 2;
+  unsigned BITFIELD_TYPE mpeg_version         : 2;
+  unsigned BITFIELD_TYPE video_format         : 2;
+  unsigned BITFIELD_TYPE display_aspect_ratio : 2;
+  unsigned BITFIELD_TYPE permitted_df         : 2;
  =20
-  unsigned char line21_cc_1          : 1;
-  unsigned char line21_cc_2          : 1;
-  unsigned char unknown1             : 1;
-  unsigned char bit_rate             : 1;
+  unsigned BITFIELD_TYPE line21_cc_1          : 1;
+  unsigned BITFIELD_TYPE line21_cc_2          : 1;
+  unsigned BITFIELD_TYPE unknown1             : 1;
+  unsigned BITFIELD_TYPE bit_rate             : 1;
  =20
-  unsigned char picture_size         : 2;
-  unsigned char letterboxed          : 1;
-  unsigned char film_mode            : 1;
+  unsigned BITFIELD_TYPE picture_size         : 2;
+  unsigned BITFIELD_TYPE letterboxed          : 1;
+  unsigned BITFIELD_TYPE film_mode            : 1;
 #else
-  unsigned char permitted_df         : 2;
-  unsigned char display_aspect_ratio : 2;
-  unsigned char video_format         : 2;
-  unsigned char mpeg_version         : 2;
+  unsigned BITFIELD_TYPE permitted_df         : 2;
+  unsigned BITFIELD_TYPE display_aspect_ratio : 2;
+  unsigned BITFIELD_TYPE video_format         : 2;
+  unsigned BITFIELD_TYPE mpeg_version         : 2;
  =20
-  unsigned char film_mode            : 1;
-  unsigned char letterboxed          : 1;
-  unsigned char picture_size         : 2;
+  unsigned BITFIELD_TYPE film_mode            : 1;
+  unsigned BITFIELD_TYPE letterboxed          : 1;
+  unsigned BITFIELD_TYPE picture_size         : 2;
  =20
-  unsigned char bit_rate             : 1;
-  unsigned char unknown1             : 1;
-  unsigned char line21_cc_2          : 1;
-  unsigned char line21_cc_1          : 1;
+  unsigned BITFIELD_TYPE bit_rate             : 1;
+  unsigned BITFIELD_TYPE unknown1             : 1;
+  unsigned BITFIELD_TYPE line21_cc_2          : 1;
+  unsigned BITFIELD_TYPE line21_cc_1          : 1;
 #endif
 } ATTRIBUTE_PACKED video_attr_t;
=20
@@ -111,58 +128,58 @@
  */
 typedef struct {
 #ifdef WORDS_BIGENDIAN
-  unsigned char audio_format           : 3;
-  unsigned char multichannel_extension : 1;
-  unsigned char lang_type              : 2;
-  unsigned char application_mode       : 2;
+  unsigned BITFIELD_TYPE audio_format           : 3;
+  unsigned BITFIELD_TYPE multichannel_extension : 1;
+  unsigned BITFIELD_TYPE lang_type              : 2;
+  unsigned BITFIELD_TYPE application_mode       : 2;
  =20
-  unsigned char quantization           : 2;
-  unsigned char sample_frequency       : 2;
-  unsigned char unknown1               : 1;
-  unsigned char channels               : 3;
+  unsigned BITFIELD_TYPE quantization           : 2;
+  unsigned BITFIELD_TYPE sample_frequency       : 2;
+  unsigned BITFIELD_TYPE unknown1               : 1;
+  unsigned BITFIELD_TYPE channels               : 3;
 #else
-  unsigned char application_mode       : 2;
-  unsigned char lang_type              : 2;
-  unsigned char multichannel_extension : 1;
-  unsigned char audio_format           : 3;
+  unsigned BITFIELD_TYPE application_mode       : 2;
+  unsigned BITFIELD_TYPE lang_type              : 2;
+  unsigned BITFIELD_TYPE multichannel_extension : 1;
+  unsigned BITFIELD_TYPE audio_format           : 3;
  =20
-  unsigned char channels               : 3;
-  unsigned char unknown1               : 1;
-  unsigned char sample_frequency       : 2;
-  unsigned char quantization           : 2;
+  unsigned BITFIELD_TYPE channels               : 3;
+  unsigned BITFIELD_TYPE unknown1               : 1;
+  unsigned BITFIELD_TYPE sample_frequency       : 2;
+  unsigned BITFIELD_TYPE quantization           : 2;
 #endif
   uint16_t lang_code;
   uint8_t  lang_extension;
   uint8_t  code_extension;
   uint8_t unknown3;
   union {
-    struct ATTRIBUTE_PACKED {
+    struct {
 #ifdef WORDS_BIGENDIAN
-      unsigned char unknown4           : 1;
-      unsigned char channel_assignment : 3;
-      unsigned char version            : 2;
-      unsigned char mc_intro           : 1; /* probably 0: true, 1:false=
 */
-      unsigned char mode               : 1; /* Karaoke mode 0: solo 1: d=
uet */
+      unsigned BITFIELD_TYPE unknown4           : 1;
+      unsigned BITFIELD_TYPE channel_assignment : 3;
+      unsigned BITFIELD_TYPE version            : 2;
+      unsigned BITFIELD_TYPE mc_intro           : 1; /* probably 0: true=
, 1:false */
+      unsigned BITFIELD_TYPE mode               : 1; /* Karaoke mode 0: =
solo 1: duet */
 #else
-      unsigned char mode               : 1;
-      unsigned char mc_intro           : 1;
-      unsigned char version            : 2;
-      unsigned char channel_assignment : 3;
-      unsigned char unknown4           : 1;
+      unsigned BITFIELD_TYPE mode               : 1;
+      unsigned BITFIELD_TYPE mc_intro           : 1;
+      unsigned BITFIELD_TYPE version            : 2;
+      unsigned BITFIELD_TYPE channel_assignment : 3;
+      unsigned BITFIELD_TYPE unknown4           : 1;
 #endif
-    } karaoke;
-    struct ATTRIBUTE_PACKED {
+    } ATTRIBUTE_PACKED karaoke;
+    struct {
 #ifdef WORDS_BIGENDIAN
-      unsigned char unknown5           : 4;
-      unsigned char dolby_encoded      : 1; /* suitable for surround dec=
oding */
-      unsigned char unknown6           : 3;
+      unsigned BITFIELD_TYPE unknown5           : 4;
+      unsigned BITFIELD_TYPE dolby_encoded      : 1; /* suitable for sur=
round decoding */
+      unsigned BITFIELD_TYPE unknown6           : 3;
 #else
-      unsigned char unknown6           : 3;
-      unsigned char dolby_encoded      : 1;
-      unsigned char unknown5           : 4;
+      unsigned BITFIELD_TYPE unknown6           : 3;
+      unsigned BITFIELD_TYPE dolby_encoded      : 1;
+      unsigned BITFIELD_TYPE unknown5           : 4;
 #endif
-    } surround;
-  } app_info;
+    } ATTRIBUTE_PACKED surround;
+  } ATTRIBUTE_PACKED app_info;
 } ATTRIBUTE_PACKED audio_attr_t;
=20
=20
@@ -171,53 +188,53 @@
  */
 typedef struct {
 #ifdef WORDS_BIGENDIAN
-  unsigned char zero1      : 7;
-  unsigned char ach0_gme   : 1;
+  unsigned BITFIELD_TYPE zero1      : 7;
+  unsigned BITFIELD_TYPE ach0_gme   : 1;
=20
-  unsigned char zero2      : 7;
-  unsigned char ach1_gme   : 1;
+  unsigned BITFIELD_TYPE zero2      : 7;
+  unsigned BITFIELD_TYPE ach1_gme   : 1;
=20
-  unsigned char zero3      : 4;
-  unsigned char ach2_gv1e  : 1;
-  unsigned char ach2_gv2e  : 1;
-  unsigned char ach2_gm1e  : 1;
-  unsigned char ach2_gm2e  : 1;
+  unsigned BITFIELD_TYPE zero3      : 4;
+  unsigned BITFIELD_TYPE ach2_gv1e  : 1;
+  unsigned BITFIELD_TYPE ach2_gv2e  : 1;
+  unsigned BITFIELD_TYPE ach2_gm1e  : 1;
+  unsigned BITFIELD_TYPE ach2_gm2e  : 1;
=20
-  unsigned char zero4      : 4;
-  unsigned char ach3_gv1e  : 1;
-  unsigned char ach3_gv2e  : 1;
-  unsigned char ach3_gmAe  : 1;
-  unsigned char ach3_se2e  : 1;
+  unsigned BITFIELD_TYPE zero4      : 4;
+  unsigned BITFIELD_TYPE ach3_gv1e  : 1;
+  unsigned BITFIELD_TYPE ach3_gv2e  : 1;
+  unsigned BITFIELD_TYPE ach3_gmAe  : 1;
+  unsigned BITFIELD_TYPE ach3_se2e  : 1;
=20
-  unsigned char zero5      : 4;
-  unsigned char ach4_gv1e  : 1;
-  unsigned char ach4_gv2e  : 1;
-  unsigned char ach4_gmBe  : 1;
-  unsigned char ach4_seBe  : 1;
+  unsigned BITFIELD_TYPE zero5      : 4;
+  unsigned BITFIELD_TYPE ach4_gv1e  : 1;
+  unsigned BITFIELD_TYPE ach4_gv2e  : 1;
+  unsigned BITFIELD_TYPE ach4_gmBe  : 1;
+  unsigned BITFIELD_TYPE ach4_seBe  : 1;
 #else
-  unsigned char ach0_gme   : 1;
-  unsigned char zero1      : 7;
+  unsigned BITFIELD_TYPE ach0_gme   : 1;
+  unsigned BITFIELD_TYPE zero1      : 7;
=20
-  unsigned char ach1_gme   : 1;
-  unsigned char zero2      : 7;
+  unsigned BITFIELD_TYPE ach1_gme   : 1;
+  unsigned BITFIELD_TYPE zero2      : 7;
=20
-  unsigned char ach2_gm2e  : 1;
-  unsigned char ach2_gm1e  : 1;
-  unsigned char ach2_gv2e  : 1;
-  unsigned char ach2_gv1e  : 1;
-  unsigned char zero3      : 4;
+  unsigned BITFIELD_TYPE ach2_gm2e  : 1;
+  unsigned BITFIELD_TYPE ach2_gm1e  : 1;
+  unsigned BITFIELD_TYPE ach2_gv2e  : 1;
+  unsigned BITFIELD_TYPE ach2_gv1e  : 1;
+  unsigned BITFIELD_TYPE zero3      : 4;
=20
-  unsigned char ach3_se2e  : 1;
-  unsigned char ach3_gmAe  : 1;
-  unsigned char ach3_gv2e  : 1;
-  unsigned char ach3_gv1e  : 1;
-  unsigned char zero4      : 4;
+  unsigned BITFIELD_TYPE ach3_se2e  : 1;
+  unsigned BITFIELD_TYPE ach3_gmAe  : 1;
+  unsigned BITFIELD_TYPE ach3_gv2e  : 1;
+  unsigned BITFIELD_TYPE ach3_gv1e  : 1;
+  unsigned BITFIELD_TYPE zero4      : 4;
=20
-  unsigned char ach4_seBe  : 1;
-  unsigned char ach4_gmBe  : 1;
-  unsigned char ach4_gv2e  : 1;
-  unsigned char ach4_gv1e  : 1;
-  unsigned char zero5      : 4;
+  unsigned BITFIELD_TYPE ach4_seBe  : 1;
+  unsigned BITFIELD_TYPE ach4_gmBe  : 1;
+  unsigned BITFIELD_TYPE ach4_gv2e  : 1;
+  unsigned BITFIELD_TYPE ach4_gv1e  : 1;
+  unsigned BITFIELD_TYPE zero5      : 4;
 #endif
   uint8_t zero6[19];
 } ATTRIBUTE_PACKED multichannel_ext_t;
@@ -238,13 +255,13 @@
    * lang extension: if type =3D=3D 1 contains the lang extension
    */
 #ifdef WORDS_BIGENDIAN
-  unsigned char code_mode : 3;
-  unsigned char zero1     : 3;
-  unsigned char type      : 2;
+  unsigned BITFIELD_TYPE code_mode : 3;
+  unsigned BITFIELD_TYPE zero1     : 3;
+  unsigned BITFIELD_TYPE type      : 2;
 #else
-  unsigned char type      : 2;
-  unsigned char zero1     : 3;
-  unsigned char code_mode : 3;
+  unsigned BITFIELD_TYPE type      : 2;
+  unsigned BITFIELD_TYPE zero1     : 3;
+  unsigned BITFIELD_TYPE code_mode : 3;
 #endif
   uint8_t  zero2;
   uint16_t lang_code;
@@ -261,12 +278,12 @@
   uint16_t nr_of_pre;
   uint16_t nr_of_post;
   uint16_t nr_of_cell;
-  uint16_t zero_1;
+  uint16_t last_byte;
   vm_cmd_t *pre_cmds;
   vm_cmd_t *post_cmds;
   vm_cmd_t *cell_cmds;
 } ATTRIBUTE_PACKED pgc_command_tbl_t;
-#define PGC_COMMAND_TBL_SIZE 8
+#define PGC_COMMAND_TBL_SIZE 8U
=20
 /**
  * PGC Program Map
@@ -278,27 +295,27 @@
  */
 typedef struct {
 #ifdef WORDS_BIGENDIAN
-  unsigned char block_mode       : 2;
-  unsigned char block_type       : 2;
-  unsigned char seamless_play    : 1;
-  unsigned char interleaved      : 1;
-  unsigned char stc_discontinuity: 1;
-  unsigned char seamless_angle   : 1;
+  unsigned BITFIELD_TYPE block_mode       : 2;
+  unsigned BITFIELD_TYPE block_type       : 2;
+  unsigned BITFIELD_TYPE seamless_play    : 1;
+  unsigned BITFIELD_TYPE interleaved      : 1;
+  unsigned BITFIELD_TYPE stc_discontinuity: 1;
+  unsigned BITFIELD_TYPE seamless_angle   : 1;
  =20
-  unsigned char playback_mode    : 1;  /**< When set, enter StillMode af=
ter each VOBU */
-  unsigned char restricted       : 1;  /**< ?? drop out of fastforward? =
*/
-  unsigned char unknown2         : 6;
+  unsigned BITFIELD_TYPE playback_mode    : 1;  /**< When set, enter Sti=
llMode after each VOBU */
+  unsigned BITFIELD_TYPE restricted       : 1;  /**< ?? drop out of fast=
forward? */
+  unsigned BITFIELD_TYPE unknown2         : 6;
 #else
-  unsigned char seamless_angle   : 1;
-  unsigned char stc_discontinuity: 1;
-  unsigned char interleaved      : 1;
-  unsigned char seamless_play    : 1;
-  unsigned char block_type       : 2;
-  unsigned char block_mode       : 2;
+  unsigned BITFIELD_TYPE seamless_angle   : 1;
+  unsigned BITFIELD_TYPE stc_discontinuity: 1;
+  unsigned BITFIELD_TYPE interleaved      : 1;
+  unsigned BITFIELD_TYPE seamless_play    : 1;
+  unsigned BITFIELD_TYPE block_type       : 2;
+  unsigned BITFIELD_TYPE block_mode       : 2;
  =20
-  unsigned char unknown2         : 6;
-  unsigned char restricted       : 1;
-  unsigned char playback_mode    : 1;
+  unsigned BITFIELD_TYPE unknown2         : 6;
+  unsigned BITFIELD_TYPE restricted       : 1;
+  unsigned BITFIELD_TYPE playback_mode    : 1;
 #endif
   uint8_t still_time;
   uint8_t cell_cmd_nr;
@@ -331,65 +348,65 @@
  */
 typedef struct {
 #ifdef WORDS_BIGENDIAN
-  unsigned char zero                           : 7; /* 25-31 */
-  unsigned char video_pres_mode_change         : 1; /* 24 */
+  unsigned BITFIELD_TYPE zero                           : 7; /* 25-31 */
+  unsigned BITFIELD_TYPE video_pres_mode_change         : 1; /* 24 */
  =20
-  unsigned char karaoke_audio_pres_mode_change : 1; /* 23 */
-  unsigned char angle_change                   : 1;
-  unsigned char subpic_stream_change           : 1;
-  unsigned char audio_stream_change            : 1;
-  unsigned char pause_on                       : 1;
-  unsigned char still_off                      : 1;
-  unsigned char button_select_or_activate      : 1;
-  unsigned char resume                         : 1; /* 16 */
+  unsigned BITFIELD_TYPE karaoke_audio_pres_mode_change : 1; /* 23 */
+  unsigned BITFIELD_TYPE angle_change                   : 1;
+  unsigned BITFIELD_TYPE subpic_stream_change           : 1;
+  unsigned BITFIELD_TYPE audio_stream_change            : 1;
+  unsigned BITFIELD_TYPE pause_on                       : 1;
+  unsigned BITFIELD_TYPE still_off                      : 1;
+  unsigned BITFIELD_TYPE button_select_or_activate      : 1;
+  unsigned BITFIELD_TYPE resume                         : 1; /* 16 */
  =20
-  unsigned char chapter_menu_call              : 1; /* 15 */
-  unsigned char angle_menu_call                : 1;
-  unsigned char audio_menu_call                : 1;
-  unsigned char subpic_menu_call               : 1;
-  unsigned char root_menu_call                 : 1;
-  unsigned char title_menu_call                : 1;
-  unsigned char backward_scan                  : 1;
-  unsigned char forward_scan                   : 1; /* 8 */
+  unsigned BITFIELD_TYPE chapter_menu_call              : 1; /* 15 */
+  unsigned BITFIELD_TYPE angle_menu_call                : 1;
+  unsigned BITFIELD_TYPE audio_menu_call                : 1;
+  unsigned BITFIELD_TYPE subpic_menu_call               : 1;
+  unsigned BITFIELD_TYPE root_menu_call                 : 1;
+  unsigned BITFIELD_TYPE title_menu_call                : 1;
+  unsigned BITFIELD_TYPE backward_scan                  : 1;
+  unsigned BITFIELD_TYPE forward_scan                   : 1; /* 8 */
  =20
-  unsigned char next_pg_search                 : 1; /* 7 */
-  unsigned char prev_or_top_pg_search          : 1;
-  unsigned char time_or_chapter_search         : 1;
-  unsigned char go_up                          : 1;
-  unsigned char stop                           : 1;
-  unsigned char title_play                     : 1;
-  unsigned char chapter_search_or_play         : 1;
-  unsigned char title_or_time_play             : 1; /* 0 */
+  unsigned BITFIELD_TYPE next_pg_search                 : 1; /* 7 */
+  unsigned BITFIELD_TYPE prev_or_top_pg_search          : 1;
+  unsigned BITFIELD_TYPE time_or_chapter_search         : 1;
+  unsigned BITFIELD_TYPE go_up                          : 1;
+  unsigned BITFIELD_TYPE stop                           : 1;
+  unsigned BITFIELD_TYPE title_play                     : 1;
+  unsigned BITFIELD_TYPE chapter_search_or_play         : 1;
+  unsigned BITFIELD_TYPE title_or_time_play             : 1; /* 0 */
 #else
-  unsigned char video_pres_mode_change         : 1; /* 24 */
-  unsigned char zero                           : 7; /* 25-31 */
+  unsigned BITFIELD_TYPE video_pres_mode_change         : 1; /* 24 */
+  unsigned BITFIELD_TYPE zero                           : 7; /* 25-31 */
  =20
-  unsigned char resume                         : 1; /* 16 */
-  unsigned char button_select_or_activate      : 1;
-  unsigned char still_off                      : 1;
-  unsigned char pause_on                       : 1;
-  unsigned char audio_stream_change            : 1;
-  unsigned char subpic_stream_change           : 1;
-  unsigned char angle_change                   : 1;
-  unsigned char karaoke_audio_pres_mode_change : 1; /* 23 */
+  unsigned BITFIELD_TYPE resume                         : 1; /* 16 */
+  unsigned BITFIELD_TYPE button_select_or_activate      : 1;
+  unsigned BITFIELD_TYPE still_off                      : 1;
+  unsigned BITFIELD_TYPE pause_on                       : 1;
+  unsigned BITFIELD_TYPE audio_stream_change            : 1;
+  unsigned BITFIELD_TYPE subpic_stream_change           : 1;
+  unsigned BITFIELD_TYPE angle_change                   : 1;
+  unsigned BITFIELD_TYPE karaoke_audio_pres_mode_change : 1; /* 23 */
  =20
-  unsigned char forward_scan                   : 1; /* 8 */
-  unsigned char backward_scan                  : 1;
-  unsigned char title_menu_call                : 1;
-  unsigned char root_menu_call                 : 1;
-  unsigned char subpic_menu_call               : 1;
-  unsigned char audio_menu_call                : 1;
-  unsigned char angle_menu_call                : 1;
-  unsigned char chapter_menu_call              : 1; /* 15 */
+  unsigned BITFIELD_TYPE forward_scan                   : 1; /* 8 */
+  unsigned BITFIELD_TYPE backward_scan                  : 1;
+  unsigned BITFIELD_TYPE title_menu_call                : 1;
+  unsigned BITFIELD_TYPE root_menu_call                 : 1;
+  unsigned BITFIELD_TYPE subpic_menu_call               : 1;
+  unsigned BITFIELD_TYPE audio_menu_call                : 1;
+  unsigned BITFIELD_TYPE angle_menu_call                : 1;
+  unsigned BITFIELD_TYPE chapter_menu_call              : 1; /* 15 */
  =20
-  unsigned char title_or_time_play             : 1; /* 0 */
-  unsigned char chapter_search_or_play         : 1;
-  unsigned char title_play                     : 1;
-  unsigned char stop                           : 1;
-  unsigned char go_up                          : 1;
-  unsigned char time_or_chapter_search         : 1;
-  unsigned char prev_or_top_pg_search          : 1;
-  unsigned char next_pg_search                 : 1; /* 7 */
+  unsigned BITFIELD_TYPE title_or_time_play             : 1; /* 0 */
+  unsigned BITFIELD_TYPE chapter_search_or_play         : 1;
+  unsigned BITFIELD_TYPE title_play                     : 1;
+  unsigned BITFIELD_TYPE stop                           : 1;
+  unsigned BITFIELD_TYPE go_up                          : 1;
+  unsigned BITFIELD_TYPE time_or_chapter_search         : 1;
+  unsigned BITFIELD_TYPE prev_or_top_pg_search          : 1;
+  unsigned BITFIELD_TYPE next_pg_search                 : 1; /* 7 */
 #endif
 } ATTRIBUTE_PACKED user_ops_t;
=20
@@ -407,8 +424,8 @@
   uint16_t next_pgc_nr;
   uint16_t prev_pgc_nr;
   uint16_t goup_pgc_nr;
+  uint8_t  pg_playback_mode;
   uint8_t  still_time;
-  uint8_t  pg_playback_mode;
   uint32_t palette[16]; /* New type struct {zero_1, Y, Cr, Cb} ? */
   uint16_t command_tbl_offset;
   uint16_t program_map_offset;
@@ -419,7 +436,7 @@
   cell_playback_t *cell_playback;
   cell_position_t *cell_position;
 } ATTRIBUTE_PACKED pgc_t;
-#define PGC_SIZE 236
+#define PGC_SIZE 236U
=20
 /**
  * Program Chain Information Search Pointer.
@@ -427,19 +444,19 @@
 typedef struct {
   uint8_t  entry_id;
 #ifdef WORDS_BIGENDIAN
-  unsigned char block_mode : 2;
-  unsigned char block_type : 2;
-  unsigned char unknown1   : 4;
+  unsigned BITFIELD_TYPE block_mode : 2;
+  unsigned BITFIELD_TYPE block_type : 2;
+  unsigned BITFIELD_TYPE unknown1   : 4;
 #else
-  unsigned char unknown1   : 4;
-  unsigned char block_type : 2;
-  unsigned char block_mode : 2;
+  unsigned BITFIELD_TYPE unknown1   : 4;
+  unsigned BITFIELD_TYPE block_type : 2;
+  unsigned BITFIELD_TYPE block_mode : 2;
 #endif =20
   uint16_t ptl_id_mask;
   uint32_t pgc_start_byte;
   pgc_t *pgc;
 } ATTRIBUTE_PACKED pgci_srp_t;
-#define PGCI_SRP_SIZE 8
+#define PGCI_SRP_SIZE 8U
=20
 /**
  * Program Chain Information Table.
@@ -450,7 +467,7 @@
   uint32_t last_byte;
   pgci_srp_t *pgci_srp;
 } ATTRIBUTE_PACKED pgcit_t;
-#define PGCIT_SIZE 8
+#define PGCIT_SIZE 8U
=20
 /**
  * Menu PGCI Language Unit.
@@ -462,7 +479,7 @@
   uint32_t lang_start_byte;
   pgcit_t *pgcit;
 } ATTRIBUTE_PACKED pgci_lu_t;
-#define PGCI_LU_SIZE 8
+#define PGCI_LU_SIZE 8U
=20
 /**
  * Menu PGCI Unit Table.
@@ -473,7 +490,7 @@
   uint32_t last_byte;
   pgci_lu_t *lu;
 } ATTRIBUTE_PACKED pgci_ut_t;
-#define PGCI_UT_SIZE 8
+#define PGCI_UT_SIZE 8U
=20
 /**
  * Cell Address Information.
@@ -495,7 +512,7 @@
   uint32_t last_byte;
   cell_adr_t *cell_adr_table;  /* No explicit size given. */
 } ATTRIBUTE_PACKED c_adt_t;
-#define C_ADT_SIZE 8
+#define C_ADT_SIZE 8U
=20
 /**
  * VOBU Address Map.
@@ -504,7 +521,7 @@
   uint32_t last_byte;
   uint32_t *vobu_start_sectors;
 } ATTRIBUTE_PACKED vobu_admap_t;
-#define VOBU_ADMAP_SIZE 4
+#define VOBU_ADMAP_SIZE 4U
=20
=20
=20
@@ -560,23 +577,23 @@
=20
 typedef struct {
 #ifdef WORDS_BIGENDIAN
-  unsigned char zero_1                    : 1;
-  unsigned char multi_or_random_pgc_title : 1; /* 0: one sequential pgc =
title */
-  unsigned char jlc_exists_in_cell_cmd    : 1;
-  unsigned char jlc_exists_in_prepost_cmd : 1;
-  unsigned char jlc_exists_in_button_cmd  : 1;
-  unsigned char jlc_exists_in_tt_dom      : 1;
-  unsigned char chapter_search_or_play    : 1; /* UOP 1 */
-  unsigned char title_or_time_play        : 1; /* UOP 0 */
+  unsigned BITFIELD_TYPE zero_1                    : 1;
+  unsigned BITFIELD_TYPE multi_or_random_pgc_title : 1; /* 0: one sequen=
tial pgc title */
+  unsigned BITFIELD_TYPE jlc_exists_in_cell_cmd    : 1;
+  unsigned BITFIELD_TYPE jlc_exists_in_prepost_cmd : 1;
+  unsigned BITFIELD_TYPE jlc_exists_in_button_cmd  : 1;
+  unsigned BITFIELD_TYPE jlc_exists_in_tt_dom      : 1;
+  unsigned BITFIELD_TYPE chapter_search_or_play    : 1; /* UOP 1 */
+  unsigned BITFIELD_TYPE title_or_time_play        : 1; /* UOP 0 */
 #else
-  unsigned char title_or_time_play        : 1;
-  unsigned char chapter_search_or_play    : 1;
-  unsigned char jlc_exists_in_tt_dom      : 1;
-  unsigned char jlc_exists_in_button_cmd  : 1;
-  unsigned char jlc_exists_in_prepost_cmd : 1;
-  unsigned char jlc_exists_in_cell_cmd    : 1;
-  unsigned char multi_or_random_pgc_title : 1;
-  unsigned char zero_1                    : 1;
+  unsigned BITFIELD_TYPE title_or_time_play        : 1;
+  unsigned BITFIELD_TYPE chapter_search_or_play    : 1;
+  unsigned BITFIELD_TYPE jlc_exists_in_tt_dom      : 1;
+  unsigned BITFIELD_TYPE jlc_exists_in_button_cmd  : 1;
+  unsigned BITFIELD_TYPE jlc_exists_in_prepost_cmd : 1;
+  unsigned BITFIELD_TYPE jlc_exists_in_cell_cmd    : 1;
+  unsigned BITFIELD_TYPE multi_or_random_pgc_title : 1;
+  unsigned BITFIELD_TYPE zero_1                    : 1;
 #endif
 } ATTRIBUTE_PACKED playback_type_t;
=20
@@ -602,7 +619,7 @@
   uint32_t last_byte;
   title_info_t *title;
 } ATTRIBUTE_PACKED tt_srpt_t;
-#define TT_SRPT_SIZE 8
+#define TT_SRPT_SIZE 8U
=20
=20
 /**
@@ -621,7 +638,7 @@
   uint16_t zero_2;
   pf_level_t *pf_ptl_mai; /* table of (nr_of_vtss + 1), video_ts is firs=
t */
 } ATTRIBUTE_PACKED ptl_mait_country_t;
-#define PTL_MAIT_COUNTRY_SIZE 8
+#define PTL_MAIT_COUNTRY_SIZE 8U
=20
 /**
  * Parental Management Information Table.
@@ -632,7 +649,7 @@
   uint32_t last_byte;
   ptl_mait_country_t *countries;
 } ATTRIBUTE_PACKED ptl_mait_t;
-#define PTL_MAIT_SIZE 8
+#define PTL_MAIT_SIZE 8U
=20
 /**
  * Video Title Set Attributes.
@@ -663,8 +680,8 @@
   uint8_t  nr_of_vtstt_subp_streams;
   subp_attr_t vtstt_subp_attr[32];
 } ATTRIBUTE_PACKED vts_attributes_t;
-#define VTS_ATTRIBUTES_SIZE 542
-#define VTS_ATTRIBUTES_MIN_SIZE 356
+#define VTS_ATTRIBUTES_SIZE 542U
+#define VTS_ATTRIBUTES_MIN_SIZE 356U
=20
 /**
  * Video Title Set Attribute Table.
@@ -676,7 +693,7 @@
   vts_attributes_t *vts;
   uint32_t *vts_atrt_offsets; /* offsets table for each vts_attributes *=
/
 } ATTRIBUTE_PACKED vts_atrt_t;
-#define VTS_ATRT_SIZE 8
+#define VTS_ATRT_SIZE 8U
=20
 /**
  * Text Data. (Incomplete)
@@ -709,7 +726,7 @@
   uint32_t txtdt_start_byte;  /* prt, rel start of vmg_txtdt_mgi  */
   txtdt_t  *txtdt;
 } ATTRIBUTE_PACKED txtdt_lu_t;
-#define TXTDT_LU_SIZE 8
+#define TXTDT_LU_SIZE 8U
=20
 /**
  * Text Data Manager Information. (Incomplete)
@@ -720,7 +737,7 @@
   uint32_t last_byte;
   txtdt_lu_t *lu;
 } ATTRIBUTE_PACKED txtdt_mgi_t;
-#define TXTDT_MGI_SIZE 20
+#define TXTDT_MGI_SIZE 20U
=20
=20
 /**
@@ -812,7 +829,7 @@
   ttu_t  *title;
   uint32_t *ttu_offset; /* offset table for each ttu */
 } ATTRIBUTE_PACKED vts_ptt_srpt_t;
-#define VTS_PTT_SRPT_SIZE 8
+#define VTS_PTT_SRPT_SIZE 8U
=20
=20
 /**
@@ -830,7 +847,7 @@
   uint16_t nr_of_entries;
   map_ent_t *map_ent;
 } ATTRIBUTE_PACKED vts_tmap_t;
-#define VTS_TMAP_SIZE 4
+#define VTS_TMAP_SIZE 4U
=20
 /**
  * Time Map Table.
@@ -842,7 +859,7 @@
   vts_tmap_t *tmap;
   uint32_t *tmap_offset; /* offset table for each tmap */
 } ATTRIBUTE_PACKED vts_tmapt_t;
-#define VTS_TMAPT_SIZE 8
+#define VTS_TMAPT_SIZE 8U
=20
=20
 #if PRAGMA_PACK

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/nav_print.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/nav_print.c	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/nav_print.c	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2000, 2001, 2002, 2003 H=E5kan Hjort <d95hjort at dtek.cha=
lmers.se>
  *
@@ -26,10 +27,16 @@
 #include "config.h"
=20
 #include <stdio.h>
+
+#if defined(HAVE_INTTYPES_H)
 #include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
=20
 #include "nav_types.h"
 #include "nav_print.h"
+#include "cmd_print.h"
 #include "dvdread_internal.h"
=20
 static void print_time(dvd_time_t *dtime) {
@@ -40,10 +47,10 @@
   CHECK_VALUE((dtime->frame_u&0xf) < 0xa);
  =20
   printf("%02x:%02x:%02x.%02x",=20
-	 dtime->hour,
-	 dtime->minute,
-	 dtime->second,
-	 dtime->frame_u & 0x3f);
+         dtime->hour,
+         dtime->minute,
+         dtime->second,
+         dtime->frame_u & 0x3f);
   switch((dtime->frame_u & 0xc0) >> 6) {
   case 1:
     rate =3D "25.00";
@@ -96,7 +103,7 @@
   for(i =3D 0; i < 9; i++)
     if(nsml_agli->nsml_agl_dsta[i])
       printf("nsml_agl_c%d_dsta  0x%08x\n", i + 1,=20
-	     nsml_agli->nsml_agl_dsta[i]);
+             nsml_agli->nsml_agl_dsta[i]);
 }
=20
 static void navPrint_HL_GI(hl_gi_t *hl_gi, int *btngr_ns, int *btn_ns) {
@@ -137,8 +144,8 @@
   for(i =3D 0; i < 3; i++)
     for(j =3D 0; j < 2; j++)
       printf("btn_cqoli %d  %s_coli:  %08x\n",
-	     i, (j =3D=3D 0) ? "sl" : "ac",
-	     btn_colit->btn_coli[i][j]);
+             i, (j =3D=3D 0) ? "sl" : "ac",
+             btn_colit->btn_coli[i][j]);
 }
=20
 static void navPrint_BTNIT(btni_t *btni_table, int btngr_ns, int btn_ns)=
 {
@@ -154,21 +161,21 @@
   for(i =3D 0; i < btngr_ns; i++) {
     for(j =3D 0; j < (36 / btngr_ns); j++) {
       if(j < btn_ns) {
-	btni_t *btni =3D &btni_table[(36 / btngr_ns) * i + j];
-=09
-	printf("group %d btni %d:  ", i+1, j+1);
-	printf("btn_coln %d, auto_action_mode %d\n",
-	       btni->btn_coln, btni->auto_action_mode);
-	printf("coords   (%d, %d) .. (%d, %d)\n",
-	       btni->x_start, btni->y_start, btni->x_end, btni->y_end);
-=09
-	printf("up %d, ", btni->up);
-	printf("down %d, ", btni->down);
-	printf("left %d, ", btni->left);
-	printf("right %d\n", btni->right);
-=09
-	/* ifoPrint_COMMAND(&btni->cmd); */
-	printf("\n");
+        btni_t *btni =3D &btni_table[(36 / btngr_ns) * i + j];
+       =20
+        printf("group %d btni %d:  ", i+1, j+1);
+        printf("btn_coln %d, auto_action_mode %d\n",
+               btni->btn_coln, btni->auto_action_mode);
+        printf("coords   (%d, %d) .. (%d, %d)\n",
+               btni->x_start, btni->y_start, btni->x_end, btni->y_end);
+       =20
+        printf("up %d, ", btni->up);
+        printf("down %d, ", btni->down);
+        printf("left %d, ", btni->left);
+        printf("right %d\n", btni->right);
+       =20
+        cmdPrint_CMD(0, &btni->cmd);
+        printf("\n");
       }
     }
   }
@@ -232,14 +239,14 @@
   printf("sml_agli:\n");
   for(i =3D 0; i < 9; i++) {
     printf("agl_c%d address: 0x%08x size 0x%04x\n", i,
-	   sml_agli->data[i].address, sml_agli->data[i].size);
+           sml_agli->data[i].address, sml_agli->data[i].size);
   }
 }
=20
 static void navPrint_VOBU_SRI(vobu_sri_t *vobu_sri) {
   int i;
   int stime[19] =3D { 240, 120, 60, 20, 15, 14, 13, 12, 11,=20
-		     10,   9,  8,  7,  6,  5,  4,  3,  2, 1};
+                    10,   9,  8,  7,  6,  5,  4,  3,  2, 1};
   printf("vobu_sri:\n");
   printf("Next VOBU with Video %08x\n", vobu_sri->next_video);
   for(i =3D 0; i < 19; i++) {

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/nav_read.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/nav_read.c	2007-01-22 11:21:=
16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/nav_read.c	2007-01-28 16:48:=
11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2000, 2001, 2002, 2003 H=E5kan Hjort <d95hjort at dtek.cha=
lmers.se>
  *
@@ -20,7 +21,11 @@
=20
 #include <stdio.h>
 #include <string.h>
+#if defined(HAVE_INTTYPES_H)
 #include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
=20
 #include "bswap.h"
 #include "nav_types.h"
@@ -28,7 +33,7 @@
 #include "dvdread_internal.h"
=20
 void navRead_PCI(pci_t *pci, unsigned char *buffer) {
-  int i, j;
+  unsigned int i, j;
=20
   CHECK_VALUE(sizeof(pci_t) =3D=3D PCI_BYTES - 1); // -1 for substream i=
d
  =20
@@ -105,7 +110,7 @@
     CHECK_VALUE(pci->hli.hl_gi.btngr_ns !=3D 0);=20
   } else {
     CHECK_VALUE((pci->hli.hl_gi.btn_ns !=3D 0 && pci->hli.hl_gi.btngr_ns=
 !=3D 0)=20
-	   || (pci->hli.hl_gi.btn_ns =3D=3D 0 && pci->hli.hl_gi.btngr_ns =3D=3D=
 0));
+                || (pci->hli.hl_gi.btn_ns =3D=3D 0 && pci->hli.hl_gi.btn=
gr_ns =3D=3D 0));
   }
=20
   /* pci hli btnit */
@@ -119,28 +124,28 @@
       CHECK_VALUE(pci->hli.btnit[n].zero5 =3D=3D 0);
       CHECK_VALUE(pci->hli.btnit[n].zero6 =3D=3D 0);
      =20
-      if (j < pci->hli.hl_gi.btn_ns) {=09
-	CHECK_VALUE(pci->hli.btnit[n].x_start <=3D pci->hli.btnit[n].x_end);
-	CHECK_VALUE(pci->hli.btnit[n].y_start <=3D pci->hli.btnit[n].y_end);
-	CHECK_VALUE(pci->hli.btnit[n].up <=3D pci->hli.hl_gi.btn_ns);
-	CHECK_VALUE(pci->hli.btnit[n].down <=3D pci->hli.hl_gi.btn_ns);
-	CHECK_VALUE(pci->hli.btnit[n].left <=3D pci->hli.hl_gi.btn_ns);
-	CHECK_VALUE(pci->hli.btnit[n].right <=3D pci->hli.hl_gi.btn_ns);
-	//vmcmd_verify(pci->hli.btnit[n].cmd);
+      if (j < pci->hli.hl_gi.btn_ns) { =20
+        CHECK_VALUE(pci->hli.btnit[n].x_start <=3D pci->hli.btnit[n].x_e=
nd);
+        CHECK_VALUE(pci->hli.btnit[n].y_start <=3D pci->hli.btnit[n].y_e=
nd);
+        CHECK_VALUE(pci->hli.btnit[n].up <=3D pci->hli.hl_gi.btn_ns);
+        CHECK_VALUE(pci->hli.btnit[n].down <=3D pci->hli.hl_gi.btn_ns);
+        CHECK_VALUE(pci->hli.btnit[n].left <=3D pci->hli.hl_gi.btn_ns);
+        CHECK_VALUE(pci->hli.btnit[n].right <=3D pci->hli.hl_gi.btn_ns);
+        //vmcmd_verify(pci->hli.btnit[n].cmd);
       } else {
-	int k;
-	CHECK_VALUE(pci->hli.btnit[n].btn_coln =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].auto_action_mode =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].x_start =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].y_start =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].x_end =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].y_end =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].up =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].down =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].left =3D=3D 0);
-	CHECK_VALUE(pci->hli.btnit[n].right =3D=3D 0);
-	for (k =3D 0; k < 8; k++)
-	  CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] =3D=3D 0); //CHECK_ZERO?
+        int k;
+        CHECK_VALUE(pci->hli.btnit[n].btn_coln =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].auto_action_mode =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].x_start =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].y_start =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].x_end =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].y_end =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].up =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].down =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].left =3D=3D 0);
+        CHECK_VALUE(pci->hli.btnit[n].right =3D=3D 0);
+        for (k =3D 0; k < 8; k++)
+          CHECK_VALUE(pci->hli.btnit[n].cmd.bytes[k] =3D=3D 0); //CHECK_=
ZERO?
       }
     }
   }

Modified: trunk/DvdMenuXtractor/libdvdread/dvdread/nav_types.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/dvdread/nav_types.h	2007-01-22 11:21=
:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/dvdread/nav_types.h	2007-01-28 16:48=
:11 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 #ifndef NAV_TYPES_H_INCLUDED
 #define NAV_TYPES_H_INCLUDED
=20
@@ -29,10 +30,9 @@
  * USA
  */
=20
-#include <inttypes.h>
 #include <dvdread/ifo_types.h> /* only dvd_time_t, vm_cmd_t and user_ops=
_t */
+/* If it's ever removed add a uintX_t test. */
=20
-
 #undef ATTRIBUTE_PACKED
 #undef PRAGMA_PACK_BEGIN=20
 #undef PRAGMA_PACK_END
@@ -103,23 +103,23 @@
   uint32_t hli_e_ptm;              /**< end ptm of hli */
   uint32_t btn_se_e_ptm;           /**< end ptm of button select */
 #ifdef WORDS_BIGENDIAN
-  unsigned char zero1 : 2;          /**< reserved */
-  unsigned char btngr_ns : 2;       /**< number of button groups 1, 2 or=
 3 with 36/18/12 buttons */
-  unsigned char zero2 : 1;          /**< reserved */
-  unsigned char btngr1_dsp_ty : 3;  /**< display type of subpic stream f=
or button group 1 */
-  unsigned char zero3 : 1;          /**< reserved */
-  unsigned char btngr2_dsp_ty : 3;  /**< display type of subpic stream f=
or button group 2 */
-  unsigned char zero4 : 1;          /**< reserved */
-  unsigned char btngr3_dsp_ty : 3;  /**< display type of subpic stream f=
or button group 3 */
+  unsigned int zero1 : 2;          /**< reserved */
+  unsigned int btngr_ns : 2;       /**< number of button groups 1, 2 or =
3 with 36/18/12 buttons */
+  unsigned int zero2 : 1;          /**< reserved */
+  unsigned int btngr1_dsp_ty : 3;  /**< display type of subpic stream fo=
r button group 1 */
+  unsigned int zero3 : 1;          /**< reserved */
+  unsigned int btngr2_dsp_ty : 3;  /**< display type of subpic stream fo=
r button group 2 */
+  unsigned int zero4 : 1;          /**< reserved */
+  unsigned int btngr3_dsp_ty : 3;  /**< display type of subpic stream fo=
r button group 3 */
 #else
-  unsigned char btngr1_dsp_ty : 3;
-  unsigned char zero2 : 1;
-  unsigned char btngr_ns : 2;
-  unsigned char zero1 : 2;
-  unsigned char btngr3_dsp_ty : 3;
-  unsigned char zero4 : 1;
-  unsigned char btngr2_dsp_ty : 3;
-  unsigned char zero3 : 1;
+  unsigned int btngr1_dsp_ty : 3;
+  unsigned int zero2 : 1;
+  unsigned int btngr_ns : 2;
+  unsigned int zero1 : 2;
+  unsigned int btngr3_dsp_ty : 3;
+  unsigned int zero4 : 1;
+  unsigned int btngr2_dsp_ty : 3;
+  unsigned int zero3 : 1;
 #endif
   uint8_t btn_ofn;     /**< button offset number range 0-255 */
   uint8_t btn_ns;      /**< number of valid buttons  <=3D 36/18/12 (low =
6 bits) */ =20
@@ -166,10 +166,10 @@
=20
   unsigned int zero4            : 2;  /**< reserved */
   unsigned int down             : 6;  /**< button index when pressing do=
wn */
-  unsigned char zero5            : 2;  /**< reserved */
-  unsigned char left             : 6;  /**< button index when pressing l=
eft */
-  unsigned char zero6            : 2;  /**< reserved */
-  unsigned char right            : 6;  /**< button index when pressing r=
ight */
+  unsigned int zero5            : 2;  /**< reserved */
+  unsigned int left             : 6;  /**< button index when pressing le=
ft */
+  unsigned int zero6            : 2;  /**< reserved */
+  unsigned int right            : 6;  /**< button index when pressing ri=
ght */
 #else
   unsigned int x_end            : 10;
   unsigned int zero1            : 2;
@@ -186,10 +186,10 @@
=20
   unsigned int down             : 6;
   unsigned int zero4            : 2;
-  unsigned char left             : 6;
-  unsigned char zero5            : 2;
-  unsigned char right            : 6;
-  unsigned char zero6            : 2;
+  unsigned int left             : 6;
+  unsigned int zero5            : 2;
+  unsigned int right            : 6;
+  unsigned int zero6            : 2;
 #endif
   vm_cmd_t cmd;
 } ATTRIBUTE_PACKED btni_t;
@@ -254,8 +254,8 @@
  * Seamless Angle Infromation for one angle
  */
 typedef struct {
-    uint32_t address; /**< offset to next ILVU, high bit is before/after=
 */
-    uint16_t size;    /**< byte size of the ILVU pointed to by address *=
/
+  uint32_t address; /**< offset to next ILVU, high bit is before/after *=
/
+  uint16_t size;    /**< byte size of the ILVU pointed to by address */
 } ATTRIBUTE_PACKED sml_agl_data_t;
=20
 /**

Deleted: trunk/DvdMenuXtractor/libdvdread/libdvdread.bkl

Added: trunk/DvdMenuXtractor/libdvdread/libdvdread.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/libdvdread.proj	2007-01-22 11:21:16 =
UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/libdvdread.proj	2007-01-28 16:48:11 =
UTC (rev 1270)
@@ -0,0 +1,11 @@
+#include "*/*.proj"
+
+WORKSPACE dvdread
+{
+  USE dvdread
+  USE disc_id
+  USE filestat
+  USE ifo_dump
+  USE play_title
+  USE title_info
+}

Modified: trunk/DvdMenuXtractor/libdvdread/src/disc_id.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/src/disc_id.c	2007-01-22 11:21:16 UT=
C (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/src/disc_id.c	2007-01-28 16:48:11 UT=
C (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2000 Bj=F6rn Englund <d4bjorn at dtek.chalmers.se>,
  *                    H=E5kan Hjort <d95hjort at dtek.chalmers.se>
@@ -17,16 +18,18 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  * USA
  */
-
-#include "config.h"
=20
+#include "config.h"
+
 #include <stdio.h>
-#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#include <stdlib.h>
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
 #endif
+#include <errno.h>
+#include <string.h>
=20
-#include <dvdread/ifo_print.h>
+#include <dvdread/dvd_reader.h>
=20
 static char *program_name;
=20
@@ -38,6 +41,7 @@
 int main(int argc, char *argv[])
 {
   int i;
+  int err =3D 0;
   unsigned char disc_id[16];
   dvd_reader_t *dvd;
=20
@@ -49,21 +53,27 @@
   }
=20
   dvd =3D DVDOpen( argv[ 1 ] );
-  if( !dvd ) {
-    fprintf( stderr, "Can't open disc %s!\n", argv[ 1 ] );
-    return -1;
-  }
+  if( dvd ) {
+    if( DVDDiscID( dvd, disc_id ) =3D=3D 0) {
+      for(i =3D 0; i < 16; i++) {
+        printf( "%02x", disc_id[i] );
+      }
+      printf( "\n" );
+    } else {
+      fprintf( stderr, "Error getting disc id from disc '%s': %s\n",
+	       argv[ 1 ], strerror(errno) );
+     =20
+      err =3D -1;
+    }
=20
-  if( DVDDiscID( dvd, disc_id ) !=3D 0) {
-    fprintf( stderr, "Error getting disc id from disc %s!\n", argv[ 1 ] =
);
-    return -1;
+    DVDClose(dvd);
+  } else {
+    fprintf( stderr, "Can't open disc '%s': %s\n",
+             argv[ 1 ], strerror(errno) );
+    err =3D -1;
   }
=20
-  for(i =3D 0; i < 16; i++) {
-    printf( "%02x", disc_id[i] );
-  }
-  printf( "\n" );
-
-  return 0; =20
+  DVDFinish();
+  return err; =20
 }
=20

Added: trunk/DvdMenuXtractor/libdvdread/src/filestat.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/src/filestat.c	2007-01-22 11:21:16 U=
TC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/src/filestat.c	2007-01-28 16:48:11 U=
TC (rev 1270)
@@ -0,0 +1,182 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (C) 2006 Bj=F6rn Englund <d4bjorn at dtek.chalmers.se>
+ *=20
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ */
+
+/*
+ * This program is a demo of the DVDFileStat() call.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <string.h>
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
+#include <dvdread/dvd_reader.h>
+#include <dvdread/ifo_read.h>
+
+static char *program_name;
+
+void usage(void)
+{
+  fprintf(stderr, "Usage: %s <dvd path>\n", program_name);
+}
+
+
+void print_stat(dvd_stat_t *buf)
+{
+ =20
+  printf("size: %lld", buf->size);
+  if(buf->nr_parts > 1) {
+    int n;
+    for(n =3D 0; n < buf->nr_parts; n++) {
+      printf(", [%lld]", buf->parts_size[n]);
+    }
+  }
+}
+
+void print_size(dvd_reader_t *dvd, int titlenum,=20
+                dvd_read_domain_t dom)=20
+{
+  dvd_stat_t buf;
+  char filename[256];
+ =20
+  if(titlenum =3D=3D 0) {
+    switch(dom) {
+    case DVD_READ_INFO_FILE:
+#if defined(_CRT_SECURE_NO_DEPRECAT)
+      sprintf(filename, "VIDEO_TS.IFO");
+#else
+	  sprintf_s(filename, 256, "VIDEO_TS.IFO");
+#endif
+      break;
+    case DVD_READ_INFO_BACKUP_FILE:
+#if defined(_CRT_SECURE_NO_DEPRECAT)
+      sprintf(filename, "VIDEO_TS.BUP");
+#else
+	  sprintf_s(filename, 256, "VIDEO_TS.BUP");
+#endif
+      break;
+    case DVD_READ_MENU_VOBS:
+      sprintf(filename, "VIDEO_TS.VOB");
+      break;
+    default:
+      sprintf(filename, "illegal");
+    }
+  } else {
+    switch(dom) {
+    case DVD_READ_INFO_FILE:
+      sprintf(filename, "VTS_%02d_0.IFO", titlenum);
+      break;
+    case DVD_READ_INFO_BACKUP_FILE:
+      sprintf(filename, "VTS_%02d_0.BUP", titlenum);
+      break;
+    case DVD_READ_MENU_VOBS:
+      sprintf(filename, "VTS_%02d_0.VOB", titlenum);
+      break;
+    case DVD_READ_TITLE_VOBS:
+      sprintf(filename, "VTS_%02d_[1-9].VOB", titlenum);
+      break;
+    default:
+      sprintf(filename, "illegal");
+    }   =20
+  }
+
+  if(!DVDFileStat(dvd, titlenum, dom, &buf)) {
+    printf("\n%s: ", filename);
+    print_stat(&buf);
+  } else {
+    fprintf(stderr, "stat(%s): %s\n", filename, strerror(errno));
+  }
+}
+
+
+int main(int argc, char *argv[])
+{
+  //int i;
+  int err =3D 0;
+
+  dvd_reader_t *dvd;
+
+  program_name =3D argv[0];
+ =20
+  if(argc !=3D 2) {
+    usage();
+    return 1;
+  }
+
+  dvd =3D DVDOpen( argv[ 1 ] );
+
+  if( dvd ) {
+    ifo_handle_t *vmg_ifo;
+    int title_sets;
+    //dvd_stat_t buf;
+    int n;
+
+
+    vmg_ifo =3D ifoOpen( dvd, 0);
+    if(!vmg_ifo) {
+      return 1;
+    }
+
+    title_sets =3D vmg_ifo->vmgi_mat->vmg_nr_of_title_sets;
+   =20
+    ifoClose(vmg_ifo);
+
+    // VIDEO_TS.IFO
+    print_size(dvd, 0, DVD_READ_INFO_FILE);
+    // VIDEO_TS.VOB
+    print_size(dvd, 0, DVD_READ_MENU_VOBS);
+    // VIDEO_TS.BUP
+    print_size(dvd, 0, DVD_READ_INFO_BACKUP_FILE);
+
+    for(n =3D 0; n < title_sets; n++) {
+      // foreach titleset
+      //  VTS_??_0.IFO
+      print_size(dvd, n+1, DVD_READ_INFO_FILE);
+      //  VTS_??_0.VOB
+      print_size(dvd, n+1, DVD_READ_MENU_VOBS);
+      //  VTS_??_[1-9].VOB
+      print_size(dvd, n+1, DVD_READ_TITLE_VOBS);
+      //  VTS_??_0.BUP
+      print_size(dvd, n+1, DVD_READ_INFO_BACKUP_FILE);
+    }
+    printf("\n");
+    DVDClose(dvd);
+  } else {
+    fprintf( stderr, "Can't open disc '%s': %s\n",
+             argv[ 1 ], strerror(errno) );
+    err =3D -1;
+  }
+
+  DVDFinish();
+
+  return err; =20
+}
+

Modified: trunk/DvdMenuXtractor/libdvdread/src/ifo_dump.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/src/ifo_dump.c	2007-01-22 11:21:16 U=
TC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/src/ifo_dump.c	2007-01-28 16:48:11 U=
TC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2000 Bj=F6rn Englund <d4bjorn at dtek.chalmers.se>,
  *                    H=E5kan Hjort <d95hjort at dtek.chalmers.se>
@@ -17,15 +18,22 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  * USA
  */
-
-#include "config.h"
=20
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#if defined(HAVE_UNISTD_H)
+#include <unistd.h>
 #endif
=20
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
+#include <dvdread/dvd_reader.h>
 #include <dvdread/ifo_print.h>
=20
 static char *program_name;
@@ -52,7 +60,9 @@
   }
=20
   ifoPrint( dvd, atoi( argv[ 2 ] ) );
+  DVDClose(dvd);
=20
+  DVDFinish(); //to keep memory checkers from complaining=20
   return 0; =20
 }
=20

Modified: trunk/DvdMenuXtractor/libdvdread/src/play_title.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/src/play_title.c	2007-01-22 11:21:16=
 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/src/play_title.c	2007-01-28 16:48:11=
 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2001 Billy Biggs <vektor at dumbterm.net>.
  *
@@ -16,10 +17,18 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
=20
+#include "config.h"
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
=20
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
 #include <dvdread/dvd_reader.h>
 #include <dvdread/ifo_types.h>
 #include <dvdread/ifo_read.h>
@@ -287,6 +296,7 @@
     ifoClose( vmg_file );
     DVDCloseFile( title );
     DVDClose( dvd );
+    DVDFinish();
     return 0;
 }
=20

Added: trunk/DvdMenuXtractor/libdvdread/src/src.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/src/src.proj	2007-01-22 11:21:16 UTC=
 (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/src/src.proj	2007-01-28 16:48:11 UTC=
 (rev 1270)
@@ -0,0 +1,51 @@
+#include "*/*.proj"
+
+CON disc_id
+{
+  USE dvdread
+
+  SOURCE disc_id.c
+ =20
+  INCLUDE(TARGET_WIN) ../win32
+  INCLUDE ..
+}
+
+CON filestat
+{
+  USE dvdread
+
+  SOURCE filestat.c
+ =20
+  INCLUDE(TARGET_WIN) ../win32
+  INCLUDE ..
+}
+
+CON ifo_dump
+{
+  USE dvdread
+
+  SOURCE ifo_dump.c
+ =20
+  INCLUDE(TARGET_WIN) ../win32
+  INCLUDE ..
+}
+
+CON play_title
+{
+  USE dvdread
+
+  SOURCE play_title.c
+ =20
+  INCLUDE(TARGET_WIN) ../win32
+  INCLUDE ..
+}
+
+CON title_info
+{
+  USE dvdread
+
+  SOURCE title_info.c
+ =20
+  INCLUDE(TARGET_WIN) ../win32
+  INCLUDE ..
+}

Modified: trunk/DvdMenuXtractor/libdvdread/src/title_info.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/src/title_info.c	2007-01-22 11:21:16=
 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/src/title_info.c	2007-01-28 16:48:11=
 UTC (rev 1270)
@@ -1,3 +1,4 @@
+/* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
 /*
  * Copyright (C) 2001 Billy Biggs <vektor at dumbterm.net>,
  *                    H=E5kan Hjort <d95hjort at dtek.chalmers.se>
@@ -17,14 +18,20 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
=20
+#include "config.h"
+
 #include <stdio.h>
=20
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
 #include <dvdread/dvd_reader.h>
 #include <dvdread/ifo_types.h>
 #include <dvdread/ifo_read.h>
=20
-void myfprintf(FILE * f, const char * format, ...){}
-
 int main( int argc, char **argv )
 {
     dvd_reader_t *dvd;
@@ -88,14 +95,10 @@
             cur_pgc =3D vts_file->vts_pgcit->pgci_srp[ pgcnum - 1 ].pgc;
             start_cell =3D cur_pgc->program_map[ pgn - 1 ] - 1;
 =09
-            printf( "\tChapter %3d [PGC %2d, PG %2d] starts at Cell %2d =
[sector %x-%x] Duration: %2d:%2d:%2d\n",
+            printf( "\tChapter %3d [PGC %2d, PG %2d] starts at Cell %2d =
[sector %x-%x]\n",
                     j, pgcnum, pgn, start_cell,
                     cur_pgc->cell_playback[ start_cell ].first_sector,
-                    cur_pgc->cell_playback[ start_cell ].last_sector,
-                    (unsigned int)cur_pgc->playback_time.hour,
-                    (unsigned int)cur_pgc->playback_time.minute,
-                    (unsigned int)cur_pgc->playback_time.second
-            );
+                    cur_pgc->cell_playback[ start_cell ].last_sector );
         }
=20
         ifoClose( vts_file );
@@ -103,6 +106,7 @@
=20
     ifoClose( ifo_file );
     DVDClose( dvd );
+    DVDFinish();
     return 0;
 }
=20

Modified: trunk/DvdMenuXtractor/libdvdread/win32/config.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/win32/config.h	2007-01-22 11:21:16 U=
TC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/win32/config.h	2007-01-28 16:48:11 U=
TC (rev 1270)
@@ -1,4 +1,4 @@
-/* config.h.in.  Generated from configure.in by autoheader.  */
+/* config.h.  Generated manually from config.h.in */
=20
 /* Define to 1 if you have the <byteswap.h> header file. */
 #undef HAVE_BYTESWAP_H
@@ -10,27 +10,25 @@
 #undef HAVE_DVDCSS_DVDCSS_H
=20
 /* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
+#define HAVE_INTTYPES_H 1
=20
 /* Define to 1 if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
-
-#define HAVE_MEMCPY 1
+#define HAVE_LIMITS_H 1
=20
 /* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
+#define HAVE_MEMORY_H 1
=20
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
=20
 /* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
+#define HAVE_STDLIB_H 1
=20
 /* Define to 1 if you have the <strings.h> header file. */
 #undef HAVE_STRINGS_H
=20
 /* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
+#define HAVE_STRING_H 1
=20
 /* Define to 1 if you have the <sys/bswap.h> header file. */
 #undef HAVE_SYS_BSWAP_H
@@ -38,9 +36,6 @@
 /* Define to 1 if you have the <sys/endian.h> header file. */
 #undef HAVE_SYS_ENDIAN_H
=20
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#undef HAVE_SYS_IOCTL_H
-
 /* Define to 1 if you have the <sys/param.h> header file. */
 #undef HAVE_SYS_PARAM_H
=20
@@ -50,44 +45,35 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
=20
+/* Define to 1 if the system has the type `uintptr_t'. */
+#define HAVE_UINTPTR_T 1
+
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
=20
 /* Name of package */
-#undef PACKAGE
+#define PACKAGE libdvdread-1.9.7
=20
 /* Define to the address where bug reports for this package should be se=
nt. */
 #undef PACKAGE_BUGREPORT
=20
 /* Define to the full name of this package. */
-#undef PACKAGE_NAME
+#define PACKAGE_NAME libdvdread
=20
 /* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
+#define PACKAGE_STRING libdvdread-1.9.7
=20
 /* Define to the one symbol short name of this package. */
 #undef PACKAGE_TARNAME
=20
 /* Define to the version of this package. */
-#undef PACKAGE_VERSION
+#define PACKAGE_VERSION 1.9.7
=20
-/* The size of a `char', as computed by sizeof. */
-#undef SIZEOF_CHAR
-
-/* The size of a `int', as computed by sizeof. */
-#undef SIZEOF_INT
-
-/* The size of a `long long', as computed by sizeof. */
-#undef SIZEOF_LONG_LONG
-
-/* The size of a `short', as computed by sizeof. */
-#undef SIZEOF_SHORT
-
 /* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
+#define STDC_HEADERS 1
=20
 /* Version number of package */
-#undef VERSION
+#define VERSION 1.9.7
=20
 /* Define to 1 if your processor stores words with the most significant =
byte
    first (like Motorola and SPARC, unlike Intel and VAX). */
@@ -97,19 +83,13 @@
 #undef __DARWIN__
=20
 /* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
+//#undef const
=20
-/* Define as `__inline' if that's what the C compiler calls it, or to no=
thing
-   if it is not supported. */
-#define inline
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name. =
 */
+#ifndef __cplusplus
+#define inline __inline
+#endif
=20
 /* Define to `unsigned' if <sys/types.h> does not define. */
-/* #undef size_t */
-
-#define _POSIX_ /* for PATH_MAX */
-#include <limits.h>
-#undef _POSIX_
-
-#ifndef LOG_ERROR
-#define LOG_ERROR fprintf
-#endif
+//#undef size_t

Modified: trunk/DvdMenuXtractor/libdvdread/win32/dirent.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/win32/dirent.c	2007-01-22 11:21:16 U=
TC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/win32/dirent.c	2007-01-28 16:48:11 U=
TC (rev 1270)
@@ -92,7 +92,7 @@
   if (nd->dd_name[0] !=3D _T ('\0') &&
       nd->dd_name[_tcslen (nd->dd_name) - 1] !=3D _T ('/') &&
       nd->dd_name[_tcslen (nd->dd_name) - 1] !=3D _T ('\\')) {
-    _tcscat (nd->dd_name, SLASH);
+		  _tcscat_s (nd->dd_name, MAX_PATH, SLASH);
   }
=20
   /* Add on the search pattern */

Modified: trunk/DvdMenuXtractor/libdvdread/win32/gtchar.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/win32/gtchar.h	2007-01-22 11:21:16 U=
TC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/win32/gtchar.h	2007-01-28 16:48:11 U=
TC (rev 1270)
@@ -111,9 +111,11 @@
 #define	_ttoi		_wtoi
 #define	_ttol		_wtol
 #define	_tcscat		wcscat
+#define	_tcscat_s	wcscat_s
 #define _tcschr		wcschr
 #define _tcscmp		wcscmp
 #define _tcscpy		wcscpy
+#define _tcscpy_s	wcscpy_s
 #define _tcscspn	wcscspn
 #define	_tcslen		wcslen
 #define	_tcsncat	wcsncat
@@ -287,9 +289,11 @@
 #define	_ttoi		atoi
 #define	_ttol		atol
 #define	_tcscat		strcat
+#define	_tcscat_s	strcat_s
 #define _tcschr		strchr
 #define _tcscmp		strcmp
 #define _tcscpy		strcpy
+#define _tcscpy_s	strcpy_s
 #define _tcscspn	strcspn
 #define	_tcslen		strlen
 #define	_tcsncat	strncat

Modified: trunk/DvdMenuXtractor/libdvdread/win32/inttypes.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/win32/inttypes.h	2007-01-22 11:21:16=
 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/win32/inttypes.h	2007-01-28 16:48:11=
 UTC (rev 1270)
@@ -1,44 +1,303 @@
-#ifndef _LOCAL_INTTYPES_H_
-#define _LOCAL_INTTYPES_H_
+// ISO C9x  compliant inttypes.h for Miscrosoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124=20
+//=20
+//  Copyright (c) 2006 Alexander Chemeris
+//=20
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions ar=
e met:
+//=20
+//   1. Redistributions of source code must retain the above copyright n=
otice,
+//      this list of conditions and the following disclaimer.
+//=20
+//   2. Redistributions in binary form must reproduce the above copyrigh=
t
+//      notice, this list of conditions and the following disclaimer in =
the
+//      documentation and/or other materials provided with the distribut=
ion.
+//=20
+//   3. The name of the author may be used to endorse or promote product=
s
+//      derived from this software without specific prior written permis=
sion.
+//=20
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL=
,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMI=
TED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PR=
OFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILI=
TY,=20
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE =
OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN I=
F
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//=20
+////////////////////////////////////////////////////////////////////////=
///////
=20
-
-#if defined(WIN32)
-#include <windows.h>
-
-typedef unsigned char uint8_t;
-typedef unsigned short int uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned __int64 uint64_t;
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
=20
-typedef unsigned int ssize_t;
-typedef __int64 int64_t;
-typedef int int32_t;
-typedef short int16_t;
+#ifndef _MSC_INTTYPES_H_ // [
+#define _MSC_INTTYPES_H_
=20
-#define strcasecmp(x,y)    stricmp(x,y)
-#define strncasecmp(x,y,z) strnicmp(x,y,z)
+#if _MSC_VER > 1000
+#pragma once
+#endif
=20
-#ifndef S_ISREG
-#define S_ISREG(mode) (0)
+#include "stdint.h"
+
+#ifdef __cplusplus
+extern "C" {
 #endif
-#ifndef S_ISDIR
-#define S_ISDIR(mode) ((mode)&_S_IFDIR)
-#endif
-#ifndef S_ISCHR
-#define S_ISCHR(mode) (0)
-#endif
-#ifndef S_ISSOCK
-#define S_ISSOCK(x) (0)
-#endif
-#ifndef S_ISBLK
-#define S_ISBLK(x) (0)
-#endif
=20
-#define dlclose(x)	FreeLibrary(x)
-#define dlsym(x,y)	GetProcAddress(x,y)
+// 7.8 Format conversion of integer types
=20
-#else /* !WIN32 */
-#include <inttypes.h>
-#endif /* !WIN32 */
+typedef struct {
+   intmax_t quot;
+   intmax_t rem;
+} imaxdiv_t;
=20
-#endif /* _LOCAL_INTTYPES_H_ */
+// 7.8.1 Macros for format specifiers
+
+// The fprintf macros for signed integers are:
+#define PRId8       "d"
+#define PRIi8       "i"
+#define PRIdLEAST8  "d"
+#define PRIiLEAST8  "i"
+#define PRIdFAST8   "d"
+#define PRIiFAST8   "i"
+
+#define PRId16       "hd"
+#define PRIi16       "hi"
+#define PRIdLEAST16  "hd"
+#define PRIiLEAST16  "hi"
+#define PRIdFAST16   "hd"
+#define PRIiFAST16   "hi"
+
+#define PRId32       "I32d"
+#define PRIi32       "I32i"
+#define PRIdLEAST32  "I32d"
+#define PRIiLEAST32  "I32i"
+#define PRIdFAST32   "I32d"
+#define PRIiFAST32   "I32i"
+
+#define PRId64       "I64d"
+#define PRIi64       "I64i"
+#define PRIdLEAST64  "I64d"
+#define PRIiLEAST64  "I64i"
+#define PRIdFAST64   "I64d"
+#define PRIiFAST64   "I64i"
+
+#define PRIdMAX     "I64d"
+#define PRIiMAX     "I64i"
+
+#define PRIdPTR     "Id"
+#define PRIiPTR     "Ii"
+
+// The fprintf macros for unsigned integers are:
+#define PRIo8       "o"
+#define PRIu8       "u"
+#define PRIx8       "x"
+#define PRIX8       "X"
+#define PRIoLEAST8  "o"
+#define PRIuLEAST8  "u"
+#define PRIxLEAST8  "x"
+#define PRIXLEAST8  "X"
+#define PRIoFAST8   "o"
+#define PRIuFAST8   "u"
+#define PRIxFAST8   "x"
+#define PRIXFAST8   "X"
+
+#define PRIo16       "ho"
+#define PRIu16       "hu"
+#define PRIx16       "hx"
+#define PRIX16       "hX"
+#define PRIoLEAST16  "ho"
+#define PRIuLEAST16  "hu"
+#define PRIxLEAST16  "hx"
+#define PRIXLEAST16  "hX"
+#define PRIoFAST16   "ho"
+#define PRIuFAST16   "hu"
+#define PRIxFAST16   "hx"
+#define PRIXFAST16   "hX"
+
+#define PRIo32       "I32o"
+#define PRIu32       "I32u"
+#define PRIx32       "I32x"
+#define PRIX32       "I32X"
+#define PRIoLEAST32  "I32o"
+#define PRIuLEAST32  "I32u"
+#define PRIxLEAST32  "I32x"
+#define PRIXLEAST32  "I32X"
+#define PRIoFAST32   "I32o"
+#define PRIuFAST32   "I32u"
+#define PRIxFAST32   "I32x"
+#define PRIXFAST32   "I32X"
+
+#define PRIo64       "I64o"
+#define PRIu64       "I64u"
+#define PRIx64       "I64x"
+#define PRIX64       "I64X"
+#define PRIoLEAST64  "I64o"
+#define PRIuLEAST64  "I64u"
+#define PRIxLEAST64  "I64x"
+#define PRIXLEAST64  "I64X"
+#define PRIoFAST64   "I64o"
+#define PRIuFAST64   "I64u"
+#define PRIxFAST64   "I64x"
+#define PRIXFAST64   "I64X"
+
+#define PRIoMAX     "I64o"
+#define PRIuMAX     "I64u"
+#define PRIxMAX     "I64x"
+#define PRIXMAX     "I64X"
+
+#define PRIoPTR     "Io"
+#define PRIuPTR     "Iu"
+#define PRIxPTR     "Ix"
+#define PRIXPTR     "IX"
+
+// The fscanf macros for signed integers are:
+#define SCNd8       "d"
+#define SCNi8       "i"
+#define SCNdLEAST8  "d"
+#define SCNiLEAST8  "i"
+#define SCNdFAST8   "d"
+#define SCNiFAST8   "i"
+
+#define SCNd16       "hd"
+#define SCNi16       "hi"
+#define SCNdLEAST16  "hd"
+#define SCNiLEAST16  "hi"
+#define SCNdFAST16   "hd"
+#define SCNiFAST16   "hi"
+
+#define SCNd32       "ld"
+#define SCNi32       "li"
+#define SCNdLEAST32  "ld"
+#define SCNiLEAST32  "li"
+#define SCNdFAST32   "ld"
+#define SCNiFAST32   "li"
+
+#define SCNd64       "I64d"
+#define SCNi64       "I64i"
+#define SCNdLEAST64  "I64d"
+#define SCNiLEAST64  "I64i"
+#define SCNdFAST64   "I64d"
+#define SCNiFAST64   "I64i"
+
+#define SCNdMAX     "I64d"
+#define SCNiMAX     "I64i"
+
+#ifdef _WIN64 // [
+#  define SCNdPTR     "I64d"
+#  define SCNiPTR     "I64i"
+#else  // _WIN64 ][
+#  define SCNdPTR     "ld"
+#  define SCNiPTR     "li"
+#endif  // _WIN64 ]
+
+// The fscanf macros for unsigned integers are:
+#define SCNo8       "o"
+#define SCNu8       "u"
+#define SCNx8       "x"
+#define SCNX8       "X"
+#define SCNoLEAST8  "o"
+#define SCNuLEAST8  "u"
+#define SCNxLEAST8  "x"
+#define SCNXLEAST8  "X"
+#define SCNoFAST8   "o"
+#define SCNuFAST8   "u"
+#define SCNxFAST8   "x"
+#define SCNXFAST8   "X"
+
+#define SCNo16       "ho"
+#define SCNu16       "hu"
+#define SCNx16       "hx"
+#define SCNX16       "hX"
+#define SCNoLEAST16  "ho"
+#define SCNuLEAST16  "hu"
+#define SCNxLEAST16  "hx"
+#define SCNXLEAST16  "hX"
+#define SCNoFAST16   "ho"
+#define SCNuFAST16   "hu"
+#define SCNxFAST16   "hx"
+#define SCNXFAST16   "hX"
+
+#define SCNo32       "lo"
+#define SCNu32       "lu"
+#define SCNx32       "lx"
+#define SCNX32       "lX"
+#define SCNoLEAST32  "lo"
+#define SCNuLEAST32  "lu"
+#define SCNxLEAST32  "lx"
+#define SCNXLEAST32  "lX"
+#define SCNoFAST32   "lo"
+#define SCNuFAST32   "lu"
+#define SCNxFAST32   "lx"
+#define SCNXFAST32   "lX"
+
+#define SCNo64       "I64o"
+#define SCNu64       "I64u"
+#define SCNx64       "I64x"
+#define SCNX64       "I64X"
+#define SCNoLEAST64  "I64o"
+#define SCNuLEAST64  "I64u"
+#define SCNxLEAST64  "I64x"
+#define SCNXLEAST64  "I64X"
+#define SCNoFAST64   "I64o"
+#define SCNuFAST64   "I64u"
+#define SCNxFAST64   "I64x"
+#define SCNXFAST64   "I64X"
+
+#define SCNoMAX     "I64o"
+#define SCNuMAX     "I64u"
+#define SCNxMAX     "I64x"
+#define SCNXMAX     "I64X"
+
+#ifdef _WIN64 // [
+#  define SCNoPTR     "I64o"
+#  define SCNuPTR     "I64u"
+#  define SCNxPTR     "I64x"
+#  define SCNXPTR     "I64X"
+#else  // _WIN64 ][
+#  define SCNoPTR     "lo"
+#  define SCNuPTR     "lu"
+#  define SCNxPTR     "lx"
+#  define SCNXPTR     "lX"
+#endif  // _WIN64 ]
+
+// 7.8.2 Functions for greatest-width integer types
+
+// 7.8.2.1 The imaxabs function
+#define imaxabs _abs64
+
+// 7.8.2.2 The imaxdiv function
+
+// This is modified version of div() function from Microsoft's div.c fou=
nd
+// in %MSVC.NET%\crt\src\div.c
+static _inline imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
+{
+   imaxdiv_t result;
+
+   result.quot =3D numer / denom;
+   result.rem =3D numer % denom;
+
+   if (numer < 0 && result.rem > 0) {
+      // did division wrong; must fix up
+      ++result.quot;
+      result.rem -=3D denom;
+   }
+
+   return result;
+}
+
+// 7.8.2.3 The strtoimax and strtoumax functions
+#define strtoimax _strtoi64
+#define strtoumax _strtoui64
+
+// 7.8.2.4 The wcstoimax and wcstoumax functions
+#define wcstoimax _wcstoi64
+#define wcstoumax _wcstoui64
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _MSC_INTTYPES_H_ ]

Deleted: trunk/DvdMenuXtractor/libdvdread/win32/libdvdread.vcproj

Added: trunk/DvdMenuXtractor/libdvdread/win32/posix.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/win32/posix.h	2007-01-22 11:21:16 UT=
C (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/win32/posix.h	2007-01-28 16:48:11 UT=
C (rev 1270)
@@ -0,0 +1,39 @@
+#ifndef _MSC_VER
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif
+
+#ifndef _MSC_POSIX_H_
+#define _MSC_POSIX_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <sys/stat.h>
+#ifndef S_ISREG
+#define S_ISREG(mode) (0)
+#endif
+#ifndef S_ISDIR
+#define S_ISDIR(mode) ((mode)&_S_IFDIR)
+#endif
+#ifndef S_ISCHR
+#define S_ISCHR(mode) (0)
+#endif
+#ifndef S_ISSOCK
+#define S_ISSOCK(x) (0)
+#endif
+#ifndef S_ISBLK
+#define S_ISBLK(x) (0)
+#endif
+
+#include <stdlib.h>
+#define strcasecmp(x,y)     stricmp(x,y)
+#define strncasecmp(x,y,z)  strnicmp(x,y,z)
+
+#define PATH_MAX _MAX_PATH
+
+#include <windows.h>
+#define dlclose(x)      FreeLibrary(x)
+#define dlsym(x,y)      GetProcAddress(x,y)
+
+#endif // _MSC_POSIX_H_

Added: trunk/DvdMenuXtractor/libdvdread/win32/stdint.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/win32/stdint.h	2007-01-22 11:21:16 U=
TC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/win32/stdint.h	2007-01-28 16:48:11 U=
TC (rev 1270)
@@ -0,0 +1,208 @@
+// ISO C9x  compliant stdint.h for Miscrosoft Visual Studio
+// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124=20
+//=20
+//  Copyright (c) 2006 Alexander Chemeris
+//=20
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions ar=
e met:
+//=20
+//   1. Redistributions of source code must retain the above copyright n=
otice,
+//      this list of conditions and the following disclaimer.
+//=20
+//   2. Redistributions in binary form must reproduce the above copyrigh=
t
+//      notice, this list of conditions and the following disclaimer in =
the
+//      documentation and/or other materials provided with the distribut=
ion.
+//=20
+//   3. The name of the author may be used to endorse or promote product=
s
+//      derived from this software without specific prior written permis=
sion.
+//=20
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR =
IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. =
IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL=
,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMI=
TED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PR=
OFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILI=
TY,=20
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE =
OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN I=
F
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//=20
+////////////////////////////////////////////////////////////////////////=
///////
+
+#ifndef _MSC_VER // [
+#error "Use this header only with Microsoft Visual C++ compilers!"
+#endif // _MSC_VER ]
+
+#ifndef _MSC_STDINT_H_ // [
+#define _MSC_STDINT_H_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif
+
+#include <BaseTsd.h>
+#include <limits.h>
+#include <wchar.h>
+
+// 7.18.1 Integer types
+
+// 7.18.1.1 Exact-width integer types
+typedef signed __int8     int8_t;
+typedef signed __int16    int16_t;
+typedef signed __int32    int32_t;
+typedef signed __int64    int64_t;
+typedef unsigned __int8   uint8_t;
+typedef unsigned __int16  uint16_t;
+typedef unsigned __int32  uint32_t;
+typedef unsigned __int64  uint64_t;
+
+// 7.18.1.2 Minimum-width integer types
+typedef int8_t    int_least8_t;
+typedef int16_t   int_least16_t;
+typedef int32_t   int_least32_t;
+typedef int64_t   int_least64_t;
+typedef uint8_t   uint_least8_t;
+typedef uint16_t  uint_least16_t;
+typedef uint32_t  uint_least32_t;
+typedef uint64_t  uint_least64_t;
+
+// 7.18.1.3 Fastest minimum-width integer types
+typedef int8_t    int_fast8_t;
+typedef int16_t   int_fast16_t;
+typedef int32_t   int_fast32_t;
+typedef int64_t   int_fast64_t;
+typedef uint8_t   uint_fast8_t;
+typedef uint16_t  uint_fast16_t;
+typedef uint32_t  uint_fast32_t;
+typedef uint64_t  uint_fast64_t;
+
+// 7.18.1.4 Integer types capable of holding object pointers
+typedef INT_PTR   intptr_t;
+typedef UINT_PTR  uintptr_t;
+
+// 7.18.1.5 Greatest-width integer types
+typedef int64_t   intmax_t;
+typedef uint64_t  uintmax_t;
+
+
+// 7.18.2 Limits of specified-width integer types
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [   See foo=
tnote 220 at page 257 and footnote 221 at page 259
+
+// 7.18.2.1 Limits of exact-width integer types
+#define INT8_MIN     _I8_MIN
+#define INT8_MAX     _I8_MAX
+#define INT16_MIN    _I16_MIN
+#define INT16_MAX    _I16_MAX
+#define INT32_MIN    _I32_MIN
+#define INT32_MAX    _I32_MAX
+#define INT64_MIN    _I64_MIN
+#define INT64_MAX    _I64_MAX
+#define UINT8_MAX    _UI8_MAX
+#define UINT16_MAX   _UI16_MAX
+#define UINT32_MAX   _UI32_MAX
+#define UINT64_MAX   _UI64_MAX
+
+// 7.18.2.2 Limits of minimum-width integer types
+#define INT_LEAST8_MIN    INT8_MIN
+#define INT_LEAST8_MAX    INT8_MAX
+#define INT_LEAST16_MIN   INT16_MIN
+#define INT_LEAST16_MAX   INT16_MAX
+#define INT_LEAST32_MIN   INT32_MIN
+#define INT_LEAST32_MAX   INT32_MAX
+#define INT_LEAST64_MIN   INT64_MIN
+#define INT_LEAST64_MAX   INT64_MAX
+#define UINT_LEAST8_MAX   UINT8_MAX
+#define UINT_LEAST16_MAX  UINT16_MAX
+#define UINT_LEAST32_MAX  UINT32_MAX
+#define UINT_LEAST64_MAX  UINT64_MAX
+
+// 7.18.2.3 Limits of fastest minimum-width integer types
+#define INT_FAST8_MIN    INT8_MIN
+#define INT_FAST8_MAX    INT8_MAX
+#define INT_FAST16_MIN   INT16_MIN
+#define INT_FAST16_MAX   INT16_MAX
+#define INT_FAST32_MIN   INT32_MIN
+#define INT_FAST32_MAX   INT32_MAX
+#define INT_FAST64_MIN   INT64_MIN
+#define INT_FAST64_MAX   INT64_MAX
+#define UINT_FAST8_MAX   UINT8_MAX
+#define UINT_FAST16_MAX  UINT16_MAX
+#define UINT_FAST32_MAX  UINT32_MAX
+#define UINT_FAST64_MAX  UINT64_MAX
+
+// 7.18.2.4 Limits of integer types capable of holding object pointers
+#ifdef _WIN64 // [
+#  define INTPTR_MIN   INT64_MIN
+#  define INTPTR_MAX   INT64_MAX
+#  define UINTPTR_MAX  UINT64_MAX
+#else // _WIN64 ][
+#  define INTPTR_MIN   INT32_MIN
+#  define INTPTR_MAX   INT32_MAX
+#  define UINTPTR_MAX  UINT32_MAX
+#endif // _WIN64 ]
+
+// 7.18.2.5 Limits of greatest-width integer types
+#define INTMAX_MIN   INT64_MIN
+#define INTMAX_MAX   INT64_MAX
+#define UINTMAX_MAX  UINT64_MAX
+
+// 7.18.3 Limits of other integer types
+
+#ifdef _WIN64 // [
+#  define PTRDIFF_MIN  _I64_MIN
+#  define PTRDIFF_MAX  _I64_MAX
+#else  // _WIN64 ][
+#  define PTRDIFF_MIN  _I32_MIN
+#  define PTRDIFF_MAX  _I32_MAX
+#endif  // _WIN64 ]
+
+#define SIG_ATOMIC_MIN  INT_MIN
+#define SIG_ATOMIC_MAX  INT_MAX
+
+#ifndef SIZE_MAX // [
+#  ifdef _WIN64 // [
+#     define SIZE_MAX  _UI64_MAX
+#  else // _WIN64 ][
+#     define SIZE_MAX  _UI32_MAX
+#  endif // _WIN64 ]
+#endif // SIZE_MAX ]
+
+// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
+#ifndef WCHAR_MIN // [
+#  define WCHAR_MIN  0
+#endif  // WCHAR_MIN ]
+#ifndef WCHAR_MAX // [
+#  define WCHAR_MAX  _UI16_MAX
+#endif  // WCHAR_MAX ]
+
+#define WINT_MIN  0
+#define WINT_MAX  _UI16_MAX
+
+#endif // __STDC_LIMIT_MACROS ]
+
+
+// 7.18.4 Limits of other integer types
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [   See =
footnote 224 at page 260
+
+// 7.18.4.1 Macros for minimum-width integer constants
+
+#define INT8_C(val)  val
+#define INT16_C(val) val
+#define INT32_C(val) val##L
+#define INT64_C(val) val##i64
+
+#define UINT8_C(val)  val
+#define UINT16_C(val) val
+#define UINT32_C(val) val##UL
+#define UINT64_C(val) val##Ui64
+
+// 7.18.4.2 Macros for greatest-width integer constants
+#define INTMAX_C   INT64_C
+#define UINTMAX_C  UINT64_C
+
+#endif // __STDC_CONSTANT_MACROS ]
+
+
+#endif // _MSC_STDINT_H_ ]

Added: trunk/DvdMenuXtractor/libdvdread/win32/win32.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/libdvdread/win32/win32.proj	2007-01-22 11:21:16=
 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/libdvdread/win32/win32.proj	2007-01-28 16:48:11=
 UTC (rev 1270)
@@ -0,0 +1,16 @@
+#include "*/*.proj"
+
+GROUP posixmsvc
+{
+  SOURCE dirent.c
+
+  HEADER dirent.h
+  HEADER gtchar.h
+  HEADER posix.h
+}
+
+GROUP c99msvc
+{
+  HEADER inttypes.h
+  HEADER stdint.h
+}

Added: trunk/DvdMenuXtractor/logtextedit.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/logtextedit.cpp	2007-01-22 11:21:16 UTC (rev 12=
69)
+++ trunk/DvdMenuXtractor/logtextedit.cpp	2007-01-28 16:48:11 UTC (rev 12=
70)
@@ -0,0 +1,46 @@
+#include <QDate>
+#include <QFile>
+#include <QTextStream>
+#include "logtextedit.h"
+#include "outputreader.h"
+
+LogTextEdit::LogTextEdit(QWidget *parent)
+	: QTextEdit(parent), notifier_(OutputReader::instance())
+{
+	// set flags
+	setReadOnly(true);
+	setLineWrapMode(QTextEdit::NoWrap);
+
+	if (!notifier_.redirect())
+	{
+		setHtml("ERROR: Could not start output redirection");
+		notifier_.cancelRedirect();
+		return;
+	}
+
+	// setup slots
+	connect(&notifier_, SIGNAL(readyReadStandardError()), this, SLOT(standa=
rdErrorReady()));
+	connect(&notifier_, SIGNAL(readyReadStandardOutput()), this, SLOT(stand=
ardOutputReady()));
+}
+
+LogTextEdit::~LogTextEdit()
+{
+}
+
+void LogTextEdit::standardErrorReady()
+{
+	static const QString format("%1;%2 - WARNING: %3");
+=09
+	QString message =3D notifier_.readError();
+	foreach (QString line, message.split('\n', QString::SkipEmptyParts))
+		append(format.arg(QDate::currentDate().toString(), QTime::currentTime(=
).toString(), line));
+}
+
+void LogTextEdit::standardOutputReady()
+{
+	static const QString format("%1;%2: %3");
+
+	QString message =3D notifier_.readOutput();
+	foreach (QString line, message.split('\n', QString::SkipEmptyParts))
+		append(format.arg(QDate::currentDate().toString(), QTime::currentTime(=
).toString(), line));
+}

Added: trunk/DvdMenuXtractor/logtextedit.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/logtextedit.h	2007-01-22 11:21:16 UTC (rev 1269=
)
+++ trunk/DvdMenuXtractor/logtextedit.h	2007-01-28 16:48:11 UTC (rev 1270=
)
@@ -0,0 +1,25 @@
+#ifndef LOGTEXTEDIT_H
+#define LOGTEXTEDIT_H
+
+#include <QTextEdit>
+
+// forward declaration
+class OutputReader;
+
+class LogTextEdit : public QTextEdit
+{
+	Q_OBJECT
+
+public:
+  LogTextEdit(QWidget *parent);
+  ~LogTextEdit();
+
+private slots:
+	void standardErrorReady();
+	void standardOutputReady();
+
+private:
+	OutputReader& notifier_;
+};
+
+#endif // LOGTEXTEDIT_H

Added: trunk/DvdMenuXtractor/main.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/main.cpp	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/main.cpp	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,27 @@
+#include <string>
+#include <QtGui/QApplication>
+
+#include "dmxwizard.h"
+#include "dmxconsole.h"
+
+int main(int argc, char *argv[])
+{=09
+	bool useGui =3D (argc =3D=3D 1); // default mode is gui mode
+
+	if (!useGui)
+	{
+		DMXConsole console(argv, argc);
+		console.extract();
+	}
+	else
+	{
+		QApplication app(argc, argv);
+		DMXWizard wizard;
+		wizard.show();
+		app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
+
+		return app.exec();
+	}
+
+	return 0;
+}

Deleted: trunk/DvdMenuXtractor/makefile.vc

Modified: trunk/DvdMenuXtractor/mpegparser/Types.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/mpegparser/Types.h	2007-01-22 11:21:16 UTC (rev=
 1269)
+++ trunk/DvdMenuXtractor/mpegparser/Types.h	2007-01-28 16:48:11 UTC (rev=
 1270)
@@ -1,7 +1,7 @@
 #ifndef __TYPES_H__
 #define __TYPES_H__
=20
-#include <inttypes.h>
+#include <stdint.h>
=20
 typedef int64_t MediaTime;
 typedef uint8_t binary;

Added: trunk/DvdMenuXtractor/mpegparser/mpegparser.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/mpegparser/mpegparser.proj	2007-01-22 11:21:16 =
UTC (rev 1269)
+++ trunk/DvdMenuXtractor/mpegparser/mpegparser.proj	2007-01-28 16:48:11 =
UTC (rev 1270)
@@ -0,0 +1,11 @@
+GROUP mpegparser
+{
+  SOURCE CircBuffer.cpp
+  SOURCE M2VParser.cpp
+  SOURCE MPEGVideoBuffer.cpp
+
+  HEADER CircBuffer.h
+  HEADER M2VParser.h
+  HEADER MPEGVideoBuffer.h
+  HEADER Types.h
+}

Added: trunk/DvdMenuXtractor/outputreader.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/outputreader.cpp	2007-01-22 11:21:16 UTC (rev 1=
269)
+++ trunk/DvdMenuXtractor/outputreader.cpp	2007-01-28 16:48:11 UTC (rev 1=
270)
@@ -0,0 +1,166 @@
+#include <io.h>
+#include <QDir>
+#include <fcntl.h>
+#include <fstream>
+#include <QWidget>
+#include <QTextStream>
+#include <QTimerEvent>
+#include "outputreader.h"
+
+OutputReader::OutputReader(QObject *parent /* =3D 0*/)
+  : QObject(parent), stderrStream(0), stdoutStream(0), redirecting_(fals=
e),
+		stderrFileName("stderr.txt"),	stdoutFileName("stdout.txt")
+{
+}
+
+OutputReader::~OutputReader()
+{
+	if (redirecting_)
+		cancelRedirect();
+}
+
+void OutputReader::timerEvent(QTimerEvent *event)
+{
+	// if the event is intended for us
+	if ((event->timerId() =3D=3D timer.timerId()) && redirecting_)
+	{
+		QFile stdoutFile (stdoutFileName);
+		QFile stderrFile (stderrFileName);
+=09
+		static qint64 stderrFileSize =3D 0;
+		static qint64 stdoutFileSize =3D 0;
+
+		qint64 size =3D stderrFile.size();
+
+		if (size > stderrFileSize) // new data is available
+		{
+			stderrFileSize =3D size;
+			emit readyReadStandardError();
+		}
+
+		size =3D stdoutFile.size();
+
+		if (size > stdoutFileSize) // new data is available
+		{
+			stdoutFileSize =3D size;
+			emit readyReadStandardOutput();
+		}
+	}
+	else
+		QObject::timerEvent(event);
+}
+
+bool OutputReader::redirect()=20
+{
+	if (redirecting_)
+		return true;
+
+	// save old descriptors
+	stdout_desc =3D _dup(1);
+	stderr_desc =3D _dup(2);
+
+	if ((stdout_desc =3D=3D -1) || (stderr_desc =3D=3D -1))
+  	return false;
+
+	// redirect stdout and stderr to corresponding files
+#if defined(_CRT_SECURE_NO_DEPRECATE)
+	stdoutStream =3D freopen(stdoutFileName.toAscii(), "wc", stdout);
+	stderrStream =3D freopen(stderrFileName.toAscii(), "wc", stderr);
+#else
+	freopen_s(&stdoutStream, stdoutFileName.toAscii(), "wc", stdout);
+	freopen_s(&stderrStream, stderrFileName.toAscii(), "wc", stderr);
+#endif
+
+	if ((stderrStream =3D=3D 0) || (stdoutStream =3D=3D 0))
+		return false;
+
+	// disable buffering
+  setvbuf(stdout, 0, _IONBF, 0);
+  setvbuf(stderr, 0, _IONBF, 0);
+
+	redirecting_ =3D true;
+
+	// start monitoring
+	timer.start(TIMEOUT, this);
+=09
+  return redirecting_;
+}
+
+bool OutputReader::cancelRedirect()
+{
+	// close streams
+	if (stderrStream !=3D 0)
+		fclose(stderrStream);
+=09
+	if (stdoutStream !=3D 0)
+		fclose(stdoutStream);
+
+	// set back standard file descriptors
+	if (( -1 =3D=3D _dup2(stdout_desc, 1))=20
+	  ||( -1 =3D=3D _dup2(stderr_desc, 2)))
+			return false;
+
+	// stop monitoring
+	timer.stop();
+
+	stderrStream =3D 0;
+	stdoutStream =3D 0;
+
+	redirecting_ =3D false;
+
+	return true;
+}
+
+QString OutputReader::readOutput() const
+{
+	static std::ifstream::pos_type position =3D 0;
+=09
+	QString output;
+	std::string data;
+	std::ifstream stream (qPrintable(stdoutFileName));
+	if (stream.is_open())
+	{
+		if (stream.seekg(position).good())
+			do
+			{
+				position =3D stream.tellg();
+				if(getline(stream, data))
+					output.append(data.data()).append('\n');
+				else
+					break;
+			}
+			while (true);
+	}
+
+	return output;
+}
+
+QString OutputReader::readError() const
+{
+	static std::ifstream::pos_type position =3D 0;
+=09
+	QString error;
+	std::string data;
+	std::ifstream stream (qPrintable(stderrFileName));
+	if (stream.is_open())
+	{
+		if (stream.seekg(position).good())
+			do
+			{
+				position =3D stream.tellg();
+				if(getline(stream, data))
+					error.append(data.data()).append('\n');
+				else
+					break;
+			}
+			while (true);
+	}
+
+	return error;
+}
+
+OutputReader& OutputReader::instance()
+{
+	static OutputReader reader;
+	return reader;
+}
\ No newline at end of file

Added: trunk/DvdMenuXtractor/outputreader.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/outputreader.h	2007-01-22 11:21:16 UTC (rev 126=
9)
+++ trunk/DvdMenuXtractor/outputreader.h	2007-01-28 16:48:11 UTC (rev 127=
0)
@@ -0,0 +1,63 @@
+/**********************************************************/
+/* Description: Contains OutputReader class declaration	  */
+/**********************************************************/
+#ifndef OUTPUTREADER_H
+#define OUTPUTREADER_H
+
+#include <QObject>
+#include <QBasicTimer>
+
+class OutputReader : public QObject
+{
+	Q_OBJECT
+
+public:
+
+	static OutputReader& instance();
+
+	/* Starts redirecting stdout and stderr to itself */
+	bool redirect();
+=09
+	/* Cancels redirecting stdout and stderr to itself */
+	bool cancelRedirect();
+
+	/* Reads stderr content, when available */
+	QString readError() const;
+=09
+	/* Reads stdout content, when available */
+	QString readOutput() const;
+
+signals:
+	/* These signals are emitted when stdout  */
+	/*  and/or stderr are ready to be read	  */
+	void readyReadStandardError();
+	void readyReadStandardOutput();
+
+protected:
+	void timerEvent(QTimerEvent *event);
+
+private:
+	static const int TIMEOUT =3D 1000;
+
+	bool redirecting_;
+
+	QString stdoutFileName; // file where stdout would be redirected
+	QString stderrFileName; // file where stderr would be redirected
+
+  int stdout_desc;	// stdout descriptor before redirecting
+	int stderr_desc;	// stderr descriptor before redirecting
+
+	FILE *stderrStream;	// file stream for standard error
+	FILE *stdoutStream; // file stream for standard output
+
+	QBasicTimer timer;	// Timer to watch for output change
+
+	// singleton pattern, no copying
+	OutputReader(const OutputReader&);
+	OutputReader& operator=3D (const OutputReader&);
+	OutputReader(QObject *parent =3D 0);
+	~OutputReader();
+};
+
+
+#endif // OUTPUTREADER_H

Added: trunk/DvdMenuXtractor/selectiontreeitem.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/selectiontreeitem.cpp	2007-01-22 11:21:16 UTC (=
rev 1269)
+++ trunk/DvdMenuXtractor/selectiontreeitem.cpp	2007-01-28 16:48:11 UTC (=
rev 1270)
@@ -0,0 +1,41 @@
+#include <QTreeWidgetItem>
+#include "selectiontreeitem.h"
+
+SelectionTreeItem::SelectionTreeItem(QTreeWidget *parent, int16_t title,=
 bool isMenuItem)
+	: QTreeWidgetItem(parent), title_(title), isMenuItem_(isMenuItem)
+{
+	static const QString vmgTitleFormat(QObject::tr("VMG"));
+	static const QString vtsTitleFormat(QObject::tr("Title %1"));
+	static const QString vtsmTitleFormat(QObject::tr("Title %1 Menu"));
+=09
+	if (isMenuItem && title)
+		setText(0, vtsmTitleFormat.arg(QString::number(title), 2, '0'));
+	else if (isMenuItem)
+		setText(0, vmgTitleFormat);
+	else
+		setText(0, vtsTitleFormat.arg(QString::number(title), 2, '0'));
+
+	setFlags(flags() | Qt::ItemIsTristate);
+	setCheckState(0, Qt::Checked);
+}
+
+SelectionTreeItem::SelectionTreeItem(const SelectionTreeItem &other)
+	: QTreeWidgetItem(other), title_(other.title_), isMenuItem_(other.isMen=
uItem_)
+{
+	setCheckState(0, other.checkState(0));
+}
+
+SelectionTreeItem::~SelectionTreeItem()
+{
+
+}
+
+bool SelectionTreeItem::isMenuItem() const
+{
+	return isMenuItem_;
+}
+
+int16_t SelectionTreeItem::title() const
+{
+	return title_;
+}

Added: trunk/DvdMenuXtractor/selectiontreeitem.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/selectiontreeitem.h	2007-01-22 11:21:16 UTC (re=
v 1269)
+++ trunk/DvdMenuXtractor/selectiontreeitem.h	2007-01-28 16:48:11 UTC (re=
v 1270)
@@ -0,0 +1,25 @@
+#ifndef SELECTIONTREEITEM_H
+#define SELECTIONTREEITEM_H
+
+#include <stdint.h>
+
+// forward declaration
+class QTreeWidgetItem;
+
+class SelectionTreeItem : public QTreeWidgetItem
+{
+public:
+
+  SelectionTreeItem(QTreeWidget *parent, int16_t title, bool isMenuItem)=
;
+	SelectionTreeItem(const SelectionTreeItem &other);
+  ~SelectionTreeItem();
+
+	int16_t title()		const;
+	bool isMenuItem() const;
+
+private:
+	int16_t title_;
+	bool isMenuItem_;
+};
+
+#endif // SELECTIONTREEITEM_H

Added: trunk/DvdMenuXtractor/selectiontreesubitem.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/selectiontreesubitem.cpp	2007-01-22 11:21:16 UT=
C (rev 1269)
+++ trunk/DvdMenuXtractor/selectiontreesubitem.cpp	2007-01-28 16:48:11 UT=
C (rev 1270)
@@ -0,0 +1,42 @@
+#include <QTreeWidgetItem>
+#include "selectiontreesubitem.h"
+
+SelectionTreeSubItem::SelectionTreeSubItem(QTreeWidgetItem *parent, cons=
t SelectionTreeItem &titleItem, size_t index, SelectionTreeSubItem::SubIt=
emType type)
+	: QTreeWidgetItem(parent), titleItem_(titleItem), index_(index), type_(=
type)
+{
+	static const QString audioTrackTitleFormat ("Audio Track %1");
+	static const QString subTrackTitleFormat ("Subtitle Track %1");
+=09
+	if (type =3D=3D AUDIO_TRACK)
+		setText(0, audioTrackTitleFormat.arg(index));
+	else
+		setText(0, subTrackTitleFormat.arg(index));
+
+	setFlags(flags() | Qt::ItemIsTristate);
+	setCheckState(0, Qt::Checked);
+}
+
+SelectionTreeSubItem::SelectionTreeSubItem(const SelectionTreeSubItem &o=
ther)
+	: QTreeWidgetItem(other), titleItem_(other.titleItem_), index_(other.in=
dex_), type_(other.type_)
+{
+	setCheckState(0, other.checkState(0));
+}
+
+SelectionTreeSubItem::~SelectionTreeSubItem()
+{
+}
+
+size_t SelectionTreeSubItem::index() const
+{
+	return index_;
+}
+
+SelectionTreeSubItem::SubItemType SelectionTreeSubItem::type() const
+{
+	return type_;
+}
+
+const SelectionTreeItem& SelectionTreeSubItem::titleItem() const
+{
+	return titleItem_;
+}

Added: trunk/DvdMenuXtractor/selectiontreesubitem.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/selectiontreesubitem.h	2007-01-22 11:21:16 UTC =
(rev 1269)
+++ trunk/DvdMenuXtractor/selectiontreesubitem.h	2007-01-28 16:48:11 UTC =
(rev 1270)
@@ -0,0 +1,26 @@
+#ifndef SELECTION_TREE_SUB_ITEM_H
+#define SELECTION_TREE_SUB_ITEM_H
+
+// forward declaration
+class QTreeWidgetItem;
+class SelectionTreeItem;
+
+class SelectionTreeSubItem : public QTreeWidgetItem
+{
+public:
+	enum SubItemType { AUDIO_TRACK, SUBTITLE_TRACK };
+	SelectionTreeSubItem(QTreeWidgetItem *parent, const SelectionTreeItem& =
titleItem, size_t index, SubItemType type);
+	SelectionTreeSubItem(const SelectionTreeSubItem& other);
+	~SelectionTreeSubItem();
+
+	size_t index() const;
+	SubItemType type() const;
+	const SelectionTreeItem& titleItem() const;
+
+private:
+	size_t index_;
+	SubItemType type_;
+	const SelectionTreeItem &titleItem_;
+};
+
+#endif // SELECTION_TREE_SUB_ITEM_H
\ No newline at end of file

Added: trunk/DvdMenuXtractor/utilities.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/utilities.cpp	2007-01-22 11:21:16 UTC (rev 1269=
)
+++ trunk/DvdMenuXtractor/utilities.cpp	2007-01-28 16:48:11 UTC (rev 1270=
)
@@ -0,0 +1,32 @@
+#include <iostream>
+#include "utilities.h"
+
+QString Utilities::CreateUID()
+{
+	return QString("%1").arg( uint32_t(rand() | (rand() << 16)) );
+}
+
+QString Utilities::FormatTime(uint64_t a_time)
+{
+	int hour, min, sec;
+	uint32_t nano;
+
+	nano =3D a_time % 1000000000;
+	a_time /=3D 1000000000;
+	sec =3D a_time % 60;
+	a_time /=3D 60;
+	min =3D a_time % 60;
+	hour =3D a_time / 60;
+
+	return QString("%1:%2:%3.%4").arg(hour, 2, 10, QChar('0')).arg(min, 2, =
10, QChar('0')).arg(sec, 2, 10, QChar('0')).arg(nano, 9, 10, QChar('0'));
+}
+
+QString Utilities::EncodeHex(const unsigned char *buffer, unsigned int s=
ize)
+{
+	QString result;
+
+	for (unsigned i =3D 0; i < size; ++i)
+		result +=3D QString("%1 ").arg(buffer[i], 2, 16, QChar('0'));
+
+	return result.trimmed();
+}
\ No newline at end of file

Added: trunk/DvdMenuXtractor/utilities.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/utilities.h	2007-01-22 11:21:16 UTC (rev 1269)
+++ trunk/DvdMenuXtractor/utilities.h	2007-01-28 16:48:11 UTC (rev 1270)
@@ -0,0 +1,17 @@
+#ifndef UTILITIES_H
+#define UTILITIES_H
+
+#include <QString>
+#include <stdint.h>
+
+namespace Utilities
+{
+	static const QString APPLICATION_NAME    ("DVDMenuXtractor: DMX - a fai=
r-use tool");
+	static const QString APPLICATION_VERSION ("0.9.x");
+
+	QString CreateUID();
+	QString FormatTime(uint64_t a_time);
+	QString EncodeHex(const unsigned char *buffer, unsigned size);
+}
+
+#endif // UTILITIES_H
\ No newline at end of file

Added: trunk/DvdMenuXtractor/vobparser/IFOContent.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/IFOContent.cpp	2007-01-22 11:21:16 UT=
C (rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/IFOContent.cpp	2007-01-28 16:48:11 UT=
C (rev 1270)
@@ -0,0 +1,273 @@
+// ---------------------------------------------------------------------=
-------
+#include "IFOContent.h"
+// ---------------------------------------------------------------------=
-------
+// Macro to convert Binary Coded Decimal to Decimal
+#define BCD2D(__x__) (((__x__ & 0xf0) >> 4) * 10 + (__x__ & 0x0f))
+// ---------------------------------------------------------------------=
-------
+int dvdtime2frame(dvd_time_t* dtime, double & frame_dur)
+{
+	double frame_rate;
+	double result =3D 0.0;
+	assert((dtime->hour>>4) < 0xa && (dtime->hour&0xf) < 0xa);
+	assert((dtime->minute>>4) < 0x7 && (dtime->minute&0xf) < 0xa);
+	assert((dtime->second>>4) < 0x7 && (dtime->second&0xf) < 0xa);
+	assert((dtime->frame_u&0xf) < 0xa);
+
+	int hh, min, sec, ff;
+	hh =3D BCD2D(dtime->hour);
+	min =3D BCD2D(dtime->minute);
+	sec =3D BCD2D(dtime->second);
+	ff =3D BCD2D(dtime->frame_u & 0x3f);
+
+	frame_rate =3D ((dtime->frame_u & 0xc0) >> 6) =3D=3D 1 ? 25.0 : (30000.=
0/1001.0);
+	result =3D (((((hh * 60) + min) * 60) + sec) * frame_rate) + (ff & 0x3f=
);
+	frame_dur =3D 1000.0 / frame_rate;
+
+	return (int)result;
+}
+// ---------------------------------------------------------------------=
-------
+IFOContent::IFOContent(dvd_reader_t *dvdr, int16_t title)
+	:m_title(title)
+{
+	m_handle =3D ifoOpen(dvdr, title);
+	if (!m_handle)
+		throw IFOInvalidFileFormatException();
+
+	CellsHashType CellsHash;
+
+	if (title =3D=3D 0)
+	{
+		if (m_handle->vmgi_mat)
+		{
+			const vmgi_mat_t &vmgi_mat =3D *m_handle->vmgi_mat;
+			if (vmgi_mat.nr_of_vmgm_audio_streams)
+				m_langAudio.push_back(&vmgi_mat.vmgm_audio_attr);
+			if (vmgi_mat.nr_of_vmgm_subp_streams)
+				m_langSubs.push_back(&vmgi_mat.vmgm_subp_attr);
+		}
+
+		if (m_handle->pgci_ut && m_handle->menu_c_adt)
+		{
+			// add each cell in a list
+			// order this list according to vob ID, cell ID
+			// for each cell, find the duration (and start time) from all menu PG=
Cs
+			for(uint16_t i =3D 0; i < m_handle->pgci_ut->nr_of_lus; i++)
+			{
+				pgci_lu_t& lu =3D m_handle->pgci_ut->lu[i];
+				GetPGCCells(*lu.pgcit, *m_handle->menu_c_adt, &CellsHash);
+			}
+
+			// Transfer hash map to the list to be sorted
+			m_langCellsList.clear();
+		=09
+			for(CellsHashType::iterator it =3D CellsHash.begin(); it !=3D CellsHa=
sh.end(); ++it )
+			{
+				m_langCellsList.append(it.value());
+			}
+
+			m_langCellsList.arrange();
+		}
+	}
+	else
+	{
+		if (m_handle->vtsi_mat)
+		{
+			const vtsi_mat_t & vtsi_mat =3D *m_handle->vtsi_mat;
+			if (vtsi_mat.nr_of_vtsm_audio_streams)
+				m_langAudio.push_back(&vtsi_mat.vtsm_audio_attr);
+			if (vtsi_mat.nr_of_vtsm_subp_streams)
+				m_langSubs.push_back(&vtsi_mat.vtsm_subp_attr);
+
+			uint8_t _stream;
+			for (_stream=3D0; _stream < vtsi_mat.nr_of_vts_audio_streams; _stream=
++)
+				m_Audio.push_back(&vtsi_mat.vts_audio_attr[_stream]);
+			for (_stream=3D0; _stream < vtsi_mat.nr_of_vts_subp_streams; _stream+=
+)
+				m_Subs.push_back(&vtsi_mat.vts_subp_attr[_stream]);
+		}
+
+		// handle the list of menu cells with their ID and sectors
+		CellsHash.clear();
+		if (m_handle->pgci_ut && m_handle->menu_c_adt)
+		{
+			// add each cell in a list
+			// order this list according to vob ID, cell ID
+			// for each cell, find the duration (and start time) from all menu PG=
Cs
+			for(int i =3D 0; i < m_handle->pgci_ut->nr_of_lus; i++)
+			{
+				pgci_lu_t& lu =3D m_handle->pgci_ut->lu[i];
+				GetPGCCells(*lu.pgcit, *m_handle->menu_c_adt, &CellsHash);
+			}
+
+			// Transfer hash map to the list to be sorted
+			m_langCellsList.clear();
+			CellsHashType::iterator it;
+			for( it =3D CellsHash.begin(); it !=3D CellsHash.end(); ++it )
+			{
+				m_langCellsList.append(it.value());
+			}
+
+			m_langCellsList.arrange();
+		}
+
+		// handle the list of cells with their ID and sectors
+		CellsHash.clear();
+		if (m_handle->vts_pgcit && m_handle->vts_c_adt)
+		{
+			// add each cell in a list
+			// order this list according to vob ID, cell ID
+			// for each cell, find the duration (and start time) from all PGCs
+			GetPGCCells(*m_handle->vts_pgcit, *m_handle->vts_c_adt, &CellsHash);
+
+			// Transfer hash map to the list to be sorted
+			m_CellsList.clear();
+		=09
+			for(CellsHashType::iterator it =3D CellsHash.begin(); it !=3D CellsHa=
sh.end(); ++it )
+			{
+				m_CellsList.append(it.value());
+			}
+
+			m_CellsList.arrange();
+		}
+	}
+}
+// ---------------------------------------------------------------------=
-------
+void IFOContent::GetPGCCells(const pgcit_t & pgcit, const c_adt_t & adt,=
 CellsHashType * CellsHash)
+{
+	CellListElem* cle;
+
+	for(int j=3D0; j < pgcit.nr_of_pgci_srp; j++)
+	{
+		pgci_srp_t& srp =3D pgcit.pgci_srp[j];
+		for(int k=3D0; k < srp.pgc->nr_of_cells; k++)
+		{
+			uint16_t vob_id =3D srp.pgc->cell_position[k].vob_id_nr;
+			uint8_t cell_id =3D srp.pgc->cell_position[k].cell_nr;
+
+			if (CellsHash->find(MAKE_CELLS_KEY(vob_id, cell_id)) =3D=3D CellsHash=
->end())
+			{
+				size_t cell_nr =3D adt.last_byte;
+				cell_nr -=3D 7;
+				cell_nr /=3D sizeof(cell_adr_t);
+				for (size_t l=3D0; l < cell_nr; l++)
+				{
+					if (adt.cell_adr_table[l].vob_id =3D=3D vob_id && adt.cell_adr_tabl=
e[l].cell_id =3D=3D cell_id)
+					{
+						cle =3D new CellListElem();
+						(*CellsHash)[MAKE_CELLS_KEY(vob_id, cell_id)] =3D cle;
+
+						cle->vobid =3D vob_id;
+						cle->cellid =3D cell_id;
+
+						cle->start_sector =3D adt.cell_adr_table[l].start_sector;
+						cle->last_sector =3D adt.cell_adr_table[l].last_sector;
+						cle->selected =3D true; // all cells selected for the moment
+						cle->found =3D false;
+						/* debug	* /			cle->found =3D true;*/
+
+						cle->nb_frames =3D dvdtime2frame(&srp.pgc->cell_playback[k].playba=
ck_time, cle->frame_dur);
+						cle->isStill =3D (srp.pgc->cell_playback[k].still_time > 0);
+						if (cle->isStill)
+						{
+							if (srp.pgc->cell_playback[k].still_time =3D=3D 0xFF) {
+							  qWarning(QString("Still cell (%1.%2) detected with infinite dur=
ation !").arg(QString::number(vob_id), QString::number(cell_id)).toAscii(=
));
+							} else {
+							  qWarning(QString("Still cell (%1.%2) detected. Assuming there i=
s just one frame.").arg(QString::number(vob_id), QString::number(cell_id)=
).toAscii());
+								cle->nb_frames =3D 1; // maybe not true ?
+								cle->frame_dur =3D srp.pgc->cell_playback[k].still_time * 1000.0=
 / cle->nb_frames;
+							}
+						}
+						break;
+					}
+				}
+			}
+		}
+	}
+}
+// ---------------------------------------------------------------------=
-------
+uint8_t IFOContent::FindAudioStream(uint8_t streamID, bool menu) const
+{
+	assert(m_handle !=3D NULL);
+	if (menu)
+	{
+		if (m_handle->pgci_ut)
+		{
+			for (int i=3D0; i<m_handle->pgci_ut->nr_of_lus; i++)
+			{
+				pgci_lu_t &_lu =3D m_handle->pgci_ut->lu[i];
+				for (int j=3D0; j < _lu.pgcit->nr_of_pgci_srp; j++)
+				{
+					pgc_t *_pgc =3D _lu.pgcit->pgci_srp[j].pgc;
+					if(_pgc->audio_control[streamID] & 0x8000) // if present
+						return (_pgc->audio_control[streamID] >> 8) & 0x7F;
+				}
+			}
+		}
+	}
+	else
+	{
+		if (m_handle->vts_pgcit)
+		{
+			for (int j=3D0; j < m_handle->vts_pgcit->nr_of_pgci_srp; j++)
+			{
+				pgc_t *_pgc =3D m_handle->vts_pgcit->pgci_srp[j].pgc;
+				if(_pgc->audio_control[streamID] & 0x8000) // if present
+					return (_pgc->audio_control[streamID] >> 8) & 0x7F;
+			}
+		}
+	}
+	return streamID;
+}
+// ---------------------------------------------------------------------=
-------
+IdArray IFOContent::FindSubStream(uint8_t streamID, bool menu) const
+{
+	IdArray result;
+
+	assert(m_handle !=3D NULL);
+	if (menu)
+	{
+		if (m_handle->pgci_ut)
+		{
+			for (int i=3D0; i<m_handle->pgci_ut->nr_of_lus; i++)
+			{
+				pgci_lu_t &_lu =3D m_handle->pgci_ut->lu[i];
+				for (int j=3D0; j < _lu.pgcit->nr_of_pgci_srp; j++)
+				{
+					pgc_t *_pgc =3D _lu.pgcit->pgci_srp[j].pgc;
+					if(_pgc->subp_control[streamID] & 0x80000000) // if present
+					{
+						result.push_back( _pgc->subp_control[streamID] >> 24 & 0x7F);
+						if (_pgc->subp_control[streamID] & 0x007F0000)
+							result.push_back( _pgc->subp_control[streamID] >> 16 & 0x7F);
+						if (_pgc->subp_control[streamID] & 0x00007F00)
+							result.push_back( _pgc->subp_control[streamID] >>  8 & 0x7F);
+						if (_pgc->subp_control[streamID] & 0x0000007F)
+							result.push_back( _pgc->subp_control[streamID] >>  0 & 0x7F);
+					}
+				}
+			}
+		}
+	}
+	else
+	{
+		if (m_handle->vts_pgcit)
+		{
+			for (int j=3D0; j < m_handle->vts_pgcit->nr_of_pgci_srp; j++)
+			{
+				pgc_t *_pgc =3D m_handle->vts_pgcit->pgci_srp[j].pgc;
+				if(_pgc->subp_control[streamID] & 0x80000000) // if present
+				{
+					result.push_back( _pgc->subp_control[streamID] >> 24 & 0x7F);
+					if (_pgc->subp_control[streamID] & 0x007F0000)
+						result.push_back( _pgc->subp_control[streamID] >> 16 & 0x7F);
+					if (_pgc->subp_control[streamID] & 0x00007F00)
+						result.push_back( _pgc->subp_control[streamID] >>  8 & 0x7F);
+					if (_pgc->subp_control[streamID] & 0x0000007F)
+						result.push_back( _pgc->subp_control[streamID] >>  0 & 0x7F);
+				}
+			}
+		}
+	}
+
+	return result;
+}
+// ---------------------------------------------------------------------=
-------
\ No newline at end of file

Added: trunk/DvdMenuXtractor/vobparser/IFOContent.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/IFOContent.h	2007-01-22 11:21:16 UTC =
(rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/IFOContent.h	2007-01-28 16:48:11 UTC =
(rev 1270)
@@ -0,0 +1,71 @@
+// ---------------------------------------------------------------------=
-------
+#ifndef _IFO_CONTENT_H_
+#define _IFO_CONTENT_H_
+// ---------------------------------------------------------------------=
-------
+#include <QHash>
+#include <vector>
+
+#include "VobParser.h"
+#include "dvdread/ifo_read.h"
+// ---------------------------------------------------------------------=
-------
+typedef std::vector<uint8_t> IdArray;
+
+typedef QHash<int, CellListElem *> CellsHashType;
+typedef std::vector<const audio_attr_t*> AudioTrackList;
+typedef std::vector<const subp_attr_t*> SubtitleTrackList;
+
+#define MAKE_CELLS_KEY(vob_id,cell_id)  ((vob_id << 8) | cell_id)
+// ---------------------------------------------------------------------=
-------
+class IFOException { };
+class IFOFileIOException : public IFOException { };
+class IFOInvalidFileFormatException : public IFOException { };
+// ---------------------------------------------------------------------=
-------
+typedef QList<CellListElem*> CellsListBaseType;
+class CellsListType : public CellsListBaseType
+{
+public:
+	void arrange();
+	CellListElem* at(uint16_t vob_id, uint8_t cell_id) const;
+	const CellListElem* at(const cell_position_t & position) const;
+
+	// comperator for qSort()
+	static int cellListElemCompare(const CellListElem *arg1, const CellList=
Elem *arg2);
+};
+// ---------------------------------------------------------------------=
-------
+class IFOContent=20
+{
+public:
+	IFOContent(dvd_reader_t *dvdr, int16_t title);
+
+	~IFOContent()
+	{
+		ifoClose(m_handle);
+		m_CellsList.clear();
+		m_langCellsList.clear();
+	}
+
+	ifo_handle_t& Handle()
+	{
+		assert(m_handle !=3D NULL);
+		return *m_handle;
+	}
+
+	IdArray FindSubStream(uint8_t streamID, bool menu) const;
+	uint8_t FindAudioStream(uint8_t streamID, bool menu) const;
+=09
+	void GetPGCCells(const pgcit_t & pgcit, const c_adt_t & adt, CellsHashT=
ype * CellsHash);
+
+	int16_t m_title;
+	AudioTrackList m_langAudio;
+	AudioTrackList m_Audio;
+	SubtitleTrackList m_langSubs;
+	SubtitleTrackList m_Subs;
+	CellsListType m_CellsList;
+	CellsListType m_langCellsList;
+
+protected:
+	ifo_handle_t *m_handle;
+};
+// ---------------------------------------------------------------------=
-------
+#endif
+// ---------------------------------------------------------------------=
-------
\ No newline at end of file

Added: trunk/DvdMenuXtractor/vobparser/IFOFile.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/IFOFile.cpp	2007-01-22 11:21:16 UTC (=
rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/IFOFile.cpp	2007-01-28 16:48:11 UTC (=
rev 1270)
@@ -0,0 +1,304 @@
+// ---------------------------------------------------------------------=
-------
+#include "IFOFile.h"
+#include "iso/iso_lang.h"
+#include "dvdread/ifo_print.h"
+// ---------------------------------------------------------------------=
-------
+IFOFile::IFOFile(const QString& filename)
+{=09
+	m_dvd =3D DVDOpen(qPrintable(filename));
+=09
+	if(!m_dvd) {
+		throw IFOInvalidFileFormatException();
+	}
+
+	try {
+		m_ifos.append(new IFOContent(m_dvd, 0));	=09
+	}
+	catch (...)	{
+		qCritical("Cannot open VIDEO_TS.IFO.");
+		throw;
+	}
+
+	IFOContent *_ifo =3D m_ifos.getIfoContent(0);
+
+	if (_ifo && _ifo->Handle().vmgi_mat)
+	{
+		for (int i =3D 1; i <=3D _ifo->Handle().vmgi_mat->vmg_nr_of_title_sets=
; i++)
+		{
+			try {
+				m_ifos.append(new IFOContent(m_dvd,i));
+			}
+			catch (...)	{
+			  qCritical(QString("Cannot open VTS_%1_X.IFO").arg(i).toAscii());
+			}
+		}
+	}
+}
+// ---------------------------------------------------------------------=
-------
+IFOFile::~IFOFile()
+{
+	for (int i =3D 0; i < m_ifos.size(); i++)
+		delete m_ifos.at(i);
+=09
+	if (m_dvd)
+	{
+		DVDClose(m_dvd);
+	}
+}
+// ---------------------------------------------------------------------=
-------
+const pgc_t *IFOFile::FirstPlayPGC() const
+{
+	if (m_ifos.at(0))
+		return m_ifos.at(0)->Handle().first_play_pgc;
+	else
+		return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const tt_srpt_t *IFOFile::TitleMap() const
+{
+	if (m_ifos.at(0))
+		return m_ifos.at(0)->Handle().tt_srpt;
+	else
+		return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const pgci_ut_t *IFOFile::LanguageUnits(unsigned int title) const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (_ifo)
+	{
+		return _ifo->Handle().pgci_ut;
+	}
+	=09
+	return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const vts_ptt_srpt_t *IFOFile::VtsTitles(unsigned int title) const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (_ifo)
+	{
+		return _ifo->Handle().vts_ptt_srpt;
+	}
+	return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const pgcit_t *IFOFile::VtsPGCs(unsigned int title) const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (_ifo)
+	{
+		return _ifo->Handle().vts_pgcit;
+	}
+	return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const int16_t IFOFile::NumberOfTitles() const
+{
+	if (m_ifos.count() && m_ifos.at(0)->Handle().vmgi_mat)
+		return m_ifos.at(0)->Handle().vmgi_mat->vmg_nr_of_title_sets;
+	return 0;
+}
+// ---------------------------------------------------------------------=
-------
+int CellsListType::cellListElemCompare(const CellListElem *arg1, const C=
ellListElem *arg2)
+{
+	const CellListElem* cle1 =3D arg1;
+	const CellListElem* cle2 =3D arg2;
+
+	return (cle1->vobid > cle2->vobid) ? 1 :
+		(cle1->vobid < cle2->vobid) ? -1 :
+			(cle1->cellid > cle2->cellid) ? 1 :=20
+				(cle1->cellid < cle2->cellid) ? -1 :
+					0;
+}
+// ---------------------------------------------------------------------=
-------
+const CellsListType* IFOFile::GetCellsList(unsigned int title, bool menu=
)
+{
+	CellsHashType CellsHash;
+
+	IFOContent *ifoc =3D m_ifos.getIfoContent(title);
+	if (!ifoc)
+		return NULL;
+
+	if (menu)
+		return &ifoc->m_langCellsList;
+	else
+		return &ifoc->m_CellsList;
+}
+// ---------------------------------------------------------------------=
-------
+const AudioTrackList & IFOFile::AudioTracks(unsigned int title, bool men=
u) const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (!_ifo)
+		throw;
+
+	if (menu)
+		return _ifo->m_langAudio;
+	else
+		return _ifo->m_Audio;
+}
+// ---------------------------------------------------------------------=
-------
+const SubtitleTrackList & IFOFile::SubsTracks(unsigned int title, bool m=
enu) const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (!_ifo)
+		throw;
+
+	if (menu)
+		return _ifo->m_langSubs;
+	else
+		return _ifo->m_Subs;
+}
+// ---------------------------------------------------------------------=
-------
+const CellsListType & IFOFile::CellsList(unsigned int title, bool menu) =
const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (!_ifo)
+		throw;
+
+	if (menu)
+		return _ifo->m_langCellsList;
+	else
+		return _ifo->m_CellsList;
+}
+// ---------------------------------------------------------------------=
-------
+bool IFOFile::VideoSize(unsigned int title, bool menu, uint16_t & width,=
 uint16_t & height, double & fps) const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	assert(_ifo !=3D NULL);
+	video_attr_t *_attr =3D NULL;
+	if (menu)
+	{
+		if (title =3D=3D 0)
+		{
+			if (_ifo->Handle().vmgi_mat)
+			{
+				_attr =3D &_ifo->Handle().vmgi_mat->vmgm_video_attr;
+			}
+		}
+		else
+		{
+			if (_ifo->Handle().vtsi_mat)
+			{
+				_attr =3D &_ifo->Handle().vtsi_mat->vtsm_video_attr;
+			}
+		}
+	}
+	else
+	{
+		if (_ifo->Handle().vtsi_mat)
+		{
+			_attr =3D &_ifo->Handle().vtsi_mat->vts_video_attr;
+		}
+	}
+
+	if (_attr !=3D NULL)
+	{
+		height =3D 480;
+		if(_attr->video_format !=3D 0) {
+			fps =3D 25.0;
+			height =3D 576;
+		} else {
+			fps =3D 30000.0/1001.0;
+		}
+		switch(_attr->picture_size) {
+			case 0:
+				width =3D 720;
+				break;
+			case 1:
+				width =3D 704;
+				break;
+			case 2:
+				width =3D 352;
+				break;
+			case 3:
+				width =3D 352;
+				height >>=3D 1;
+			break;     =20
+		}
+		return true;
+	}
+	return false;
+}
+// ---------------------------------------------------------------------=
-------
+const uint32_t * IFOFile::GetPalette(unsigned int title, bool menu) cons=
t
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	assert(_ifo !=3D NULL);
+	video_attr_t *_attr =3D NULL;
+=09
+	if (menu)
+		return (_ifo->Handle().pgci_ut->lu->pgcit->pgci_srp->pgc->palette);
+	else
+		return (_ifo->Handle().vts_pgcit->pgci_srp->pgc->palette);
+
+	return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+uint8_t IFOFile::GetAudioId(uint8_t streamID, uint8_t title, bool menu) =
const
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (!_ifo)
+		throw;
+
+	return _ifo->FindAudioStream(streamID, menu);
+}
+// ---------------------------------------------------------------------=
-------
+IdArray IFOFile::GetSubsId(uint8_t streamID, uint8_t title, bool menu) c=
onst
+{
+	IFOContent *_ifo =3D m_ifos.getIfoContent(title);
+	if (!_ifo)
+		throw;
+
+	return _ifo->FindSubStream(streamID, menu);
+}
+// ---------------------------------------------------------------------=
-------
+IFOContent * IfoHandleList::getIfoContent(int16_t title) const
+{
+	for (size_type _index =3D 0; _index < size(); _index++)
+	{
+		if (at(_index)->m_title =3D=3D title)
+			return at(_index);
+	}
+	return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+const CellListElem* CellsListType::at(const cell_position_t & position) =
const
+{
+	return at(position.vob_id_nr, position.cell_nr);
+}
+// ---------------------------------------------------------------------=
-------
+CellListElem* CellsListType::at(uint16_t vob_id, uint8_t cell_id) const
+{
+	CellsListType::const_iterator node =3D begin();
+	while (node !=3D end())
+	{
+		CellListElem *cell =3D *node;
+	=09
+		if (cell->cellid =3D=3D cell_id && cell->vobid =3D=3D vob_id)
+			return cell;
+	=09
+		++node;
+	}
+=09
+	return NULL;
+}
+// ---------------------------------------------------------------------=
-------
+void CellsListType::arrange()
+{
+	qSort(begin(), end(), &CellsListType::cellListElemCompare);
+
+	// make the timecodes continuous
+	int64_t timecode =3D 0;
+	CellsListType::const_iterator node =3D begin();
+	while (node !=3D end())
+	{
+		CellListElem *cell =3D *node;
+		cell->start_time =3D timecode;
+		cell->duration =3D int64_t(cell->frame_dur * cell->nb_frames * 1000000=
.0);
+		if (cell->found)
+			timecode +=3D cell->duration;
+		++node;
+	}
+}
+// ---------------------------------------------------------------------=
-------
\ No newline at end of file

Added: trunk/DvdMenuXtractor/vobparser/IFOFile.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/IFOFile.h	2007-01-22 11:21:16 UTC (re=
v 1269)
+++ trunk/DvdMenuXtractor/vobparser/IFOFile.h	2007-01-28 16:48:11 UTC (re=
v 1270)
@@ -0,0 +1,43 @@
+// ---------------------------------------------------------------------=
-------
+#ifndef _IFO_FILE_H_
+#define _IFO_FILE_H_
+// ---------------------------------------------------------------------=
-------
+#include <QStringList>
+
+#include "IfoContent.h"
+// ---------------------------------------------------------------------=
-------
+class IfoHandleList: public QList<IFOContent*>
+{
+public:
+	/// look for IfoContent corresponding to the title
+	IFOContent* getIfoContent(int16_t title) const;
+};
+// ---------------------------------------------------------------------=
-------
+class IFOFile =20
+{
+public:
+	IFOFile(const QString& filename);
+	const CellsListType* GetCellsList(unsigned int title, bool menu);
+	virtual ~IFOFile();
+	const pgc_t *FirstPlayPGC() const;
+	const tt_srpt_t *TitleMap() const;
+	const pgci_ut_t *LanguageUnits(unsigned int title) const;
+	const vts_ptt_srpt_t *VtsTitles(unsigned int title) const;
+	const pgcit_t *VtsPGCs(unsigned int title) const;
+	const int16_t NumberOfTitles() const;
+	const AudioTrackList & AudioTracks(unsigned int title, bool menu) const=
;
+	const SubtitleTrackList & SubsTracks(unsigned int title, bool menu) con=
st;
+	const CellsListType & CellsList(unsigned int title, bool menu) const;
+	bool VideoSize(unsigned int title, bool menu, uint16_t & width, uint16_=
t & height, double & fps) const;
+	const uint32_t * GetPalette(unsigned int title, bool menu) const;
+
+	uint8_t GetAudioId(uint8_t streamID, uint8_t title, bool menu) const;
+	IdArray GetSubsId(uint8_t streamID, uint8_t title, bool menu) const;
+
+private:
+	IfoHandleList m_ifos;
+	dvd_reader_t* m_dvd;
+};
+// ---------------------------------------------------------------------=
-------
+#endif
+// ---------------------------------------------------------------------=
-------

Added: trunk/DvdMenuXtractor/vobparser/VobParser.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/VobParser.cpp	2007-01-22 11:21:16 UTC=
 (rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/VobParser.cpp	2007-01-28 16:48:11 UTC=
 (rev 1270)
@@ -0,0 +1,1310 @@
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// VOBParser class
+// Copyright =A9 2002 : Christophe PARIS (christophe.paris at free.fr)
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+#include <QFileInfo>
+
+#include "IFOFile.h"
+#include "VobParser.h"
+#include "iso/iso_lang.h"
+
+// ---------------------------------------------------------------------=
-------
+
+#define VOB_SLICE			0x00000100
+#define PACK_HEADER			0xBA
+#define SYSTEM_HEADER		0xBB
+#define PROGRAM_STREAM_MAP	0xBC
+#define PRIVATE_STREAM1		0xBD
+#define PADDING_STREAM		0xBE
+#define PRIVATE_STREAM2		0xBF
+#define CURRENT_OFFSET		(m_pktindex * DVD_VIDEO_LB_LEN + m_index)
+
+#define INDENT_UNIT 2
+unsigned int indent_lvl =3D 0;
+inline void inc_lvl() { indent_lvl +=3D INDENT_UNIT; }
+inline void dec_lvl() { indent_lvl -=3D INDENT_UNIT; }
+void debug (const QString& str)
+{
+	QString debugStr (indent_lvl, ' ');
+	debugStr +=3D str;
+	qDebug(qPrintable(debugStr));
+}
+
+// ---------------------------------------------------------------------=
-------
+// CompositeDemuxWriter
+// ---------------------------------------------------------------------=
-------
+
+CompositeDemuxWriter::CompositeDemuxWriter()
+{
+	for (int i=3D0; i<256; i++)
+		m_muxers[i] =3D NULL;
+}
+
+CompositeDemuxWriter::~CompositeDemuxWriter()
+{
+	Reset();
+}
+
+bool CompositeDemuxWriter::AddDemuxer(uint8_t streamID, Writer * demuxer=
, QString& CommandLine)
+{
+	if (m_muxers[streamID] !=3D NULL)
+		return false;
+	m_muxers[streamID] =3D demuxer;
+	m_strings[streamID] =3D CommandLine;
+	return true;
+}
+
+void CompositeDemuxWriter::ProcessStream(int streamID, uint8_t* buff, ui=
nt32_t size, int32_t start_time, int32_t end_time, const QString& debug)
+{
+	if (m_muxers[streamID] !=3D NULL)
+		m_muxers[streamID]->ProcessStream(buff, size, start_time, end_time, de=
bug);
+}
+
+void CompositeDemuxWriter::Reset()
+{
+	for (int i=3D0; i<256; i++)
+	{
+		if (m_muxers[i] !=3D NULL)
+		{
+			delete m_muxers[i];
+			m_muxers[i] =3D NULL;
+		}
+	}
+}
+
+void CompositeDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t=
 duration, const CellListElem *cell)
+{
+	for (int i=3D0; i<256; i++)
+	{
+		if (m_muxers[i] !=3D NULL)
+		{
+			m_muxers[i]->SetBoundary(start_timecode, duration, cell);
+		}
+	}
+}
+
+// ---------------------------------------------------------------------=
-------
+
+VobParser::VobParser(const char* dirname, int16_t title, bool menu)
+	:m_title(title)
+	,m_dvdhandle(NULL)
+	,m_stream(NULL)
+	,m_language(menu)
+	,m_bFirstPacket(true)
+{
+	m_pktcount =3D 0;
+
+	QFileInfo _tmpDirName(dirname);
+
+	// handle all parts of this title (VIDEO_TS.vob or VTS_XX_Y.vob)
+	m_dvdhandle =3D DVDOpen(qPrintable(_tmpDirName.canonicalPath()));
+
+	if (m_dvdhandle)
+	{
+		if (m_language)
+			m_stream =3D DVDOpenFile(m_dvdhandle, title, DVD_READ_MENU_VOBS);
+		else
+			m_stream =3D DVDOpenFile(m_dvdhandle, title, DVD_READ_TITLE_VOBS);
+	}
+
+	if(!m_stream)
+	{
+		throw VobParserFileNotFoundException(dirname);
+	}
+	else
+	{
+		m_pktcount =3D DVDFileSize(m_stream);
+	}
+
+	Reset();
+}
+
+// ---------------------------------------------------------------------=
-------
+
+VobParser::~VobParser()
+{
+	if (m_stream)
+		DVDCloseFile(m_stream);
+
+	if (m_dvdhandle)
+		DVDClose(m_dvdhandle);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetPacketCount() const
+{
+	return m_pktcount;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetPacketIndex() const
+{
+	return m_pktindex;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+char* VobParser::GetCurrentPacketData() const
+{
+	return (char*)m_buff;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::ParseNextPacket(const CellsListType & Cells)
+{
+	if(GetNextPacket())
+	{=09
+		pktinfo.identifier =3D GetNext32Bits();
+		if((pktinfo.identifier & VOB_SLICE) !=3D VOB_SLICE || (pktinfo.identif=
ier & PACK_HEADER) !=3D PACK_HEADER)
+		{
+			// Invalid block start code
+			throw VobParserInvalidPacketException(CURRENT_OFFSET-4);
+		}
+	=09
+		ParseSCR(); // System Clock Reference
+
+		// Program Mux Rate (measured in units of 50 bytes/second)
+		pktinfo.program_mux_rate =3D (GetNext8Bits() << 14) |=20
+			(GetNext8Bits() << 6) | (GetNext8Bits() >> 2);
+
+		// Skip Pack stuffing length
+		int stuffing_nb =3D GetNext8Bits() & 0x07;
+		SkipNBytes(stuffing_nb);
+	=09
+		uint32_t _Header =3D GetNext32Bits();
+		int _StreamID;
+		if ((_Header & VOB_SLICE) =3D=3D VOB_SLICE)
+		{
+			_StreamID =3D _Header & 0xFF;
+			if (_StreamID =3D=3D SYSTEM_HEADER)
+			{
+				// skip the system header data
+				uint16_t _size =3D GetNext16Bits();
+				SkipNBytes(_size);
+
+				while (AvailablePacketData())
+				{
+					_Header =3D GetNext32Bits();
+					uint8_t _StreamId =3D _Header & 0xFF;
+					if (_StreamId =3D=3D PRIVATE_STREAM2)
+					{
+						debug("Navigation pack {\n");
+						inc_lvl();
+						debug(QString("SCR: %1.%2\n").arg(pktinfo.scr).arg(pktinfo.scr_ext=
));
+						debug(QString("Program mux rate: %1 (%2 bps)\n").arg(pktinfo.progr=
am_mux_rate).arg(pktinfo.program_mux_rate * 50 * 8));
+						ParseNavPacket();
+						dec_lvl();
+						debug("}\n");
+					}
+					else
+					{
+						// skip these data
+						uint16_t _size =3D GetNext16Bits();
+						SkipNBytes(_size);
+					}
+				}
+				if (IsNewCell()) {
+					CellListElem* cell =3D Cells.at(GetVobID(), GetCellID());
+
+					if (cell !=3D NULL)
+					{
+						cell->found =3D true;
+						if (m_dsi.nv_pck_scr =3D=3D 0)
+							m_pci_vob_timecode_offset =3D m_pci.vobu_s_ptm / 90;
+						m_demuxer.SetBoundary(m_pci.vobu_s_ptm/90 - m_pci_vob_timecode_off=
set, cell->nb_frames * cell->frame_dur, cell);
+					}
+				}
+				if (m_pci.btn_ns !=3D 0)
+				{ // there are some buttons
+					uint32_t t3 =3D m_pci.vobu_s_ptm/90 - m_pci_vob_timecode_offset;
+					uint32_t t4 =3D m_pci.vobu_e_ptm/90 - m_pci_vob_timecode_offset;
+					m_demuxer.ProcessStream(SUBSTREAM_PCI, &m_buff[m_pci_position], m_p=
ci_size+2, t3, t4,=20
+						QString("# %1 -> %2 / %3 / %4 / %5 / %6 / off %7\n")
+						.arg(m_pci.vobu_s_ptm/90).arg(m_pci.vobu_e_ptm/90)
+						.arg(m_dsi.c_eltm, 0, 16).arg(m_pci.c_eltm, 0, 16)
+						.arg(t3).arg(t4).arg(m_pci_vob_timecode_offset));
+					=09
+				}
+			}
+			else if ((_StreamID & VIDEO_STREAM) =3D=3D VIDEO_STREAM)
+			{
+				debug("Video pack {}\n");
+				ParseVideoPacket();
+			}
+			else if ((_StreamID & AUDIO_STREAM) =3D=3D AUDIO_STREAM)
+			{
+				debug("Audio pack {}\n");
+				ParseAudioPacket(_StreamID);
+			}
+			else if (_StreamID =3D=3D PRIVATE_STREAM1)
+			{
+				debug("Private stream 1 pack {\n");
+				inc_lvl();
+				ParsePrivateStream1();
+				dec_lvl();
+				debug("}\n");
+			}
+			else
+			{
+				uint16_t _size =3D GetNext16Bits();
+				SkipNBytes(_size);
+				debug("Unknown slice type\n");
+			}
+
+			if (m_bFirstPacket && _StreamID !=3D SYSTEM_HEADER)
+			{
+				m_bFirstPacket =3D false;
+				m_startdts =3D pktinfo.dts;
+				m_startpts =3D pktinfo.pts;
+			}
+		}
+		else
+		{
+			debug("Unknown start code\n");
+		}
+	=09
+		m_pktindex++;
+	}
+	else
+	{
+		return false;
+	}
+
+	return true;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::AvailablePacketData() const
+{
+	return (m_index < DVD_VIDEO_LB_LEN);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::GetNextPacket()
+{
+	m_index =3D 0;
+
+	return (DVDReadBlocks(m_stream, m_pktindex, 1, m_buff) =3D=3D 1);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetNext32Bits()
+{
+	uint32_t result =3D 0;
+	result |=3D m_buff[m_index++];
+	result <<=3D 8;
+	result |=3D m_buff[m_index++];
+	result <<=3D 8;
+	result |=3D m_buff[m_index++];
+	result <<=3D 8;
+	result |=3D m_buff[m_index++];
+    return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint16_t VobParser::GetNext16Bits()
+{
+	uint32_t result =3D 0;
+	result |=3D m_buff[m_index++];
+	result <<=3D 8;
+	result |=3D m_buff[m_index++];
+	return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint8_t VobParser::GetNext8Bits()
+{
+	return m_buff[m_index++];
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::SkipNBytes(int n)
+{
+	m_index +=3D n;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseSCR()
+{
+
+/* From http://dvd.sourceforge.net/dvdinfo/packhdr.html
+
+	      Byte 4                      Byte 5
+	      +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+          | 7| 6| 5| 4| 3| 2| 1| 0|   | 7| 6| 5| 4| 3| 2| 1| 0|
+	      +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+SCR bits  |f0|f1|32|31|30|f1|29|28|   |27|26|25|24|23|22|21|20|
+          +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+
+	      Byte 6                      Byte 7
+	      +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+          | 7| 6| 5| 4| 3| 2| 1| 0|   | 7| 6| 5| 4| 3| 2| 1| 0|
+	      +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+SCR bits  |19|18|17|16|15|f1|14|13|   |12|11|10| 9| 8| 7| 6| 5|
+          +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+
+	      Byte 8                      Byte 9
+	      +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+          | 7| 6| 5| 4| 3| 2| 1| 0|   | 7| 6| 5| 4| 3| 2| 1| 0|
+	      +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+SCR bits  | 4| 3| 2| 1| 0|f1|e8|e7|   |e6|e5|e4|e3|e2|f1|e0|c1|
+          +--+--+--+--+--+--+--+--+   +--+--+--+--+--+--+--+--+
+
+  fx =3D bit value fixed to x
+  ex =3D bit x of scr_ext
+*/
+
+	uint8_t byte4, byte5, byte6, byte7, byte8, byte9;
+	byte4 =3D GetNext8Bits();	byte5 =3D GetNext8Bits();
+	byte6 =3D GetNext8Bits();	byte7 =3D GetNext8Bits();
+	byte8 =3D GetNext8Bits();	byte9 =3D GetNext8Bits();
+
+	assert((byte4 & 0xc4) =3D=3D 0x44);
+	assert(byte6 & 0x04);
+	assert(byte8 & 0x04);
+	assert(byte9 & 0x01);
+	=09
+	uint64_t scr =3D 0;
+	scr |=3D ((((byte4 & 0x38) >> 1) | (byte4 & 0x03)) << 28);
+	scr |=3D (byte5 << 20);
+	scr |=3D ((((byte6 & 0xf8) >> 1) | (byte6 & 0x03)) << 13);
+	scr |=3D (byte7 << 5);
+	scr |=3D ((byte8 & 0xf8) >> 3);
+
+	uint16_t scr_ext =3D 0;
+	scr_ext |=3D ((byte8 & 0x03) << 7);
+	scr_ext |=3D ((byte9 & 0xfe) >> 1);
+
+	pktinfo.scr =3D scr;
+	pktinfo.scr_ext =3D scr_ext;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseNavPacket()
+{
+	uint32_t endStreamIndex =3D 0;
+	uint32_t position =3D m_index;
+	uint16_t length =3D GetNext16Bits();
+	endStreamIndex =3D m_index + length;
+	uint8_t substreamID =3D GetNext8Bits();
+=09
+	switch(substreamID)
+	{
+	case SUBSTREAM_PCI:
+		debug("PCI {\n");
+		inc_lvl();
+		ParsePCI();
+		m_pci_position =3D position-4; // keep the Private Stream 2 header
+		m_pci_size =3D length+4;
+		dec_lvl();
+		debug("}\n");
+		break;
+	case SUBSTREAM_DSI:
+		debug("DSI {\n");
+		inc_lvl();
+		ParseDSI();
+		dec_lvl();
+		debug("}\n");
+		break;
+	default:
+	  debug(QString("ParseNavPacket: unknown substream id @LBA=3D%1\n").arg=
(m_pktindex));
+	}
+=09
+	m_index =3D endStreamIndex;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePCI()
+{
+	int i,j;
+	uint8_t onebyte;
+
+	// PCI General Information
+	m_pci.nv_pck_lbn =3D GetNext32Bits();
+	m_pci.vobu_cat =3D GetNext16Bits();
+	m_pci.reserved1 =3D GetNext16Bits();
+	m_pci.vobu_uop_ctl =3D GetNext32Bits();
+	m_pci.vobu_s_ptm =3D GetNext32Bits();
+	m_pci.vobu_e_ptm =3D GetNext32Bits();
+	m_pci.vobu_se_e_ptm =3D GetNext32Bits();
+	m_pci.c_eltm =3D GetNext32Bits();
+	memcpy(m_pci.vobu_isrc, &m_buff[m_index],32*1);=09
+	SkipNBytes(32*1);
+
+	// Non Seamless Angle Information
+	memcpy(m_pci.nsml_agli_dsta, &m_buff[m_index], 9*4);
+	SkipNBytes(9*4);
+
+	// Highlight General Information=20
+	m_pci.hli_ss =3D GetNext16Bits();
+	m_pci.hli_s_ptm =3D GetNext32Bits();
+	m_pci.hli_e_ptm =3D GetNext32Bits();
+	m_pci.btn_sl_e_ptm =3D GetNext32Bits();
+	m_pci.btn_md =3D GetNext16Bits();
+	m_pci.btn_sn =3D GetNext8Bits();
+	m_pci.btn_ns =3D GetNext8Bits();
+	m_pci.nsl_btn_ns =3D GetNext8Bits();
+	m_pci.reserved1 =3D GetNext8Bits();
+	m_pci.fosl_btnn =3D GetNext8Bits();
+	m_pci.foac_btnn =3D GetNext8Bits();
+=09
+	// Button Color Information Table=20
+	for(i =3D 0; i < 3; i++)
+		for(j =3D 0; j < 2; j++)
+			m_pci.btn_coli[i][j] =3D GetNext32Bits();
+
+	// Button Information
+	for(i =3D 0; i < 36; i++)
+	{
+		onebyte =3D GetNext8Bits();
+		m_pci.btnit[i].btn_coln =3D (onebyte & 0xC0) >> 6;
+		m_pci.btnit[i].start_x =3D (onebyte & 0x3F) << 4;
+
+		onebyte =3D GetNext8Bits();
+		m_pci.btnit[i].start_x |=3D (onebyte & 0xF0) >> 4;
+		m_pci.btnit[i].end_x =3D (onebyte & 0x03) << 8;
+
+		onebyte =3D GetNext8Bits();
+		m_pci.btnit[i].end_x |=3D onebyte;
+
+		onebyte =3D GetNext8Bits();
+		m_pci.btnit[i].auto_action_flag =3D (onebyte & 0xC0) >> 6;
+		m_pci.btnit[i].start_y =3D (onebyte & 0x3F) << 4;
+	=09
+		onebyte =3D GetNext8Bits();
+		m_pci.btnit[i].start_y |=3D (onebyte & 0xF0) >> 4;
+		m_pci.btnit[i].end_y =3D (onebyte & 0x03) << 8;
+	=09
+		onebyte =3D GetNext8Bits();
+		m_pci.btnit[i].end_y |=3D onebyte;
+
+		m_pci.btnit[i].up =3D GetNext8Bits() & 0x3F;
+		m_pci.btnit[i].down =3D GetNext8Bits() & 0x3F;
+		m_pci.btnit[i].left =3D GetNext8Bits() & 0x3F;
+		m_pci.btnit[i].right =3D GetNext8Bits() & 0x3F;
+	=09
+		memcpy(m_pci.btnit[i].vm_cmd, &m_buff[m_index],8*1);
+		SkipNBytes(8*1);
+	}
+
+	debug(QString("nv_pck_lbn: %1\n").arg(m_pci.nv_pck_lbn));
+	debug(QString("vobu_cat: %1\n").arg(m_pci.vobu_cat));
+	debug(QString("reserved1: %1\n").arg(m_pci.reserved1));
+	debug(QString("vobu_uop_ctl: %1\n").arg(m_pci.vobu_uop_ctl));
+	debug(QString("vobu_s_ptm: %1\n").arg(m_pci.vobu_s_ptm));
+	debug(QString("vobu_e_ptm: %1\n").arg(m_pci.vobu_e_ptm));
+	debug(QString("vobu_se_e_ptm: %1\n").arg(m_pci.vobu_se_e_ptm));
+	debug(QString("e_eltm: %1\n").arg(m_pci.c_eltm));
+	debug(QString("vobu_isrc: ...\n").toAscii());
+	debug(QString("nsml_agli_dsta: ...\n").toAscii());
+	debug(QString("hli_ss: %1\n").arg(m_pci.hli_ss));
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseDSI()
+{
+	m_dsi.nv_pck_scr =3D GetNext32Bits();
+	m_dsi.nv_pck_lbn =3D GetNext32Bits();
+	m_dsi.vobu_ea =3D GetNext32Bits();
+	m_dsi.vobu_1stref_ea =3D GetNext32Bits();
+	m_dsi.vobu_2ndref_ea =3D GetNext32Bits();
+	m_dsi.vobu_3rdref_ea =3D GetNext32Bits();
+	m_dsi.vobu_vob_idn =3D GetNext16Bits();
+	m_dsi.reserved =3D GetNext8Bits();
+	m_dsi.vobu_c_idn =3D GetNext8Bits();
+	m_dsi.c_eltm =3D GetNext32Bits();
+
+	debug(QString("nv_pck_scr: %1\n").arg(m_dsi.nv_pck_scr));
+	debug(QString("nv_pck_lbn: %1\n").arg(m_dsi.nv_pck_lbn));
+	debug(QString("vobu_ea: %1\n").arg(m_dsi.vobu_ea));
+	debug(QString("vobu_1stref_ea: %1\n").arg(m_dsi.vobu_1stref_ea));
+	debug(QString("vobu_2ndref_ea: %1\n").arg(m_dsi.vobu_2ndref_ea));
+	debug(QString("vobu_3rdref_ea: %1\n").arg(m_dsi.vobu_3rdref_ea));
+	debug(QString("vobu_vob_idn: %1\n").arg(m_dsi.vobu_vob_idn));
+	debug(QString("reserved: %1\n").arg(m_dsi.reserved));
+	debug(QString("vobu_c_idn: %1\n").arg(m_dsi.vobu_c_idn));
+	debug(QString("c_eltm: %1\n").arg(m_dsi.c_eltm));
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint8_t GetBit(uint32_t data, uint8_t n)
+{
+	return ((data >> n) & 0x01);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePESHeaderDataContentFlag()
+{=09
+	uint8_t byte6 =3D GetNext8Bits();
+	assert((byte6 & 0xC0) =3D=3D 0x80);
+	pes_header_data_content.PES_scrambling_control =3D (byte6 & 0x30) >> 4;
+	pes_header_data_content.PES_priority =3D GetBit(byte6,3);
+	pes_header_data_content.data_alignment_indicator =3D GetBit(byte6,2);
+	pes_header_data_content.copyright =3D GetBit(byte6,1);
+	pes_header_data_content.original_or_copy =3D GetBit(byte6,0);
+
+	uint8_t byte7 =3D GetNext8Bits();
+	pes_header_data_content.PTS_flag =3D GetBit(byte7,7);
+	pes_header_data_content.DTS_flag =3D GetBit(byte7,6);
+	pes_header_data_content.ESCR_flag =3D GetBit(byte7,5);
+	pes_header_data_content.ES_rate_flag =3D GetBit(byte7,4);
+	pes_header_data_content.DSM_trick_mode_flag =3D GetBit(byte7,3);
+	pes_header_data_content.additionnal_copy_info_flag =3D GetBit(byte7,2);
+	pes_header_data_content.PES_CRC_flag =3D GetBit(byte7,1);
+	pes_header_data_content.PES_extension_flag =3D GetBit(byte7,0);
+=09
+	pes_header_data_content.PES_header_data_len =3D GetNext8Bits();
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint64_t VobParser::ParsePTS_DTS()
+{
+	// PTS and DTS have same format
+	uint64_t result =3D 0;
+
+	uint8_t byte0 =3D GetNext8Bits();
+	uint16_t word0 =3D GetNext16Bits();
+	uint16_t word1 =3D GetNext16Bits();
+
+	assert(word0 & 0x01);
+	assert(word1 & 0x01);
+
+	result |=3D (((byte0 & 0x0E) >> 1) << 30);
+	result |=3D ((word0 >> 1) << 15);
+	result |=3D (word1 >> 1);
+
+	return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePESHeaderData()
+{
+	uint8_t bytesLeft =3D pes_header_data_content.PES_header_data_len;
+	if(pes_header_data_content.PTS_flag)
+	{
+		// PTS : Presentation Time Stamp
+		pktinfo.pts =3D ParsePTS_DTS();
+		bytesLeft -=3D 5;
+		if (m_bFirstPacket)
+		{
+			m_startpts =3D pktinfo.pts;
+		}
+		pktinfo.pts -=3D m_startpts;
+	}
+	if(pes_header_data_content.DTS_flag)
+	{
+		// DTS : Decoding Time Stamp
+		pktinfo.dts =3D ParsePTS_DTS();
+		bytesLeft -=3D 5;
+		if (m_bFirstPacket)
+		{
+			m_startdts =3D pktinfo.dts;
+		}
+		pktinfo.dts -=3D m_startdts;
+	}
+	m_bFirstPacket =3D false;
+
+	// Skip the rest
+	SkipNBytes(bytesLeft);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParseVideoPacket()
+{
+	uint16_t length =3D GetNext16Bits();
+	ParsePESHeaderDataContentFlag();
+	ParsePESHeaderData();
+
+	m_demuxer.ProcessStream(VIDEO_STREAM, &m_buff[m_index],
+		length - 3 - pes_header_data_content.PES_header_data_len, pktinfo.dts/=
90, pktinfo.pts/90,
+		QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startpts/9=
0).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+}
+
+void VobParser::ParseAudioPacket(int StreamID)
+{
+	uint16_t length =3D GetNext16Bits();
+	ParsePESHeaderDataContentFlag();
+	ParsePESHeaderData();
+
+	m_demuxer.ProcessStream(StreamID, &m_buff[m_index],
+		length - 3 - pes_header_data_content.PES_header_data_len, pktinfo.pts/=
90, pktinfo.dts/90,
+		QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startpts/9=
0).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::ParsePrivateStream1()
+{
+	uint16_t length =3D GetNext16Bits();=09
+	uint16_t dataStartIndex =3D m_index;
+	// PES : Packetized Elementary Stream
+	ParsePESHeaderDataContentFlag();
+	ParsePESHeaderData();
+	uint8_t substreamID =3D GetNext8Bits();
+
+	uint32_t t3 =3D m_pci.vobu_s_ptm/90 - m_pci_vob_timecode_offset;
+	uint32_t t4 =3D m_pci.vobu_e_ptm/90 - m_pci_vob_timecode_offset;
+	if(substreamID >=3D SUBSTREAM_SUB_LOW && substreamID < SUBSTREAM_SUB_HI=
GH)
+	{
+		debug(QString("Subtitles streamID =3D 0x%1\n").arg(substreamID, 0, 16)=
);
+
+		// .sub files the VobSub way (includes the whole packet)
+		m_demuxer.ProcessStream(substreamID, m_buff, DVD_VIDEO_LB_LEN, t3, t4,=
=20
+		    QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startp=
ts/90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+	}
+	else if(substreamID >=3D SUBSTREAM_AC3_LOW && substreamID < SUBSTREAM_A=
C3_HIGH)
+	{
+		debug(QString("AC3 streamID =3D 0x%1\n").arg(substreamID, 0, 16));
+
+		// Skip frame header number
+		SkipNBytes(1);
+		// Skip first access unit pointer
+		SkipNBytes(2);
+
+		uint16_t ac3DataLen =3D length - (m_index - dataStartIndex);
+		m_demuxer.ProcessStream(substreamID, &m_buff[m_index], ac3DataLen, t3,=
 t4,=20
+		    QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startp=
ts/90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+	}
+	else if(substreamID >=3D SUBSTREAM_DTS_LOW && substreamID < SUBSTREAM_D=
TS_HIGH)
+	{
+		debug(QString("DTS streamID =3D 0x%1\n").arg(substreamID, 0, 16));
+	=09
+		// Skip frame header number
+		SkipNBytes(1);
+		// Skip first access unit pointer
+		SkipNBytes(2);
+
+		uint16_t ac3DataLen =3D length - (m_index - dataStartIndex);
+		m_demuxer.ProcessStream(substreamID, &m_buff[m_index], ac3DataLen, t3,=
 t4,=20
+		    QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startp=
ts/90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+	}
+	else if(substreamID >=3D SUBSTREAM_PCM_LOW && substreamID < SUBSTREAM_P=
CM_HIGH)
+	{
+		debug(QString("LPCM streamID =3D 0x%1\n").arg(substreamID, 0, 16));
+
+		// Skip unknown data
+		SkipNBytes(6);
+
+		uint16_t ac3DataLen =3D length - (m_index - dataStartIndex);
+		m_demuxer.ProcessStream(substreamID, &m_buff[m_index], ac3DataLen, t3,=
 t4,=20
+			QString("DTS %1 PTS %2 - %3 %4\n").arg(m_startdts/90).arg(m_startpts/=
90).arg(pktinfo.dts/90).arg(pktinfo.pts/90));
+	}
+	else
+	{
+		debug("Unknown\n");
+	}
+}
+
+// ---------------------------------------------------------------------=
-------
+
+void VobParser::Reset()
+{
+	memset(&m_dsi, 0, sizeof(m_dsi));
+	memset(&pktinfo, 0, sizeof(pktinfo));
+	memset(&pes_header_data_content, 0, sizeof(pes_header_data_content));
+	previous_vobid =3D -1;
+	previous_cellid =3D -1;
+	m_index =3D 0;
+	m_pktindex =3D 0;
+	DVDFileSeek(m_stream,0);
+}
+
+// ---------------------------------------------------------------------=
-------
+
+bool VobParser::IsNewCell()
+{
+	bool result =3D (GetVobID() !=3D previous_vobid ||
+					GetCellID() !=3D previous_cellid);
+=09
+    previous_vobid =3D GetVobID();
+    previous_cellid =3D GetCellID();
+	if (result)
+		m_bFirstPacket =3D true;
+
+	return result;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+inline uint8_t VobParser::GetVobID() const
+{
+	return m_dsi.vobu_vob_idn;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+inline uint8_t VobParser::GetCellID() const
+{
+	return m_dsi.vobu_c_idn;
+}
+
+// ---------------------------------------------------------------------=
-------
+
+uint32_t VobParser::GetCellSCR() const
+{
+	return m_dsi.nv_pck_scr;
+}
+
+// ---------------------------------------------------------------------=
-------
+=20
+void SubDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+	int i;
+
+	if (!m_TimecodeFile)
+	{
+		QString m_filename =3D m_Filename;
+		m_filename +=3D ".idx";
+		m_TimecodeFile =3D fopen(qPrintable(m_filename),"w");
+		fwrite("# VobSub index file, v7 (do not modify this line!)\n#\n", 1, 5=
3, m_TimecodeFile);
+		fwrite("# Settings\n\n# Original frame size\nsize: ", 1, 40, m_Timecod=
eFile);
+		fprintf(m_TimecodeFile, "%dx%d\n\n", m_width, m_height);
+		fwrite("# Origin, relative to the upper-left corner, can be overloaded=
 by aligment\n"
+		       "org: 0, 0\n\n"
+		       "# Image scaling (hor,ver), origin is at the upper-left corner =
or at the alignment coord (x, y)\n"
+		       "scale: 100%, 100%\n\n"
+		       "# Alpha blending\n"
+		       "alpha: 100%\n\n"
+		       "# Smoothing for very blocky images (use OLD for no filtering)\=
n"
+		       "smooth: OFF\n\n"
+		       "# In millisecs\n"
+		       "fadein/out: 50, 50\n\n"
+		       "# Force subtitle placement relative to (org.x, org.y)\n"
+		       "align: OFF at LEFT TOP\n\n"
+		       "# For correcting non-progressive desync. (in millisecs or hh:m=
m:ss:ms)\n"
+		       "# Note: Not effective in DirectVobSub, use \"delay: ... \" ins=
tead.\n"
+		       "time offset: 0\n\n"
+		       "# ON: displays only forced subtitles, OFF: shows everything\n"
+               "forced subs: OFF\n\n"
+               "# The original palette of the DVD\n"
+			   "palette: ", 1, 692, m_TimecodeFile);
+		for (i=3D0; i<15; i++)
+		{
+			fprintf(m_TimecodeFile, "%06x, ", m_palette[i]);
+		}
+		fprintf(m_TimecodeFile, "%06x\n\n", m_palette[i]);
+		fwrite("# Custom colors (transp idxs and the four colors)\n"
+		       "custom colors: OFF, tridx: 0000, colors: 000000, 000000, 00000=
0, 000000\n\n"
+		       "# Language index in use\n"
+		       "langidx: 0\n\n"
+		       "id: ", 1, 163, m_TimecodeFile);
+		if (m_language)
+			fprintf(m_TimecodeFile, "%c%c", m_language >> 8, m_language);
+		else
+			fwrite("un", 1, 2, m_TimecodeFile);
+		fwrite(", index: 0\n"
+		       "# Decomment next line to activate alternative name in DirectVo=
bSub / Windows Media Player 6.x\n"
+		       "# alt: ", 1, 112, m_TimecodeFile);
+        fprintf(m_TimecodeFile, "%s\n\n", DecodeLanguage(m_language));
+	}
+	int32_t delay =3D start_time + m_start_timecode;
+	int millisecond =3D delay % 1000;
+	delay /=3D 1000;
+	int second =3D delay % 60;
+	delay /=3D 60;
+	int minute =3D delay % 60;
+	delay /=3D 60;
+	fprintf(m_TimecodeFile, "timestamp: %02d:%02d:%02d:%03d, filepos: %09x\=
n", delay,minute,second,millisecond,filepos);
+}
+
+void BtnDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+//static uint32_t time =3D0;
+	m_TimecodeFile =3D GetTimecodeFile();
+	if (start_time > m_last_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_last_start_t=
imecode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+		m_start_timecode =3D start_time;
+	}
+//fwrite(debug.c_str(), debug.size(), 1, m_TimecodeFile);
+//fprintf(m_TimecodeFile, "# %d =3D> %d\n",time, time + end_time - start=
_time);
+//time +=3D end_time - start_time;
+	m_last_start_timecode =3D start_time;
+	m_last_end_timecode =3D end_time;
+}
+
+void DTSDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+	if (start_time > m_last_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_last_start_t=
imecode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+		m_start_timecode =3D start_time;
+	}
+	m_last_start_timecode =3D start_time;
+	m_last_end_timecode =3D end_time;
+}
+
+void LPCMDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t en=
d_time, uint64_t filepos, const QString& debug)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+	if (start_time > m_last_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timeco=
de) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+		m_start_timecode =3D start_time;
+	}
+	m_last_start_timecode =3D start_time;
+	m_last_end_timecode =3D end_time;
+}
+
+void MPADemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+}
+
+void AC3DemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t end=
_time, uint64_t filepos, const QString& debug)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+	if (start_time > m_last_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_last_start_t=
imecode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (start_time - m_last_end_timecode=
) / 1000.0);
+		m_start_timecode =3D start_time;
+	}
+	m_last_start_timecode =3D start_time;
+	m_last_end_timecode =3D end_time;
+}
+
+void VideoDemuxWriter::WriteTimecodeInfo(uint32_t start_time, uint32_t e=
nd_time, uint64_t filepos, const QString& debug)
+{
+	// TODO detect gaps in the stream
+}
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+void VideoDemuxWriter::ProcessStream(uint8_t* buff, uint32_t size, uint3=
2_t start_time, uint32_t end_time, const QString& debug)
+{
+	if (m_parser =3D=3D NULL)
+		m_parser =3D new M2VParser;
+=09
+	m_parser->WriteData(buff, size);
+
+	MPEG2ParserState state =3D m_parser->GetState();
+
+	while (state =3D=3D MPV_PARSER_STATE_FRAME)=20
+	{
+		delete m_parser->ReadFrame();
+		state =3D m_parser->GetState();
+	}
+
+	Write(buff, size, start_time, end_time, debug);=20
+}
+
+void VideoDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t dur=
ation, const CellListElem *cell)
+{
+	if (m_parser !=3D NULL)
+	{
+		m_parser->SetEOS();
+
+		MPEG2ParserState state =3D m_parser->GetState();
+
+		while (state =3D=3D MPV_PARSER_STATE_FRAME)=20
+		{
+			MPEGFrame* current_frame =3D m_parser->ReadFrame();
+			if ((current_frame->timecode + current_frame->duration) / 1000000 > m=
_last_end_timecode)
+			{
+				m_last_start_timecode =3D current_frame->timecode / 1000000;
+				m_last_end_timecode =3D (current_frame->timecode + current_frame->du=
ration) / 1000000;
+			}
+			delete current_frame;
+
+			state =3D m_parser->GetState();
+		}
+	=09
+		delete m_parser;
+	}
+=09
+	m_parser =3D new M2VParser();
+
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	if (m_end_timecode !=3D 0)
+	{
+		if (m_is_still) {
+			fwrite(" (Still)\n", 1, 9, m_TimecodeFile);
+			fprintf(m_TimecodeFile, "%lf,%lf\n", (m_end_timecode - m_start_timeco=
de) / 1000.0, 1000.0 / (m_end_timecode - m_start_timecode));
+		}
+		else if (m_last_end_timecode < m_end_timecode)
+		{
+			fprintf(m_TimecodeFile, "\n%lf\n", (m_last_end_timecode - m_start_tim=
ecode) / 1000.0);
+			fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_tim=
ecode) / 1000.0);
+		}
+		else
+		{
+			if (m_last_end_timecode > m_end_timecode)
+				qWarning("There is more video that indicated in the cell.");
+			fprintf(m_TimecodeFile, "\n%lf\n", (m_last_end_timecode - m_start_tim=
ecode) / 1000.0);
+		}
+	}
+
+	m_start_timecode =3D start_timecode;
+	m_end_timecode =3D start_timecode + duration;
+	m_last_end_timecode =3D start_timecode;
+	m_is_still =3D cell->isStill;
+
+	fprintf(m_TimecodeFile, "\n# VOB %d Cell %d", cell->vobid, cell->cellid=
);
+}
+
+void AC3DemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+		{
+			if (m_last_end_timecode > m_end_timecode)
+				qWarning("There is more AC3 audio that indicated in the cell.");
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		}
+	}
+
+	m_start_timecode =3D start_timecode;
+	m_end_timecode =3D start_timecode + duration;
+	m_last_end_timecode =3D start_timecode;
+	m_last_start_timecode =3D start_timecode;
+
+	fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+void DTSDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+		{
+			if (m_last_end_timecode > m_end_timecode)
+				qWarning("There is more DTS audio that indicated in the cell.");
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		}
+	}
+
+	m_start_timecode =3D start_timecode;
+	m_end_timecode =3D start_timecode + duration;
+	m_last_end_timecode =3D start_timecode;
+	m_last_start_timecode =3D start_timecode;
+
+	fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+void LPCMDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t dura=
tion, const CellListElem *cell)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+		{
+			if (m_last_end_timecode > m_end_timecode)
+				qWarning("There is more PCM audio that indicated in the cell.");
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		}
+	}
+
+	m_start_timecode =3D start_timecode;
+	m_end_timecode =3D start_timecode + duration;
+	m_last_end_timecode =3D start_timecode;
+	m_last_start_timecode =3D start_timecode;
+
+	fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+void MPADemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+}
+
+void SubDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+	if (start_timecode =3D=3D 0)
+		m_start_timecode =3D m_end_timecode;
+	m_end_timecode +=3D duration;
+}
+
+void BtnDemuxWriter::SetBoundary(uint32_t start_timecode, uint32_t durat=
ion, const CellListElem *cell)
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+		{
+			if (m_last_end_timecode > m_end_timecode)
+				qWarning("There is more Button data that indicated in the cell.");
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		}
+	}
+
+	m_start_timecode =3D start_timecode;
+	m_end_timecode =3D start_timecode + duration;
+	m_last_end_timecode =3D start_timecode;
+	m_last_start_timecode =3D start_timecode;
+
+	fprintf(m_TimecodeFile, "\n# VOB %d Cell %d\n", cell->vobid, cell->cell=
id);
+}
+
+VideoDemuxWriter::~VideoDemuxWriter()
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+	if (m_parser !=3D NULL)
+	{
+		m_parser->SetEOS();
+
+		MPEG2ParserState state =3D m_parser->GetState();
+
+		while (state =3D=3D MPV_PARSER_STATE_FRAME)=20
+		{
+			MPEGFrame* current_frame =3D m_parser->ReadFrame();
+			if ((current_frame->timecode + current_frame->duration) / 1000000 > m=
_last_end_timecode)
+			{
+				m_last_start_timecode =3D current_frame->timecode / 1000000;
+				m_last_end_timecode =3D (current_frame->timecode + current_frame->du=
ration) / 1000000;
+			}
+			delete current_frame;
+
+			state =3D m_parser->GetState();
+		}
+		delete m_parser;
+	}
+
+
+	if (m_end_timecode !=3D 0)
+	{
+		if (m_is_still) {
+			fwrite(" (Still)\n", 1, 9, m_TimecodeFile);
+			fprintf(m_TimecodeFile, "%lf,%lf\n", (m_end_timecode - m_start_timeco=
de) / 1000.0, 1000.0 / (m_end_timecode - m_start_timecode));
+		}
+		else if (m_last_end_timecode < m_end_timecode)
+		{
+			fprintf(m_TimecodeFile, "\n%lf\n", (m_last_end_timecode - m_start_tim=
ecode) / 1000.0);
+			fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_tim=
ecode) / 1000.0);
+		}
+		else
+			fprintf(m_TimecodeFile, "\n%lf\n", (m_end_timecode - m_start_timecode=
) / 1000.0);
+	}
+}
+
+AC3DemuxWriter::~AC3DemuxWriter()
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+			fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+	}
+}
+
+DTSDemuxWriter::~DTSDemuxWriter()
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+			fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+	}
+}
+
+LPCMDemuxWriter::~LPCMDemuxWriter()
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+			fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+	}
+}
+
+BtnDemuxWriter::~BtnDemuxWriter()
+{
+	m_TimecodeFile =3D GetTimecodeFile();
+
+	// handle ending of the previous cell
+	if (m_last_end_timecode < m_end_timecode)
+	{
+		if (m_last_end_timecode > m_start_timecode)
+			fprintf(m_TimecodeFile, "%lf\n", (m_last_end_timecode - m_start_timec=
ode) / 1000.0);
+		fprintf(m_TimecodeFile, "gap,%lf\n", (m_end_timecode - m_last_end_time=
code) / 1000.0);
+	}
+	else
+	{
+		if (m_end_timecode !=3D 0)
+			fprintf(m_TimecodeFile, "%lf\n", (m_end_timecode - m_start_timecode) =
/ 1000.0);
+	}
+}
+
+WavWriter::~WavWriter()
+{
+	if (m_file)
+	{
+		uint8_t _tinteger[4];
+
+		fseek(m_file, m_size_position2, SEEK_SET);
+		_tinteger[0] =3D m_size & 0xFF;
+		_tinteger[1] =3D (m_size >> 8) & 0xFF;
+		_tinteger[2] =3D (m_size >> 16) & 0xFF;
+		_tinteger[3] =3D (m_size >> 24) & 0xFF;
+		fwrite(_tinteger,4,1, m_file);
+	=09
+		m_size +=3D 36;
+		fseek(m_file, m_size_position1, SEEK_SET);
+		_tinteger[0] =3D m_size & 0xFF;
+		_tinteger[1] =3D (m_size >> 8) & 0xFF;
+		_tinteger[2] =3D (m_size >> 16) & 0xFF;
+		_tinteger[3] =3D (m_size >> 24) & 0xFF;
+		fwrite(_tinteger,4,1, m_file);
+	}
+}
+
+void WavWriter::Write(uint8_t* buff, uint32_t size, uint32_t start_time,=
 uint32_t end_time, const QString& debug)
+{
+	if (m_bit_depth !=3D 16) // not supported
+		return;
+	if (m_file =3D=3D NULL)
+	{
+		uint8_t _tinteger[4];
+		m_file =3D OpenOuputFile();
+
+		// create the WAV header
+		//   RIFF head
+		fwrite("RIFF",4,1, m_file);
+		m_size_position1 =3D ftell(m_file);
+		fwrite("0000",4,1, m_file);
+		fwrite("WAVE",4,1, m_file);
+	=09
+		//   Format head
+		fwrite("fmt ",4,1, m_file);
+		_tinteger[0] =3D 16;
+		_tinteger[1] =3D 0;
+		_tinteger[2] =3D 0;
+		_tinteger[3] =3D 0;
+		fwrite(_tinteger,4,1, m_file);
+	=09
+		_tinteger[0] =3D 1;
+		fwrite(_tinteger,2,1, m_file); // PCM
+	=09
+		_tinteger[0] =3D m_channel_nb;
+		_tinteger[1] =3D 0;
+		fwrite(_tinteger,2,1, m_file); // Channels
+	=09
+		_tinteger[0] =3D m_sample_rate & 0xFF;
+		_tinteger[1] =3D (m_sample_rate >> 8) & 0xFF;
+		_tinteger[2] =3D (m_sample_rate >> 16) & 0xFF;
+		_tinteger[3] =3D (m_sample_rate >> 24) & 0xFF;
+		fwrite(_tinteger,4,1, m_file); // Sampling freq
+	=09
+		uint32_t _byte_rate =3D (m_sample_rate * m_channel_nb * m_bit_depth) >=
> 3;
+		_tinteger[0] =3D _byte_rate & 0xFF;
+		_tinteger[1] =3D (_byte_rate >> 8) & 0xFF;
+		_tinteger[2] =3D (_byte_rate >> 16) & 0xFF;
+		_tinteger[3] =3D (_byte_rate >> 24) & 0xFF;
+		fwrite(_tinteger,4,1, m_file); // Byte Rate
+	=09
+		uint16_t _block_align =3D (m_channel_nb * m_bit_depth) >> 3;
+		_tinteger[0] =3D _block_align & 0xFF;
+		_tinteger[1] =3D (_block_align >> 8) & 0xFF;
+		fwrite(_tinteger,2,1, m_file); // Block Align
+	=09
+		_tinteger[0] =3D m_bit_depth;
+		_tinteger[1] =3D 0;
+		fwrite(_tinteger,2,1, m_file); // Block Align
+	=09
+		//   Data head
+		fwrite("data",4,1, m_file);
+		m_size_position2 =3D ftell(m_file);
+		fwrite("0000",4,1, m_file);
+		m_size =3D 0;
+	}
+	uint16_t _tmp;
+	for (size_t i=3D0; i < size; i+=3D2) {
+		_tmp =3D buff[i];
+		_tmp <<=3D 8;
+		_tmp +=3D buff[i+1];
+		buff[i] =3D _tmp & 0xFF;
+		buff[i+1] =3D _tmp >> 8;
+	}
+	Writer::Write(buff, size, start_time, end_time, debug);
+	m_size +=3D size;
+}

Added: trunk/DvdMenuXtractor/vobparser/VobParser.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/VobParser.h	2007-01-22 11:21:16 UTC (=
rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/VobParser.h	2007-01-28 16:48:11 UTC (=
rev 1270)
@@ -0,0 +1,621 @@
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// VOBParser class
+// Copyright =A9 2002 : Christophe PARIS (christophe.paris at free.fr)
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+#ifndef _VOB_PARSER_H_
+#define _VOB_PARSER_H_
+// ---------------------------------------------------------------------=
-------
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+#define HAVE_INTTYPES_H
+#include "dvdread/ifo_read.h"
+#include "mpegparser/M2VParser.h"
+
+#include <QList>
+#include <QString>
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+#define VIDEO_STREAM_TYPE		0x01
+#define AUDIO_STREAM_TYPE		0x02
+#define SUB_STREAM_TYPE			0x04
+
+#define AC3_STREAM_TYPE			(AUDIO_STREAM_TYPE | 0x08)
+#define DTS_STREAM_TYPE			(AUDIO_STREAM_TYPE | 0x10)
+#define PCM_STREAM_TYPE			(AUDIO_STREAM_TYPE | 0x20)
+
+
+#define AUDIO_STREAM		0xC0
+#define VIDEO_STREAM		0xE0
+
+#define SUBSTREAM_PCI       0x00
+#define SUBSTREAM_DSI       0x01
+
+#define SUBSTREAM_SUB_LOW		0x20
+#define SUBSTREAM_SUB_HIGH		(SUBSTREAM_SUB_LOW + 32)
+
+#define SUBSTREAM_AC3_LOW		0x80
+#define SUBSTREAM_AC3_HIGH		(SUBSTREAM_AC3_LOW + 8)
+
+#define SUBSTREAM_DTS_LOW		0x88
+#define SUBSTREAM_DTS_HIGH		(SUBSTREAM_DTS_LOW + 8)
+
+#define SUBSTREAM_PCM_LOW		0xA0
+#define SUBSTREAM_PCM_HIGH		(SUBSTREAM_PCM_LOW + 8)
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Type
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+typedef struct=20
+{
+	unsigned int vobid;
+	unsigned int cellid;
+	unsigned int start_frame;
+	unsigned int end_frame;
+	unsigned int nb_frames;
+	uint32_t start_sector;
+	uint32_t last_sector;
+	double frame_dur;
+	uint64_t start_time;
+	uint64_t duration;
+	bool isStill;
+	bool selected;
+	bool found;
+	//ButtonsListType btt_list;
+} CellListElem;
+
+typedef struct {
+	uint16_t start_x;				// Starting X position
+	uint16_t start_y;				// Starting Y position
+	uint16_t end_x;					// Ending X position
+	uint16_t end_y;					// Ending Y position
+	uint8_t btn_coln;				// Button color table number, 0=3Dnone
+	uint8_t auto_action_flag;		// Auto Action flag 0=3Dno, 1=3Dyes
+	uint8_t up;						// Button number to select if "Up" is pressed
+	uint8_t down;					// Button number to select if "Down" is pressed
+	uint8_t left;					// Button number to select if "Left" is pressed
+	uint8_t right;					// Button number to select if "Right" is pressed
+	uint8_t vm_cmd[8];				// One vm command to be executed on "action" of t=
his button
+} btni;
+
+typedef struct {
+	uint32_t nv_pck_lbn		: 32;	// Logical Block Number (sector) of this blo=
ck
+	uint16_t vobu_cat		: 16;	// Flags, including APS (Analog Protection Sys=
tem)
+	uint16_t reserved1		: 16;	// Reserved
+	uint32_t vobu_uop_ctl	: 32;	// bitmask for prohibited user operations
+	uint32_t vobu_s_ptm		: 32;	// Vobu Start Presentation Time (90KHz clk)
+	uint32_t vobu_e_ptm		: 32;	// Vobu End Presentation Time (PTM)
+	uint32_t vobu_se_e_ptm	: 32;	// End PTM of VOBU if Sequence_End_Code
+	uint32_t c_eltm			: 32;	// Cell elapsed time (BCD)
+	uint8_t  vobu_isrc[32];			// International Standard Recording Code (roy=
alty management)
+	uint32_t nsml_agli_dsta[9];		// Non-seamless angle 1 relative offset to=
 VOBU for CURRENT ILVU=20
+	uint16_t hli_ss;				// Highlight status (lower 2 bits only)
+	uint32_t hli_s_ptm;				// Highlight start time
+	uint32_t hli_e_ptm;				// Highlight end time
+	uint32_t btn_sl_e_ptm;			// Button selection end time (ignore user afte=
r this)
+	uint16_t btn_md;				// 4 nibbles which describe the grouping of the but=
tons
+	uint8_t  btn_sn;				// Starting button number
+	uint8_t  btn_ns;				// Number of buttons
+	uint8_t  nsl_btn_ns;			// Number of numerically selected buttons
+	uint8_t  reserved2;				// Reserved
+	uint8_t  fosl_btnn;				// Force select button number
+	uint8_t  foac_btnn;				// Force action button number
+	uint32_t btn_coli[3][2];		// Selection and action color and contrast va=
lues
+	btni     btnit[36];
+} nav_pci_gi;
+
+typedef struct {
+	uint32_t nv_pck_scr		: 32;	// System clock reference
+	uint32_t nv_pck_lbn		: 32;	// Logical Block Number (sector) of this blo=
ck
+	uint32_t vobu_ea		: 32;	// VOBU end address - relative offset to last s=
ector of VOBU
+	uint32_t vobu_1stref_ea	: 32;	// First reference frame end block, relat=
ive - used for fast playing
+	uint32_t vobu_2ndref_ea	: 32;	// Second reference frame end block, rela=
tive - used for fast playing
+	uint32_t vobu_3rdref_ea	: 32;	// Third reference frame end block, relat=
ive - used for fast playing
+	uint16_t vobu_vob_idn	: 16;	// VOB number
+	uint8_t  reserved		: 8;	// Reserved
+	uint8_t  vobu_c_idn		: 8;	// CELL number within VOB
+	uint32_t c_eltm			: 32;	// Cell elapsed time (BCD)
+} nav_dsi_gi;
+
+typedef struct {
+	uint8_t PES_scrambling_control : 2;
+	uint8_t PES_priority : 1;
+	uint8_t data_alignment_indicator : 1;
+	uint8_t copyright : 1;
+	uint8_t original_or_copy : 1;
+	uint8_t PTS_flag : 1;
+	uint8_t DTS_flag : 1;
+	uint8_t ESCR_flag : 1;
+	uint8_t ES_rate_flag : 1;
+	uint8_t DSM_trick_mode_flag : 1;
+	uint8_t additionnal_copy_info_flag : 1;
+	uint8_t PES_CRC_flag : 1;
+	uint8_t PES_extension_flag : 1;
+	uint8_t PES_header_data_len;
+} PES_header_data_content;
+
+typedef struct {
+	uint32_t identifier;
+	uint64_t scr;
+	uint16_t scr_ext;
+	uint32_t program_mux_rate;
+	int64_t pts;
+	int64_t dts;
+} packet_info;
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Exception
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+class Exception
+{
+public:
+	Exception() {}
+	Exception(const char* message)
+	{
+		strcpy(m_message, message);
+	}
+
+	char m_message[512];
+};
+
+class VobParserException : public Exception
+{
+public:
+	VobParserException() : Exception() {}
+	VobParserException(const char* message) : Exception(message) {}
+};
+
+class VobParserFileNotFoundException : public VobParserException
+{
+public:
+	VobParserFileNotFoundException(const char* filename)
+	{
+		sprintf(m_message,"File not found exception : %s", filename);
+	}
+};
+
+class VobParserInvalidPacketException : public VobParserException
+{
+public:
+	VobParserInvalidPacketException(int offset)
+	{
+		sprintf(m_message,"Invalid packet exception @LBA %d", offset);
+	}
+};
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Demuxer class
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+class Demuxer
+{
+public:
+	virtual ~Demuxer() {}
+	virtual void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start=
_time, uint32_t end_time, const QString & debug) =3D 0;
+	virtual void SetBoundary(uint32_t start_timecode, uint32_t duration, co=
nst CellListElem *cell) =3D 0;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class Writer : public Demuxer
+{
+public:
+	Writer(const char* filenamePrefix, const char* extension, double fps)
+		:m_file(NULL)
+		,m_TimecodeFile(NULL)
+		,m_fps(fps)
+	{
+		m_Filename =3D filenamePrefix;
+		m_fileExtension =3D extension;
+	}
+
+	virtual ~Writer()
+	{
+		if(m_file)
+		{
+			fclose(m_file);
+		}
+		if (m_TimecodeFile)
+			fclose(m_TimecodeFile);
+	}
+
+	virtual void Write(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+	{
+		m_file =3D OpenOuputFile();
+		WriteTimecodeInfo(start_time, end_time, ftell(m_file), debug);
+		fwrite(buff, 1, size, m_file);
+	}
+
+	bool FileExists() const {
+		return m_file !=3D NULL;
+	}
+
+protected:
+	inline FILE* GetTimecodeFile()
+	{
+		if (!m_TimecodeFile)
+		{
+			QString m_filename =3D m_Filename;
+			m_filename +=3D "_";
+			m_filename +=3D m_fileExtension;
+			m_filename +=3D ".tmc";
+			m_TimecodeFile =3D fopen(m_filename.toAscii().data(),"w");
+			fwrite("# timecode format v3\n", 1, 21, m_TimecodeFile);
+			fprintf(m_TimecodeFile, "assume %lf\n", m_fps);
+		}
+		return m_TimecodeFile;
+	}
+
+	inline FILE* OpenOuputFile()
+	{
+		if(!m_file)
+		{
+			QString m_filename =3D m_Filename;
+			m_filename +=3D ".";
+			m_filename +=3D  m_fileExtension;
+			m_file =3D fopen(m_filename.toAscii().data(),"wb");
+		}
+		return m_file;
+	}
+
+	QString m_Filename;
+	QString m_fileExtension;
+	FILE* m_file;
+	FILE* m_TimecodeFile;
+	double m_fps;
+
+	virtual void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, =
uint64_t filepos, const QString& debug) =3D 0;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class VideoDemuxWriter : public Writer
+{
+public:
+	VideoDemuxWriter(const char* filenamePrefix, double fps)
+		:Writer(filenamePrefix,"m2v", fps)=20
+		,m_end_timecode(0)
+		,m_last_start_timecode(0)
+		,m_last_end_timecode(0)
+		,m_is_still(false)
+		,m_parser(NULL)
+	{}
+	void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug);
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+	~VideoDemuxWriter();
+protected:
+	void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
 filepos, const QString& debug);
+	uint32_t m_start_timecode;
+	uint32_t m_end_timecode;
+	uint32_t m_last_start_timecode;
+	uint32_t m_last_end_timecode;
+	bool m_is_still;
+
+	M2VParser * m_parser;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class AC3DemuxWriter : public Writer
+{
+public:
+	AC3DemuxWriter(const char* filenamePrefix, const uint8_t streamID)
+		:Writer(filenamePrefix, "ac3", 0.0)
+		,m_streamID(streamID)
+		,m_end_timecode(0)
+		,m_last_start_timecode(0)
+		,m_last_end_timecode(0)
+	{}
+	~AC3DemuxWriter();
+	void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+	{
+		Write(buff,size, start_time, end_time, debug);
+	}
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+	uint8_t m_streamID;
+protected:
+	void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
 filepos, const QString& debug);
+	uint32_t m_start_timecode;
+	uint32_t m_end_timecode;
+	uint32_t m_last_start_timecode;
+	uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class DTSDemuxWriter : public Writer
+{
+public:
+	DTSDemuxWriter(const char* filenamePrefix, const uint8_t streamID)
+		:Writer(filenamePrefix,"dts",0.0)
+		,m_streamID(streamID)
+		,m_end_timecode(0)
+		,m_last_start_timecode(0)
+		,m_last_end_timecode(0)
+	{}
+	~DTSDemuxWriter();
+	void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+	{
+		Write(buff,size, start_time, end_time, debug);
+	}
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+	uint8_t m_streamID;
+protected:
+	void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
 filepos, const QString& debug);
+	uint32_t m_start_timecode;
+	uint32_t m_end_timecode;
+	uint32_t m_last_start_timecode;
+	uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class WavWriter : public Writer
+{
+	public:
+		WavWriter(const char* filenamePrefix, double fps, uint32_t sample_rate=
, uint8_t bit_depth, uint8_t channel_nb)
+			:Writer(filenamePrefix, "wav", fps)
+			,m_sample_rate(sample_rate)
+			,m_bit_depth(bit_depth)
+			,m_channel_nb(channel_nb)
+		{}
+		~WavWriter();
+		void Write(uint8_t* buff, uint32_t size, uint32_t start_time, uint32_t=
 end_time, const QString& debug);
+	protected:
+		uint32_t m_sample_rate;
+		uint8_t m_bit_depth, m_channel_nb;
+		size_t m_size_position1,m_size_position2, m_size;
+};
+
+class LPCMDemuxWriter : public WavWriter
+{
+public:
+	LPCMDemuxWriter(const char* filenamePrefix, const uint8_t streamID, uin=
t32_t sample_rate, uint8_t bit_depth, uint8_t channel_nb)
+		:WavWriter(filenamePrefix,0.0, sample_rate, bit_depth, channel_nb)
+		,m_streamID(streamID)
+		,m_end_timecode(0)
+		,m_last_start_timecode(0)
+		,m_last_end_timecode(0)
+	{}
+	~LPCMDemuxWriter();
+	void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+	{
+		Write(buff,size, start_time, end_time, debug);
+	}
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+	uint8_t m_streamID;
+protected:
+	void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
 filepos, const QString& debug);
+	uint32_t m_start_timecode;
+	uint32_t m_end_timecode;
+	uint32_t m_last_start_timecode;
+	uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class MPADemuxWriter : public Writer
+{
+public:
+	MPADemuxWriter(const char* filenamePrefix, const uint8_t streamID) :
+	  Writer(filenamePrefix,"mpa",0.0), m_streamID(streamID) {}
+	void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+	{
+		Write(buff,size, start_time, end_time, debug);
+	}
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+private:
+	uint8_t m_streamID;
+protected:
+	void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
 filepos, const QString& debug);
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class SubDemuxWriter : public Writer
+{
+public:
+	SubDemuxWriter(const char* filenamePrefix, const uint8_t streamID, uint=
16_t width, uint16_t height, const uint32_t * palette, uint16_t language,=
 bool forced)
+		:Writer(filenamePrefix, "sub",0.0)
+		,m_width(width)
+		,m_height(height)
+		,m_forced(forced)
+		,m_palette(palette)
+		,m_language(language)
+		,m_start_timecode(0)
+		,m_end_timecode(0)
+	{}
+	void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+	{
+		Write(buff,size, start_time, end_time, debug);
+	}
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+protected:
+	void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
 filepos, const QString& debug);
+private:
+	uint16_t m_width;
+	uint16_t m_height;
+	bool m_forced;
+	const uint32_t * m_palette;
+	uint16_t m_language;
+	uint32_t m_start_timecode;
+	uint32_t m_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class BtnDemuxWriter : public Writer
+{
+public:
+	BtnDemuxWriter(const char* filenamePrefix, uint16_t width, uint16_t hei=
ght)
+		:Writer(filenamePrefix, "btn",0.0)
+		,m_width(width)
+		,m_height(height)
+		,m_end_timecode(0)
+		,m_last_start_timecode(0)
+		,m_last_end_timecode(0)
+	{}
+	void ProcessStream(uint8_t* buff, uint32_t size, uint32_t start_time, u=
int32_t end_time, const QString& debug)
+	{
+		if (!m_file) {
+			m_file =3D OpenOuputFile();
+			fwrite("butonDVD", 8, 1, m_file);
+			uint8_t _tmp[4];
+			// width & height
+			_tmp[0] =3D m_width >> 8;
+			_tmp[1] =3D m_width & 0xFF;
+			_tmp[2] =3D m_height >> 8;
+			_tmp[3] =3D m_height & 0xFF;
+			fwrite(_tmp, 4, 1, m_file);
+			// pad to 16 bytes
+			_tmp[0] =3D 0;
+			_tmp[1] =3D 0;
+			_tmp[2] =3D 0;
+			_tmp[3] =3D 0;
+			fwrite(_tmp, 4, 1, m_file);
+		}
+		Write(buff,size, start_time, end_time, debug);
+	}
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+	~BtnDemuxWriter();
+protected:
+	void WriteTimecodeInfo(uint32_t start_time, uint32_t end_time, uint64_t=
 filepos, const QString& debug);
+	uint16_t m_width, m_height;
+	uint32_t m_start_timecode;
+	uint32_t m_end_timecode;
+	uint32_t m_last_start_timecode;
+	uint32_t m_last_end_timecode;
+};
+
+// ---------------------------------------------------------------------=
-------
+
+class CompositeDemuxWriter
+{
+public:
+	CompositeDemuxWriter();
+	~CompositeDemuxWriter();
+	bool AddDemuxer(uint8_t streamID, Writer * demuxer, QString& CommandLin=
e);
+	void ProcessStream(int streamID, uint8_t* buff, uint32_t size, int32_t =
start_time, int32_t end_time, const QString& debug);
+	void Reset();
+	void SetBoundary(uint32_t start_timecode, uint32_t duration, const Cell=
ListElem *cell);
+
+	bool FileExists(uint8_t streamID) const {
+		return (m_muxers[streamID] !=3D NULL && m_muxers[streamID]->FileExists=
());
+	}
+
+	const QString& GetString(uint8_t streamID) const {
+		return m_strings[streamID];
+	}
+
+protected:
+	Writer * m_muxers[256];
+	QString m_strings[256];
+};
+
+// ---------------------------------------------------------------------=
-------
+
+struct stream_info_node
+{
+	uint8_t id;
+	uint32_t type;
+	stream_info_node* next;
+};
+
+
+// ---------------------------------------------------------------------=
-------
+
+typedef struct=20
+{
+	int x1;
+	int y1;
+	int x2;
+	int y2;
+} ButtonListElem;
+
+typedef QList<ButtonListElem *> ButtonListType;
+
+
+// ---------------------------------------------------------------------=
-------
+
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+// Main class
+// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D
+
+class IFOFile;
+class CellsListType;
+
+class VobParser
+{
+public:
+	VobParser(const char* dirname, int16_t title, bool menu);
+	void Reset();
+	bool ParseNextPacket(const CellsListType & Cells);
+	uint32_t GetPacketCount() const;
+	uint32_t GetPacketIndex() const;
+	char* GetCurrentPacketData() const;
+	inline uint8_t GetVobID() const;
+	inline uint8_t GetCellID() const;
+	bool IsNewCell();
+	virtual ~VobParser();
+	inline CompositeDemuxWriter & GetDemuxer()
+	{
+		return m_demuxer;
+	}
+	uint32_t GetCellSCR() const;
+
+	nav_dsi_gi m_dsi;
+	nav_pci_gi m_pci;
+	packet_info pktinfo;
+	PES_header_data_content pes_header_data_content;
+protected:
+	void ParseNavPacket();
+	void ParseAudioPacket(int StreamID);
+	void ParseVideoPacket();
+	void ParsePrivateStream1();
+
+	void ParseSCR();
+	void ParsePCI();
+	void ParseDSI();
+	void ParsePESHeaderDataContentFlag();
+	void ParsePESHeaderData();
+	uint64_t ParsePTS_DTS();
+
+	// Buffer management
+	bool AvailablePacketData() const;
+	bool GetNextPacket();
+	uint32_t GetNext32Bits();
+	uint16_t GetNext16Bits();
+	uint8_t GetNext8Bits();
+	void SkipNBytes(int n);
+
+private:
+	int16_t m_title;
+	dvd_reader_t *m_dvdhandle;
+	dvd_file_t *m_stream;
+	bool m_language;
+	uint8_t m_buff[DVD_VIDEO_LB_LEN];
+	uint32_t m_index;
+	uint32_t m_pktindex;
+	uint32_t m_pktcount;
+	bool m_bFirstPacket;
+	int64_t m_startpts;
+	int64_t m_startdts;
+	uint16_t m_pci_position;
+	uint16_t m_pci_size;
+	uint32_t m_pci_vob_timecode_offset;
+=09
+	CompositeDemuxWriter m_demuxer;
+
+	int previous_vobid, previous_cellid;
+};
+
+// ---------------------------------------------------------------------=
-------
+#endif
+// ---------------------------------------------------------------------=
-------

Added: trunk/DvdMenuXtractor/vobparser/iso/iso-639.def
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/iso/iso-639.def	2007-01-22 11:21:16 U=
TC (rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/iso/iso-639.def	2007-01-28 16:48:11 U=
TC (rev 1270)
@@ -0,0 +1,173 @@
+/*
+ * Defines the languages codes and abbreviations according to ISO 639-[1=
2].
+ * This is used in iso_lang.cpp and is taken from the GNU glibc 2.2.5 ta=
rball.
+ * It has been partially completed with native language name.
+ *
+ * Format is: ("English name", 639-1-code, 639-2/T-code, 639-2/B-code)
+ * If you find something missing or wrong contact <bug-glibc at gnu.org>
+ */
+
+DEFINE_LANGUAGE_CODE ("Afar", "", aa, aar, aar)
+DEFINE_LANGUAGE_CODE ("Abkhazian", "", ab, abk, abk)
+DEFINE_LANGUAGE_CODE ("Afrikaans", "", af, afr, afr)
+DEFINE_LANGUAGE_CODE ("Albanian", "", sq, sqi, alb)
+DEFINE_LANGUAGE_CODE ("Amharic", "", am, amh, amh)
+DEFINE_LANGUAGE_CODE ("Arabic", "", ar, ara, ara)
+DEFINE_LANGUAGE_CODE ("Armenian", "", hy, hye, arm)
+DEFINE_LANGUAGE_CODE ("Assamese", "", as, asm, asm)
+DEFINE_LANGUAGE_CODE ("Avestan", "", ae, ave, ave)
+DEFINE_LANGUAGE_CODE ("Aymara", "", ay, aym, aym)
+DEFINE_LANGUAGE_CODE ("Azerbaijani", "", az, aze, aze)
+DEFINE_LANGUAGE_CODE ("Bashkir", "", ba, bak, bak)
+DEFINE_LANGUAGE_CODE ("Basque", "", eu, eus, baq)
+DEFINE_LANGUAGE_CODE ("Belarusian", "", be, bel, bel)
+DEFINE_LANGUAGE_CODE ("Bengali", "", bn, ben, ben)
+DEFINE_LANGUAGE_CODE ("Bihari", "", bh, bih, bih)
+DEFINE_LANGUAGE_CODE ("Bislama", "", bi, bis, bis)
+DEFINE_LANGUAGE_CODE ("Bosnian", "", bs, bos, bos)
+DEFINE_LANGUAGE_CODE ("Breton", "", br, bre, bre)
+DEFINE_LANGUAGE_CODE ("Bulgarian", "", bg, bul, bul)
+DEFINE_LANGUAGE_CODE ("Burmese", "", my, mya, bur)
+DEFINE_LANGUAGE_CODE ("Catalan", "", ca, cat, cat)
+DEFINE_LANGUAGE_CODE ("Chamorro", "", ch, cha, cha)
+DEFINE_LANGUAGE_CODE ("Chechen", "", ce, che, che)
+DEFINE_LANGUAGE_CODE ("Chinese", "", zh, zho, chi)
+DEFINE_LANGUAGE_CODE ("Church Slavic", "", cu, chu, chu)
+DEFINE_LANGUAGE_CODE ("Chuvash", "", cv, chv, chv)
+DEFINE_LANGUAGE_CODE ("Cornish", "", kw, cor, cor)
+DEFINE_LANGUAGE_CODE ("Corsican", "", co, cos, cos)
+DEFINE_LANGUAGE_CODE ("Czech", "", cs, ces, cze)
+DEFINE_LANGUAGE_CODE ("Danish", "Dansk", da, dan, dan)
+DEFINE_LANGUAGE_CODE ("Dutch", "Nederlands", nl, nld, dut)
+DEFINE_LANGUAGE_CODE ("Dzongkha", "", dz, dzo, dzo)
+DEFINE_LANGUAGE_CODE ("English", "English", en, eng, eng)
+DEFINE_LANGUAGE_CODE ("Esperanto", "", eo, epo, epo)
+DEFINE_LANGUAGE_CODE ("Estonian", "", et, est, est)
+DEFINE_LANGUAGE_CODE ("Faroese", "", fo, fao, fao)
+DEFINE_LANGUAGE_CODE ("Fijian", "", fj, fij, fij)
+DEFINE_LANGUAGE_CODE ("Finnish", "Suomi", fi, fin, fin)
+DEFINE_LANGUAGE_CODE ("French", "Francais", fr, fra, fre)
+DEFINE_LANGUAGE_CODE ("Frisian", "", fy, fry, fry)
+DEFINE_LANGUAGE_CODE ("Georgian", "", ka, kat, geo)
+DEFINE_LANGUAGE_CODE ("German", "Deutsch", de, deu, ger)
+DEFINE_LANGUAGE_CODE ("Gaelic (Scots)", "", gd, gla, gla)
+DEFINE_LANGUAGE_CODE ("Irish", "", ga, gle, gle)
+DEFINE_LANGUAGE_CODE ("Gallegan", "", gl, glg, glg)
+DEFINE_LANGUAGE_CODE ("Manx", "", gv, glv, glv)
+DEFINE_LANGUAGE_CODE ("Greek, Modern ()", "", el, gre, ell)
+DEFINE_LANGUAGE_CODE ("Guarani", "", gn, grn, grn)
+DEFINE_LANGUAGE_CODE ("Gujarati", "", gu, guj, guj)
+DEFINE_LANGUAGE_CODE ("Hebrew", "", he, heb, heb)
+DEFINE_LANGUAGE_CODE ("Herero", "", hz, her, her)
+DEFINE_LANGUAGE_CODE ("Hindi", "", hi, hin, hin)
+DEFINE_LANGUAGE_CODE ("Hiri Motu", "", ho, hmo, hmo)
+DEFINE_LANGUAGE_CODE ("Hungarian", "Magyar", hu, hun, hun)
+DEFINE_LANGUAGE_CODE ("Icelandic", "Islenska", is, isl, ice)
+DEFINE_LANGUAGE_CODE ("Inuktitut", "", iu, iku, iku)
+DEFINE_LANGUAGE_CODE ("Interlingue", "", ie, ile, ile)
+DEFINE_LANGUAGE_CODE ("Interlingua", "", ia, ina, ina)
+DEFINE_LANGUAGE_CODE ("Indonesian", "", id, ind, ind)
+DEFINE_LANGUAGE_CODE ("Inupiaq", "", ik, ipk, ipk)
+DEFINE_LANGUAGE_CODE ("Italian", "Italiano", it, ita, ita)
+DEFINE_LANGUAGE_CODE ("Javanese", "", jv, jaw, jav)
+DEFINE_LANGUAGE_CODE ("Japanese", "", ja, jpn, jpn)
+DEFINE_LANGUAGE_CODE ("Kalaallisut (Greenlandic)", "", kl, kal, kal)
+DEFINE_LANGUAGE_CODE ("Kannada", "", kn, kan, kan)
+DEFINE_LANGUAGE_CODE ("Kashmiri", "", ks, kas, kas)
+DEFINE_LANGUAGE_CODE ("Kazakh", "", kk, kaz, kaz)
+DEFINE_LANGUAGE_CODE ("Khmer", "", km, khm, khm)
+DEFINE_LANGUAGE_CODE ("Kikuyu", "", ki, kik, kik)
+DEFINE_LANGUAGE_CODE ("Kinyarwanda", "", rw, kin, kin)
+DEFINE_LANGUAGE_CODE ("Kirghiz", "", ky, kir, kir)
+DEFINE_LANGUAGE_CODE ("Komi", "", kv, kom, kom)
+DEFINE_LANGUAGE_CODE ("Korean", "", ko, kor, kor)
+DEFINE_LANGUAGE_CODE ("Kuanyama", "", kj, kua, kua)
+DEFINE_LANGUAGE_CODE ("Kurdish", "", ku, kur, kur)
+DEFINE_LANGUAGE_CODE ("Lao", "", lo, lao, lao)
+DEFINE_LANGUAGE_CODE ("Latin", "", la, lat, lat)
+DEFINE_LANGUAGE_CODE ("Latvian", "", lv, lav, lav)
+DEFINE_LANGUAGE_CODE ("Lingala", "", ln, lin, lin)
+DEFINE_LANGUAGE_CODE ("Lithuanian", "", lt, lit, lit)
+DEFINE_LANGUAGE_CODE ("Letzeburgesch", "", lb, ltz, ltz)
+DEFINE_LANGUAGE_CODE ("Macedonian", "", mk, mkd, mac)
+DEFINE_LANGUAGE_CODE ("Marshall", "", mh, mah, mah)
+DEFINE_LANGUAGE_CODE ("Malayalam", "", ml, mal, mal)
+DEFINE_LANGUAGE_CODE ("Maori", "", mi, mri, mao)
+DEFINE_LANGUAGE_CODE ("Marathi", "", mr, mar, mar)
+DEFINE_LANGUAGE_CODE ("Malay", "", ms, msa, may)
+DEFINE_LANGUAGE_CODE ("Malagasy", "", mg, mlg, mlg)
+DEFINE_LANGUAGE_CODE ("Maltese", "", mt, mlt, mlt)
+DEFINE_LANGUAGE_CODE ("Moldavian", "", mo, mol, mol)
+DEFINE_LANGUAGE_CODE ("Mongolian", "", mn, mon, mon)
+DEFINE_LANGUAGE_CODE ("Nauru", "", na, nau, nau)
+DEFINE_LANGUAGE_CODE ("Navajo", "", nv, nav, nav)
+DEFINE_LANGUAGE_CODE ("Ndebele, South", "", nr, nbl, nbl)
+DEFINE_LANGUAGE_CODE ("Ndebele, North", "", nd, nde, nde)
+DEFINE_LANGUAGE_CODE ("Ndonga", "", ng, ndo, ndo)
+DEFINE_LANGUAGE_CODE ("Nepali", "", ne, nep, nep)
+DEFINE_LANGUAGE_CODE ("Norwegian", "Norsk", no, nor, nor)
+DEFINE_LANGUAGE_CODE ("Norwegian Nynorsk", "", nn, nno, nno)
+DEFINE_LANGUAGE_CODE ("Norwegian Bokm=E5l", "", nb, nob, nob)
+DEFINE_LANGUAGE_CODE ("Chichewa; Nyanja", "", ny, nya, nya)
+DEFINE_LANGUAGE_CODE ("Occitan (post 1500); Proven=E7al", "", oc, oci, o=
ci)
+DEFINE_LANGUAGE_CODE ("Oriya", "", or, ori, ori)
+DEFINE_LANGUAGE_CODE ("Oromo", "", om, orm, orm)
+DEFINE_LANGUAGE_CODE ("Ossetian; Ossetic", "", os, oss, oss)
+DEFINE_LANGUAGE_CODE ("Panjabi", "", pa, pan, pan)
+DEFINE_LANGUAGE_CODE ("Persian", "", fa, fas, per)
+DEFINE_LANGUAGE_CODE ("Pali", "", pi, pli, pli)
+DEFINE_LANGUAGE_CODE ("Polish", "", pl, pol, pol)
+DEFINE_LANGUAGE_CODE ("Portuguese", "Portugues", pt, por, por)
+DEFINE_LANGUAGE_CODE ("Pushto", "", ps, pus, pus)
+DEFINE_LANGUAGE_CODE ("Quechua", "", qu, que, que)
+DEFINE_LANGUAGE_CODE ("Raeto-Romance", "", rm, roh, roh)
+DEFINE_LANGUAGE_CODE ("Romanian", "", ro, ron, rum)
+DEFINE_LANGUAGE_CODE ("Rundi", "", rn, run, run)
+DEFINE_LANGUAGE_CODE ("Russian", "", ru, rus, rus)
+DEFINE_LANGUAGE_CODE ("Sango", "", sg, sag, sag)
+DEFINE_LANGUAGE_CODE ("Sanskrit", "", sa, san, san)
+DEFINE_LANGUAGE_CODE ("Serbian", "", sr, srp, scc)
+DEFINE_LANGUAGE_CODE ("Croatian", "Hrvatski", hr, hrv, scr)
+DEFINE_LANGUAGE_CODE ("Sinhalese", "", si, sin, sin)
+DEFINE_LANGUAGE_CODE ("Slovak", "", sk, slk, slo)
+DEFINE_LANGUAGE_CODE ("Slovenian", "", sl, slv, slv)
+DEFINE_LANGUAGE_CODE ("Northern Sami", "", se, sme, sme)
+DEFINE_LANGUAGE_CODE ("Samoan", "", sm, smo, smo)
+DEFINE_LANGUAGE_CODE ("Shona", "", sn, sna, sna)
+DEFINE_LANGUAGE_CODE ("Sindhi", "", sd, snd, snd)
+DEFINE_LANGUAGE_CODE ("Somali", "", so, som, som)
+DEFINE_LANGUAGE_CODE ("Sotho, Southern", "", st, sot, sot)
+DEFINE_LANGUAGE_CODE ("Spanish", "Espanol", es, spa, spa)
+DEFINE_LANGUAGE_CODE ("Sardinian", "", sc, srd, srd)
+DEFINE_LANGUAGE_CODE ("Swati", "", ss, ssw, ssw)
+DEFINE_LANGUAGE_CODE ("Sundanese", "", su, sun, sun)
+DEFINE_LANGUAGE_CODE ("Swahili", "", sw, swa, swa)
+DEFINE_LANGUAGE_CODE ("Swedish", "Svenska", sv, swe, swe)
+DEFINE_LANGUAGE_CODE ("Tahitian", "", ty, tah, tah)
+DEFINE_LANGUAGE_CODE ("Tamil", "", ta, tam, tam)
+DEFINE_LANGUAGE_CODE ("Tatar", "", tt, tat, tat)
+DEFINE_LANGUAGE_CODE ("Telugu", "", te, tel, tel)
+DEFINE_LANGUAGE_CODE ("Tajik", "", tg, tgk, tgk)
+DEFINE_LANGUAGE_CODE ("Tagalog", "", tl, tgl, tgl)
+DEFINE_LANGUAGE_CODE ("Thai", "", th, tha, tha)
+DEFINE_LANGUAGE_CODE ("Tibetan", "", bo, bod, tib)
+DEFINE_LANGUAGE_CODE ("Tigrinya", "", ti, tir, tir)
+DEFINE_LANGUAGE_CODE ("Tonga (Tonga Islands)", "", to, ton, ton)
+DEFINE_LANGUAGE_CODE ("Tswana", "", tn, tsn, tsn)
+DEFINE_LANGUAGE_CODE ("Tsonga", "", ts, tso, tso)
+DEFINE_LANGUAGE_CODE ("Turkish", "", tr, tur, tur)
+DEFINE_LANGUAGE_CODE ("Turkmen", "", tk, tuk, tuk)
+DEFINE_LANGUAGE_CODE ("Twi", "", tw, twi, twi)
+DEFINE_LANGUAGE_CODE ("Uighur", "", ug, uig, uig)
+DEFINE_LANGUAGE_CODE ("Ukrainian", "", uk, ukr, ukr)
+DEFINE_LANGUAGE_CODE ("Urdu", "", ur, urd, urd)
+DEFINE_LANGUAGE_CODE ("Uzbek", "", uz, uzb, uzb)
+DEFINE_LANGUAGE_CODE ("Vietnamese", "", vi, vie, vie)
+DEFINE_LANGUAGE_CODE ("Volap=FCk", "", vo, vol, vol)
+DEFINE_LANGUAGE_CODE ("Welsh", "", cy, cym, wel)
+DEFINE_LANGUAGE_CODE ("Wolof", "", wo, wol, wol)
+DEFINE_LANGUAGE_CODE ("Xhosa", "", xh, xho, xho)
+DEFINE_LANGUAGE_CODE ("Yiddish", "", yi, yid, yid)
+DEFINE_LANGUAGE_CODE ("Yoruba", "", yo, yor, yor)
+DEFINE_LANGUAGE_CODE ("Zhuang", "", za, zha, zha)
+DEFINE_LANGUAGE_CODE ("Zulu", "", zu, zul, zul)

Added: trunk/DvdMenuXtractor/vobparser/iso/iso_lang.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/iso/iso_lang.c	2007-01-22 11:21:16 UT=
C (rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/iso/iso_lang.c	2007-01-28 16:48:11 UT=
C (rev 1270)
@@ -0,0 +1,113 @@
+/***********************************************************************=
******
+ * iso_lang.c: function to decode language code (in dvd or a52 for insta=
nce).
+ ***********************************************************************=
******
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: iso_lang.c,v 1.6 2002/06/01 12:32:01 sam Exp $
+ *
+ * Author: St=E9phane Borel <stef at via.ecp.fr>
+ *         Arnaud de Bossoreille de Ribou <bozo at via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *=20
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA=
.
+ ***********************************************************************=
******/
+
+/***********************************************************************=
******
+ * Preamble
+ ***********************************************************************=
******/
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include "iso_lang.h"
+
+/***********************************************************************=
******
+ * Local tables
+ ***********************************************************************=
******/
+
+#define DEFINE_LANGUAGE_CODE(engName, nativeName, iso1, iso2T, iso2B) \
+          { engName, nativeName, #iso1, #iso2T, #iso2B },
+
+static const iso639_lang_t p_languages[] =3D
+{
+#include "iso-639.def"
+    { NULL, NULL, NULL, NULL, NULL }
+};
+
+static const iso639_lang_t unknown_language =3D
+    { "Unknown", "Unknown", "??", "???", "???" };
+
+/***********************************************************************=
******
+ * DecodeLanguage: gives the long language name from the two-letter
+ *                 ISO-639 code
+ ***********************************************************************=
******/
+const char * DecodeLanguage( uint16_t i_code )
+{
+    const iso639_lang_t * p_lang;
+    uint8_t psz_code[3];
+
+	if (i_code !=3D 0)
+	{
+		psz_code[0] =3D (uint8_t)(i_code >> 8);
+		psz_code[1] =3D (uint8_t)i_code;
+		psz_code[2] =3D '\0';
+
+		for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+		{
+			if( !strncmp( p_lang->psz_iso639_1, psz_code, 2 ) )
+			{
+				if( *p_lang->psz_native_name )
+				{
+					return p_lang->psz_native_name;
+				}
+
+				return p_lang->psz_eng_name;
+			}
+		}
+	}
+
+    return "Unknown";
+}
+
+const iso639_lang_t * GetLang_1( const char * psz_code )
+{
+    const iso639_lang_t *p_lang;
+
+    for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+        if( !strncmp( p_lang->psz_iso639_1, psz_code, 2 ) )
+            return p_lang;
+
+    return &unknown_language;
+}
+
+const iso639_lang_t * GetLang_2T( const char * psz_code )
+{
+    const iso639_lang_t *p_lang;
+   =20
+    for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+        if( !strncmp( p_lang->psz_iso639_2T, psz_code, 3 ) )
+            return p_lang;
+
+    return &unknown_language;
+}
+
+const iso639_lang_t * GetLang_2B( const char * psz_code )
+{
+    const iso639_lang_t *p_lang;
+
+    for( p_lang =3D p_languages; p_lang->psz_eng_name; p_lang++ )
+        if( !strncmp( p_lang->psz_iso639_2B, psz_code, 3 ) )
+            return p_lang;
+
+    return &unknown_language;
+}
+

Added: trunk/DvdMenuXtractor/vobparser/iso/iso_lang.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/iso/iso_lang.h	2007-01-22 11:21:16 UT=
C (rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/iso/iso_lang.h	2007-01-28 16:48:11 UT=
C (rev 1270)
@@ -0,0 +1,51 @@
+/***********************************************************************=
******
+ * iso_lang.h: function to decode language code (in dvd or a52 for insta=
nce).
+ ***********************************************************************=
******
+ * Copyright (C) 1998-2001 VideoLAN
+ * $Id: iso_lang.h,v 1.5 2002/05/20 22:36:42 sam Exp $
+ *
+ * Author: St=E9phane Borel <stef at via.ecp.fr>
+ *         Arnaud de Bossoreille de Ribou <bozo at via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *=20
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA=
.
+ ***********************************************************************=
******/
+
+#ifndef _ISO_LANG_H_
+#define _ISO_LANG_H_
+
+struct iso639_lang_s
+{
+    char * psz_eng_name;        /* Description in English */
+    char * psz_native_name;     /* Description in native language */
+    char * psz_iso639_1;        /* ISO-639-1 (2 characters) code */
+    char * psz_iso639_2T;       /* ISO-639-2/T (3 characters) English co=
de */
+    char * psz_iso639_2B;       /* ISO-639-2/B (3 characters) native cod=
e */
+};
+
+typedef struct iso639_lang_s iso639_lang_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const iso639_lang_t * GetLang_1( const char * psz_iso639_1 );
+const iso639_lang_t * GetLang_2T( const char * psz_iso639_2T );
+const iso639_lang_t * GetLang_2B( const char * psz_iso639_2B );
+const char * DecodeLanguage( uint16_t );
+
+#ifdef __cplusplus
+};
+#endif
+#endif // _ISO_LANG_H_

Added: trunk/DvdMenuXtractor/vobparser/vobparser.proj
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/DvdMenuXtractor/vobparser/vobparser.proj	2007-01-22 11:21:16 UT=
C (rev 1269)
+++ trunk/DvdMenuXtractor/vobparser/vobparser.proj	2007-01-28 16:48:11 UT=
C (rev 1270)
@@ -0,0 +1,14 @@
+GROUP vobparser
+{
+  SOURCE IFOContent.cpp
+  SOURCE IFOFile.cpp
+  SOURCE VobParser.cpp
+  SOURCE iso/iso_lang.c
+
+  HEADER IFOContent.h
+  HEADER IFOFile.h
+  HEADER VobParser.h
+  HEADER iso/iso_lang.h
+ =20
+  INCLUDE ..
+}



More information about the Matroska-cvs mailing list