Commit b08376be authored by Stéphane Borel's avatar Stéphane Borel

*Merged hh patch in libdvdcss from main tree.

*Updated local libdvdread, so that it does not depend on libdvdcss
(ala dummy_dvdcss) and modified configure to reflect changes.
parent b7ee1eea
...@@ -6286,6 +6286,7 @@ if test "${with_dvdcss+set}" = set; then ...@@ -6286,6 +6286,7 @@ if test "${with_dvdcss+set}" = set; then
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
fi fi
;; ;;
...@@ -6298,6 +6299,7 @@ if test "${with_dvdcss+set}" = set; then ...@@ -6298,6 +6299,7 @@ if test "${with_dvdcss+set}" = set; then
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
LIB_DVD="${LIB_DVD} -Llib -ldvdcss" LIB_DVD="${LIB_DVD} -Llib -ldvdcss"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -L../../lib -ldvdcss" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -L../../lib -ldvdcss"
LIB_DVDREAD="${LIB_DVD} -Llib -ldvdread -ldvdcss"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -L../../lib -ldvdcss" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -L../../lib -ldvdcss"
fi fi
;; ;;
...@@ -6310,6 +6312,7 @@ if test "${with_dvdcss+set}" = set; then ...@@ -6310,6 +6312,7 @@ if test "${with_dvdcss+set}" = set; then
CFLAGS_DVD="${CFLAGS_DVD} -DLIBDVDCSS_VERSION=\"${LIBDVDCSS_VERSION}\"" CFLAGS_DVD="${CFLAGS_DVD} -DLIBDVDCSS_VERSION=\"${LIBDVDCSS_VERSION}\""
LIB_DVD="${LIB_DVD} -ldl" LIB_DVD="${LIB_DVD} -ldl"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
;; ;;
*) *)
...@@ -6323,7 +6326,8 @@ if test "${with_dvdcss+set}" = set; then ...@@ -6323,7 +6326,8 @@ if test "${with_dvdcss+set}" = set; then
fi fi
LIB_DVD="${LIB_DVD} -ldvdcss" LIB_DVD="${LIB_DVD} -ldvdcss"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldvdcss" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldvdcss"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdcss" LIB_DVDREAD="${LIB_DVDREAD} -ldvdread -ldvdcss"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdread -ldvdcss"
esac esac
else else
# user didn't decide, we choose to use local libdvdcss and link statically # user didn't decide, we choose to use local libdvdcss and link statically
...@@ -6336,7 +6340,8 @@ else ...@@ -6336,7 +6340,8 @@ else
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdread.a ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
else else
# XXX: no check for libdl is done, don't try this at home ! # XXX: no check for libdl is done, don't try this at home !
DUMMY_LIBDVDCSS=1 DUMMY_LIBDVDCSS=1
...@@ -6345,6 +6350,7 @@ else ...@@ -6345,6 +6350,7 @@ else
CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA" CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA"
LIB_DVD="${LIB_DVD} -ldl" LIB_DVD="${LIB_DVD} -ldl"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
fi fi
fi fi
...@@ -6355,11 +6361,8 @@ if test "${enable_dvdread+set}" = set; then ...@@ -6355,11 +6361,8 @@ if test "${enable_dvdread+set}" = set; then
enableval="$enable_dvdread" enableval="$enable_dvdread"
if test x$enableval = xyes if test x$enableval = xyes
then then
NEED_LIBDVDCSS=1
STATIC_LIBDVDCSS=1
BUILTINS="${BUILTINS} dvdread" BUILTINS="${BUILTINS} dvdread"
CFLAGS_DVDREAD="${CFLAGS_DVDREAD} -I../../extras/libdvdread" CFLAGS_DVDREAD="${CFLAGS_DVD} ${CFLAGS_DVDREAD} -I../../extras/libdvdread"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a"
fi fi
fi fi
...@@ -6374,7 +6377,7 @@ fi ...@@ -6374,7 +6377,7 @@ fi
if test x$enable_vcd != xno if test x$enable_vcd != xno
then then
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 6378 "configure" #line 6381 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <linux/cdrom.h> #include <linux/cdrom.h>
EOF EOF
...@@ -6448,17 +6451,17 @@ if test "${with_mad+set}" = set; then ...@@ -6448,17 +6451,17 @@ if test "${with_mad+set}" = set; then
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:6452: checking for $ac_hdr" >&5 echo "configure:6455: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 6457 "configure" #line 6460 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:6462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:6465: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -6488,7 +6491,7 @@ fi ...@@ -6488,7 +6491,7 @@ fi
done done
echo $ac_n "checking for mad_bit_init in -lmad""... $ac_c" 1>&6 echo $ac_n "checking for mad_bit_init in -lmad""... $ac_c" 1>&6
echo "configure:6492: checking for mad_bit_init in -lmad" >&5 echo "configure:6495: checking for mad_bit_init in -lmad" >&5
ac_lib_var=`echo mad'_'mad_bit_init | sed 'y%./+-%__p_%'` ac_lib_var=`echo mad'_'mad_bit_init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
...@@ -6496,7 +6499,7 @@ else ...@@ -6496,7 +6499,7 @@ else
ac_save_LIBS="$LIBS" ac_save_LIBS="$LIBS"
LIBS="-lmad $LIBS" LIBS="-lmad $LIBS"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 6500 "configure" #line 6503 "configure"
#include "confdefs.h" #include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */ /* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2 /* We use char because int might match the return type of a gcc2
...@@ -6507,7 +6510,7 @@ int main() { ...@@ -6507,7 +6510,7 @@ int main() {
mad_bit_init() mad_bit_init()
; return 0; } ; return 0; }
EOF EOF
if { (eval echo configure:6511: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then if { (eval echo configure:6514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest* rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes" eval "ac_cv_lib_$ac_lib_var=yes"
else else
...@@ -6574,7 +6577,7 @@ if test "${enable_esd+set}" = set; then ...@@ -6574,7 +6577,7 @@ if test "${enable_esd+set}" = set; then
# Extract the first word of "esd-config", so it can be a program name with args. # Extract the first word of "esd-config", so it can be a program name with args.
set dummy esd-config; ac_word=$2 set dummy esd-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:6578: checking for $ac_word" >&5 echo "configure:6581: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_ESD_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_ESD_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -6625,7 +6628,7 @@ if test "${enable_arts+set}" = set; then ...@@ -6625,7 +6628,7 @@ if test "${enable_arts+set}" = set; then
# Extract the first word of "artsc-config", so it can be a program name with args. # Extract the first word of "artsc-config", so it can be a program name with args.
set dummy artsc-config; ac_word=$2 set dummy artsc-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:6629: checking for $ac_word" >&5 echo "configure:6632: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_ARTS_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_ARTS_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -6683,17 +6686,17 @@ else ...@@ -6683,17 +6686,17 @@ else
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:6687: checking for $ac_hdr" >&5 echo "configure:6690: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 6692 "configure" #line 6695 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:6697: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:6700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -6738,17 +6741,17 @@ fi ...@@ -6738,17 +6741,17 @@ fi
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:6742: checking for $ac_hdr" >&5 echo "configure:6745: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 6747 "configure" #line 6750 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:6752: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:6755: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -6836,7 +6839,7 @@ fi ...@@ -6836,7 +6839,7 @@ fi
# Extract the first word of "sdl12-config", so it can be a program name with args. # Extract the first word of "sdl12-config", so it can be a program name with args.
set dummy sdl12-config; ac_word=$2 set dummy sdl12-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:6840: checking for $ac_word" >&5 echo "configure:6843: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SDL12_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_SDL12_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -6876,7 +6879,7 @@ fi ...@@ -6876,7 +6879,7 @@ fi
# Extract the first word of "sdl11-config", so it can be a program name with args. # Extract the first word of "sdl11-config", so it can be a program name with args.
set dummy sdl11-config; ac_word=$2 set dummy sdl11-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:6880: checking for $ac_word" >&5 echo "configure:6883: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SDL11_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_SDL11_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -6917,7 +6920,7 @@ fi ...@@ -6917,7 +6920,7 @@ fi
# Extract the first word of "sdl-config", so it can be a program name with args. # Extract the first word of "sdl-config", so it can be a program name with args.
set dummy sdl-config; ac_word=$2 set dummy sdl-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:6921: checking for $ac_word" >&5 echo "configure:6924: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -6963,17 +6966,17 @@ fi ...@@ -6963,17 +6966,17 @@ fi
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:6967: checking for $ac_hdr" >&5 echo "configure:6970: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 6972 "configure" #line 6975 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:6977: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:6980: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -7043,17 +7046,17 @@ fi ...@@ -7043,17 +7046,17 @@ fi
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:7047: checking for $ac_hdr" >&5 echo "configure:7050: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7052 "configure" #line 7055 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:7057: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:7060: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -7082,7 +7085,7 @@ done ...@@ -7082,7 +7085,7 @@ done
else else
echo $ac_n "checking for directX headers in ${withval}""... $ac_c" 1>&6 echo $ac_n "checking for directX headers in ${withval}""... $ac_c" 1>&6
echo "configure:7086: checking for directX headers in ${withval}" >&5 echo "configure:7089: checking for directX headers in ${withval}" >&5
if test -f ${withval}/include/directx.h if test -f ${withval}/include/directx.h
then then
PLUGINS="${PLUGINS} directx" PLUGINS="${PLUGINS} directx"
...@@ -7179,7 +7182,7 @@ if test "${enable_gnome+set}" = set; then ...@@ -7179,7 +7182,7 @@ if test "${enable_gnome+set}" = set; then
# Extract the first word of "gnome-config", so it can be a program name with args. # Extract the first word of "gnome-config", so it can be a program name with args.
set dummy gnome-config; ac_word=$2 set dummy gnome-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:7183: checking for $ac_word" >&5 echo "configure:7186: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GNOME_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_GNOME_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -7224,17 +7227,17 @@ fi ...@@ -7224,17 +7227,17 @@ fi
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:7228: checking for $ac_hdr" >&5 echo "configure:7231: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7233 "configure" #line 7236 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:7238: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:7241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -7294,7 +7297,7 @@ fi ...@@ -7294,7 +7297,7 @@ fi
# Extract the first word of "gtk-config", so it can be a program name with args. # Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2 set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:7298: checking for $ac_word" >&5 echo "configure:7301: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
...@@ -7344,17 +7347,17 @@ fi ...@@ -7344,17 +7347,17 @@ fi
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:7348: checking for $ac_hdr" >&5 echo "configure:7351: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7353 "configure" #line 7356 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:7358: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:7361: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -7411,17 +7414,17 @@ if test x$enable_x11 != xno && ...@@ -7411,17 +7414,17 @@ if test x$enable_x11 != xno &&
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:7415: checking for $ac_hdr" >&5 echo "configure:7418: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7420 "configure" #line 7423 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:7425: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:7428: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -7474,17 +7477,17 @@ if test x$enable_xvideo != xno && ...@@ -7474,17 +7477,17 @@ if test x$enable_xvideo != xno &&
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:7478: checking for $ac_hdr" >&5 echo "configure:7481: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7483 "configure" #line 7486 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:7488: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:7491: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -7508,7 +7511,7 @@ EOF ...@@ -7508,7 +7511,7 @@ EOF
saved_CFLAGS=$CFLAGS saved_CFLAGS=$CFLAGS
CFLAGS="$CFLAGS -L$x_libraries -lX11 -lXext" CFLAGS="$CFLAGS -L$x_libraries -lX11 -lXext"
echo $ac_n "checking for XvSetPortAttribute in -lXv_pic""... $ac_c" 1>&6 echo $ac_n "checking for XvSetPortAttribute in -lXv_pic""... $ac_c" 1>&6
echo "configure:7512: checking for XvSetPortAttribute in -lXv_pic" >&5 echo "configure:7515: checking for XvSetPortAttribute in -lXv_pic" >&5
ac_lib_var=`echo Xv_pic'_'XvSetPortAttribute | sed 'y%./+-%__p_%'` ac_lib_var=`echo Xv_pic'_'XvSetPortAttribute | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
...@@ -7516,7 +7519,7 @@ else ...@@ -7516,7 +7519,7 @@ else
ac_save_LIBS="$LIBS" ac_save_LIBS="$LIBS"
LIBS="-lXv_pic $LIBS" LIBS="-lXv_pic $LIBS"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7520 "configure" #line 7523 "configure"
#include "confdefs.h" #include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */ /* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2 /* We use char because int might match the return type of a gcc2
...@@ -7527,7 +7530,7 @@ int main() { ...@@ -7527,7 +7530,7 @@ int main() {
XvSetPortAttribute() XvSetPortAttribute()
; return 0; } ; return 0; }
EOF EOF
if { (eval echo configure:7531: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then if { (eval echo configure:7534: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest* rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes" eval "ac_cv_lib_$ac_lib_var=yes"
else else
...@@ -7571,17 +7574,17 @@ if test "${enable_alsa+set}" = set; then ...@@ -7571,17 +7574,17 @@ if test "${enable_alsa+set}" = set; then
then then
ac_safe=`echo "alsa/asoundlib.h" | sed 'y%./+-%__p_%'` ac_safe=`echo "alsa/asoundlib.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for alsa/asoundlib.h""... $ac_c" 1>&6 echo $ac_n "checking for alsa/asoundlib.h""... $ac_c" 1>&6
echo "configure:7575: checking for alsa/asoundlib.h" >&5 echo "configure:7578: checking for alsa/asoundlib.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7580 "configure" #line 7583 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:7585: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:7588: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
...@@ -7598,7 +7601,7 @@ fi ...@@ -7598,7 +7601,7 @@ fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6 echo "$ac_t""yes" 1>&6
echo $ac_n "checking for main in -lasound""... $ac_c" 1>&6 echo $ac_n "checking for main in -lasound""... $ac_c" 1>&6
echo "configure:7602: checking for main in -lasound" >&5 echo "configure:7605: checking for main in -lasound" >&5
ac_lib_var=`echo asound'_'main | sed 'y%./+-%__p_%'` ac_lib_var=`echo asound'_'main | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
...@@ -7606,14 +7609,14 @@ else ...@@ -7606,14 +7609,14 @@ else
ac_save_LIBS="$LIBS" ac_save_LIBS="$LIBS"
LIBS="-lasound $LIBS" LIBS="-lasound $LIBS"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 7610 "configure" #line 7613 "configure"
#include "confdefs.h" #include "confdefs.h"
int main() { int main() {
main() main()
; return 0; } ; return 0; }
EOF EOF
if { (eval echo configure:7617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then if { (eval echo configure:7620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest* rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes" eval "ac_cv_lib_$ac_lib_var=yes"
else else
......
...@@ -767,6 +767,7 @@ AC_ARG_WITH(dvdcss, ...@@ -767,6 +767,7 @@ AC_ARG_WITH(dvdcss,
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
fi fi
;; ;;
...@@ -779,6 +780,7 @@ AC_ARG_WITH(dvdcss, ...@@ -779,6 +780,7 @@ AC_ARG_WITH(dvdcss,
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
LIB_DVD="${LIB_DVD} -Llib -ldvdcss" LIB_DVD="${LIB_DVD} -Llib -ldvdcss"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -L../../lib -ldvdcss" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -L../../lib -ldvdcss"
LIB_DVDREAD="${LIB_DVD} -Llib -ldvdread -ldvdcss"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -L../../lib -ldvdcss" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -L../../lib -ldvdcss"
fi fi
;; ;;
...@@ -791,6 +793,7 @@ AC_ARG_WITH(dvdcss, ...@@ -791,6 +793,7 @@ AC_ARG_WITH(dvdcss,
CFLAGS_DVD="${CFLAGS_DVD} -DLIBDVDCSS_VERSION=\"${LIBDVDCSS_VERSION}\"" CFLAGS_DVD="${CFLAGS_DVD} -DLIBDVDCSS_VERSION=\"${LIBDVDCSS_VERSION}\""
LIB_DVD="${LIB_DVD} -ldl" LIB_DVD="${LIB_DVD} -ldl"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
;; ;;
*) *)
...@@ -804,7 +807,8 @@ AC_ARG_WITH(dvdcss, ...@@ -804,7 +807,8 @@ AC_ARG_WITH(dvdcss,
fi fi
LIB_DVD="${LIB_DVD} -ldvdcss" LIB_DVD="${LIB_DVD} -ldvdcss"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldvdcss" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldvdcss"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdcss" LIB_DVDREAD="${LIB_DVDREAD} -ldvdread -ldvdcss"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdread -ldvdcss"
esac ], esac ],
# user didn't decide, we choose to use local libdvdcss and link statically # user didn't decide, we choose to use local libdvdcss and link statically
# if libdvdcss is in the archive, or to use the dummy replacement otherwise. # if libdvdcss is in the archive, or to use the dummy replacement otherwise.
...@@ -816,7 +820,8 @@ AC_ARG_WITH(dvdcss, ...@@ -816,7 +820,8 @@ AC_ARG_WITH(dvdcss,
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss" CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}" LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdread.a ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
else else
# XXX: no check for libdl is done, don't try this at home ! # XXX: no check for libdl is done, don't try this at home !
DUMMY_LIBDVDCSS=1 DUMMY_LIBDVDCSS=1
...@@ -825,6 +830,7 @@ AC_ARG_WITH(dvdcss, ...@@ -825,6 +830,7 @@ AC_ARG_WITH(dvdcss,
CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA" CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA"
LIB_DVD="${LIB_DVD} -ldl" LIB_DVD="${LIB_DVD} -ldl"
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl" LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl" LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
fi ]) fi ])
...@@ -835,11 +841,8 @@ AC_ARG_ENABLE(dvdread, ...@@ -835,11 +841,8 @@ AC_ARG_ENABLE(dvdread,
[ --enable-dvdread Enable dvdread support (default disabled)], [ --enable-dvdread Enable dvdread support (default disabled)],
[ if test x$enableval = xyes [ if test x$enableval = xyes
then then
NEED_LIBDVDCSS=1
STATIC_LIBDVDCSS=1
BUILTINS="${BUILTINS} dvdread" BUILTINS="${BUILTINS} dvdread"
CFLAGS_DVDREAD="${CFLAGS_DVDREAD} -I../../extras/libdvdread" CFLAGS_DVDREAD="${CFLAGS_DVD} ${CFLAGS_DVDREAD} -I../../extras/libdvdread"
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a"
fi ]) fi ])
dnl dnl
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* css.c: Functions for DVD authentification and unscrambling * css.c: Functions for DVD authentification and unscrambling
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: css.c,v 1.21 2002/01/21 07:00:21 gbazin Exp $ * $Id: css.c,v 1.22 2002/01/23 03:15:31 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* Hkan Hjort <d95hjort@dtek.chalmers.se> * Hkan Hjort <d95hjort@dtek.chalmers.se>
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int CSSAuth ( dvdcss_handle dvdcss );
static int CSSGetASF ( dvdcss_handle dvdcss ); static int CSSGetASF ( dvdcss_handle dvdcss );
static void CSSCryptKey ( int i_key_type, int i_varient, static void CSSCryptKey ( int i_key_type, int i_varient,
u8 const * p_challenge, u8* p_key ); u8 const * p_challenge, u8* p_key );
...@@ -92,55 +93,56 @@ int CSSTest( dvdcss_handle dvdcss ) ...@@ -92,55 +93,56 @@ int CSSTest( dvdcss_handle dvdcss )
} }
/***************************************************************************** /*****************************************************************************
* CSSAuth : CSS Structure initialisation and DVD authentication. * CSSAuth : DVD CSS authentication.
***************************************************************************** *****************************************************************************
* It simulates the mutual authentication between logical unit and host. * It simulates the mutual authentication between logical unit and host,
* Since we don't need the disc key to find the title key, we just run the * and stops when a session key (called bus key) has been established.
* basic unavoidable commands to authenticate device and disc. * Always do the full auth sequence. Some drives seem to lie and always
* respond with ASF=1. For instance the old DVD roms on Compaq Armada says
* that ASF=1 from the start and then later fail with a 'read of scrambled
* block without authentication' error.
*****************************************************************************/ *****************************************************************************/
int CSSAuth( dvdcss_handle dvdcss ) static int CSSAuth( dvdcss_handle dvdcss )
{ {
/* structures defined in cdrom.h or dvdio.h */ u8 p_buffer[10];
unsigned char p_buffer[10]; u8 p_challenge[2*KEY_SIZE];
dvd_key_t p_key1;
dvd_key_t p_key2;
dvd_key_t p_key_check;
u8 i_varient = 0;
char psz_warning[48]; char psz_warning[48];
int i_ret = -1; int i_ret = -1;
int i; int i;
dvdcss->css.i_agid = 0; /* So this isn't really necessary except for debuging. */
if( CSSGetASF( dvdcss ) < 0 )
/* Test authentication success */
switch( CSSGetASF( dvdcss ) )
{ {
case -1: _dvdcss_error( dvdcss, "fatal error in CSSAuth" );
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
return -1; return -1;
case 1:
_dvdcss_debug( dvdcss, "already authenticated" );
break;
case 0:
_dvdcss_debug( dvdcss, "need to authenticate" );
break;
} }
/* Init sequence, request AGID */ _dvdcss_debug( dvdcss, "requesting AGID" );
for( i = 1; i < 4 ; ++i )
{
snprintf( psz_warning, sizeof(psz_warning), "requesting AGID %d", i );
_dvdcss_debug( dvdcss, psz_warning );
i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
if( i_ret != -1 ) /* We might have to reset hung authentication processes in the drive
by invalidating the corresponding AGID'. As long as we haven't got
an AGID, invalidate one (in sequence) and try again. */
for( i = 0; i_ret == -1 && i < 4 ; ++i )
{ {
/* No error during ioctl: we know the device is authenticated */ _dvdcss_debug( dvdcss, "ioctl_ReportAgid failed" );
break;
}
_dvdcss_error( dvdcss, "ioctl_ReportAgid failed, invalidating" ); sprintf( psz_warning, "invalidating AGID %d", i );
_dvdcss_debug( dvdcss, psz_warning );
dvdcss->css.i_agid = 0; /* This is really _not good_, should be handled by the OS.
Invalidating an AGID could make another process fail some
where in it's authentication process. */
dvdcss->css.i_agid = i;
ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
_dvdcss_debug( dvdcss, "requesting AGID" );
i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
} }
/* Unable to authenticate without AGID */ /* Unable to authenticate without AGID */
...@@ -150,21 +152,23 @@ int CSSAuth( dvdcss_handle dvdcss ) ...@@ -150,21 +152,23 @@ int CSSAuth( dvdcss_handle dvdcss )
return -1; return -1;
} }
/* Setup a challenge, any valuse should work */
for( i = 0 ; i < 10; ++i ) for( i = 0 ; i < 10; ++i )
{ {
dvdcss->css.disc.p_challenge[i] = i; p_challenge[i] = i;
} }
/* Get challenge from host */ /* Get challenge from host */
for( i = 0 ; i < 10 ; ++i ) for( i = 0 ; i < 10 ; ++i )
{ {
p_buffer[9-i] = dvdcss->css.disc.p_challenge[i]; p_buffer[9-i] = p_challenge[i];
} }
/* Send challenge to LU */ /* Send challenge to LU */
if( ioctl_SendChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) if( ioctl_SendChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 )
{ {
_dvdcss_error( dvdcss, "ioctl_SendChallenge failed" ); _dvdcss_error( dvdcss, "ioctl_SendChallenge failed" );
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
return -1; return -1;
} }
...@@ -172,27 +176,26 @@ int CSSAuth( dvdcss_handle dvdcss ) ...@@ -172,27 +176,26 @@ int CSSAuth( dvdcss_handle dvdcss )
if( ioctl_ReportKey1( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0) if( ioctl_ReportKey1( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0)
{ {
_dvdcss_error( dvdcss, "ioctl_ReportKey1 failed" ); _dvdcss_error( dvdcss, "ioctl_ReportKey1 failed" );
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
return -1; return -1;
} }
/* Send key1 to host */ /* Send key1 to host */
for( i = 0 ; i < KEY_SIZE ; i++ ) for( i = 0 ; i < KEY_SIZE ; i++ )
{ {
dvdcss->css.disc.p_key1[i] = p_buffer[4-i]; p_key1[i] = p_buffer[4-i];
} }
for( i = 0 ; i < 32 ; ++i ) for( i = 0 ; i < 32 ; ++i )
{ {
CSSCryptKey( 0, i, dvdcss->css.disc.p_challenge, CSSCryptKey( 0, i, p_challenge, p_key_check );
dvdcss->css.disc.p_key_check );
if( memcmp( dvdcss->css.disc.p_key_check, if( memcmp( p_key_check, p_key1, KEY_SIZE ) == 0 )
dvdcss->css.disc.p_key1, KEY_SIZE ) == 0 )
{ {
snprintf( psz_warning, sizeof(psz_warning), snprintf( psz_warning, sizeof(psz_warning),
"drive authentic, using variant %d", i ); "drive authentic, using varient %d", i );
_dvdcss_debug( dvdcss, psz_warning ); _dvdcss_debug( dvdcss, psz_warning );
dvdcss->css.disc.i_varient = i; i_varient = i;
break; break;
} }
} }
...@@ -200,73 +203,61 @@ int CSSAuth( dvdcss_handle dvdcss ) ...@@ -200,73 +203,61 @@ int CSSAuth( dvdcss_handle dvdcss )
if( i == 32 ) if( i == 32 )
{ {
_dvdcss_error( dvdcss, "drive would not authenticate" ); _dvdcss_error( dvdcss, "drive would not authenticate" );
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
return -1; return -1;
} }
/* Get challenge from LU */ /* Get challenge from LU */
if( ioctl_ReportChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) if( ioctl_ReportChallenge( dvdcss->i_fd,
&dvdcss->css.i_agid, p_buffer ) < 0 )
{ {
_dvdcss_error( dvdcss, "ioctl_ReportKeyChallenge failed" ); _dvdcss_error( dvdcss, "ioctl_ReportKeyChallenge failed" );
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
return -1; return -1;
} }
/* Send challenge to host */ /* Send challenge to host */
for( i = 0 ; i < 10 ; ++i ) for( i = 0 ; i < 10 ; ++i )
{ {
dvdcss->css.disc.p_challenge[i] = p_buffer[9-i]; p_challenge[i] = p_buffer[9-i];
} }
CSSCryptKey( 1, dvdcss->css.disc.i_varient, CSSCryptKey( 1, i_varient, p_challenge, p_key2 );
dvdcss->css.disc.p_challenge,
dvdcss->css.disc.p_key2 );
/* Get key2 from host */ /* Get key2 from host */
for( i = 0 ; i < KEY_SIZE ; ++i ) for( i = 0 ; i < KEY_SIZE ; ++i )
{ {
p_buffer[4-i] = dvdcss->css.disc.p_key2[i]; p_buffer[4-i] = p_key2[i];
} }
/* Send key2 to LU */ /* Send key2 to LU */
if( ioctl_SendKey2( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 ) if( ioctl_SendKey2( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 )
{ {
_dvdcss_error( dvdcss, "ioctl_SendKey2 failed" ); _dvdcss_error( dvdcss, "ioctl_SendKey2 failed" );
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
return -1; return -1;
} }
/* The drive has accepted us as authentic. */
_dvdcss_debug( dvdcss, "authentication established" ); _dvdcss_debug( dvdcss, "authentication established" );
memcpy( dvdcss->css.disc.p_challenge, memcpy( p_challenge, p_key1, KEY_SIZE );
dvdcss->css.disc.p_key1, KEY_SIZE ); memcpy( p_challenge + KEY_SIZE, p_key2, KEY_SIZE );
memcpy( dvdcss->css.disc.p_challenge+KEY_SIZE,
dvdcss->css.disc.p_key2, KEY_SIZE );
CSSCryptKey( 2, dvdcss->css.disc.i_varient, CSSCryptKey( 2, i_varient, p_challenge, dvdcss->css.p_bus_key );
dvdcss->css.disc.p_challenge,
dvdcss->css.disc.p_key_check );
_dvdcss_debug( dvdcss, "received session key" );
if( dvdcss->css.i_agid < 0 )
{
return -1;
}
/* Test authentication success */
switch( CSSGetASF( dvdcss ) )
{
case -1:
return -1;
case 1:
_dvdcss_debug( dvdcss, "already authenticated" );
return 0; return 0;
}
case 0: /*****************************************************************************
_dvdcss_debug( dvdcss, "need to get disc key" ); * CSSPrintKey : debug function that dumps a key value
return 0; *****************************************************************************/static void CSSPrintKey( dvdcss_handle dvdcss, u8* data )
} {
char psz_output[80];
return -1; sprintf( psz_output, "the key is %02x %02x %02x %02x %02x",
data[0], data[1], data[2], data[3], data[4] );
_dvdcss_debug( dvdcss, psz_output );
} }
/***************************************************************************** /*****************************************************************************
...@@ -279,7 +270,7 @@ int CSSAuth( dvdcss_handle dvdcss ) ...@@ -279,7 +270,7 @@ int CSSAuth( dvdcss_handle dvdcss )
*****************************************************************************/ *****************************************************************************/
int CSSGetDiscKey( dvdcss_handle dvdcss ) int CSSGetDiscKey( dvdcss_handle dvdcss )
{ {
unsigned char p_buffer[2048 + 4 + 1]; unsigned char p_buffer[2048];
#ifdef HAVE_CSSKEYS #ifdef HAVE_CSSKEYS
dvd_key_t disc_key; dvd_key_t disc_key;
dvd_key_t test_key; dvd_key_t test_key;
...@@ -301,9 +292,8 @@ int CSSGetDiscKey( dvdcss_handle dvdcss ) ...@@ -301,9 +292,8 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
/* Unencrypt disc key using bus key */ /* Unencrypt disc key using bus key */
for( i = 0 ; i < 2048 ; i++ ) for( i = 0 ; i < 2048 ; i++ )
{ {
p_buffer[ i ] ^= dvdcss->css.disc.p_key_check[ 4 - (i % KEY_SIZE) ]; p_buffer[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ];
} }
memcpy( dvdcss->css.disc.p_disc_key, p_buffer, 2048 );
switch( dvdcss->i_method ) switch( dvdcss->i_method )
{ {
...@@ -316,14 +306,13 @@ int CSSGetDiscKey( dvdcss_handle dvdcss ) ...@@ -316,14 +306,13 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
{ {
/* Take encrypted disc key and decrypt it */ /* Take encrypted disc key and decrypt it */
memcpy( disc_key, memcpy( disc_key,
dvdcss->css.disc.p_disc_key p_buffer + playerkeys[i].i_offset,
+ playerkeys[i].i_offset,
KEY_SIZE ); KEY_SIZE );
CSSDecryptKey( disc_key, playerkeys[i].p_key, 0 ); CSSDecryptKey( disc_key, playerkeys[i].p_key, 0 );
/* Encrypt disc key hash with disc key to /* Encrypt disc key hash with disc key to
* check we have disc key */ * check we have disc key */
memcpy( test_key, dvdcss->css.disc.p_disc_key, KEY_SIZE ); memcpy( test_key, p_buffer, KEY_SIZE );
CSSDecryptKey( test_key, disc_key, 0); CSSDecryptKey( test_key, disc_key, 0);
i++; i++;
...@@ -332,7 +321,7 @@ int CSSGetDiscKey( dvdcss_handle dvdcss ) ...@@ -332,7 +321,7 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
( memcmp( test_key, disc_key, KEY_SIZE ) ) ); ( memcmp( test_key, disc_key, KEY_SIZE ) ) );
/* The decrypted disk key will replace the disk key hash */ /* The decrypted disk key will replace the disk key hash */
memcpy( dvdcss->css.disc.p_disc_key, disc_key, KEY_SIZE ); memcpy( dvdcss->css.p_disc_key, disc_key, KEY_SIZE );
break; break;
#else #else
dvdcss->i_method = DVDCSS_METHOD_DISC; dvdcss->i_method = DVDCSS_METHOD_DISC;
...@@ -341,13 +330,15 @@ int CSSGetDiscKey( dvdcss_handle dvdcss ) ...@@ -341,13 +330,15 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
/* Crack Disc key to be able to use it */ /* Crack Disc key to be able to use it */
_dvdcss_debug( dvdcss, "cracking disc key with key hash" ); _dvdcss_debug( dvdcss, "cracking disc key with key hash" );
_dvdcss_debug( dvdcss, "building 64MB table ... this will take some time" ); _dvdcss_debug( dvdcss, "building 64MB table ... this will take some time" );
CSSDiscCrack( dvdcss, dvdcss->css.disc.p_disc_key ); CSSDiscCrack( dvdcss, p_buffer );
memcpy( dvdcss->css.p_disc_key, p_buffer, KEY_SIZE );
break; break;
default: default:
_dvdcss_debug( dvdcss, "disc key won't be decrypted" ); _dvdcss_debug( dvdcss, "disc key won't be decrypted" );
} }
CSSPrintKey( dvdcss, dvdcss->css.p_disc_key );
return 0; return 0;
} }
...@@ -449,6 +440,7 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos ) ...@@ -449,6 +440,7 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos )
if( b_stop_scanning ) if( b_stop_scanning )
{ {
memcpy( dvdcss->css.p_title_key, &p_key, sizeof(dvd_key_t) ); memcpy( dvdcss->css.p_title_key, &p_key, sizeof(dvd_key_t) );
CSSPrintKey( dvdcss, dvdcss->css.p_title_key );
_dvdcss_debug( dvdcss, "vts key initialized" ); _dvdcss_debug( dvdcss, "vts key initialized" );
return 0; return 0;
} }
...@@ -456,6 +448,7 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos ) ...@@ -456,6 +448,7 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos )
if( !b_encrypted ) if( !b_encrypted )
{ {
_dvdcss_debug( dvdcss, "file was unscrambled" ); _dvdcss_debug( dvdcss, "file was unscrambled" );
dvdcss->b_encrypted = 0;
return 0; return 0;
} }
...@@ -489,13 +482,22 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos ) ...@@ -489,13 +482,22 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos )
/* Unencrypt title key using bus key */ /* Unencrypt title key using bus key */
for( i = 0 ; i < KEY_SIZE ; i++ ) for( i = 0 ; i < KEY_SIZE ; i++ )
{ {
p_key[ i ] ^= dvdcss->css.disc.p_key_check[ 4 - (i % KEY_SIZE ) ]; p_key[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE ) ];
}
/* If p_key is all zero then there realy wasn't any key pressent. */
if( !( p_key[0] | p_key[1] | p_key[2] | p_key[3] | p_key[4] ) )
{
memset( dvdcss->css.p_title_key, 0, sizeof(dvd_key_t) );
CSSPrintKey( dvdcss, dvdcss->css.p_title_key );
return 0;
} }
/* Title key decryption needs one inversion 0xff */ /* Title key decryption needs one inversion 0xff */
CSSDecryptKey( p_key, dvdcss->css.disc.p_disc_key, 0xff ); CSSDecryptKey( p_key, dvdcss->css.p_disc_key, 0xff );
memcpy( dvdcss->css.p_title_key, p_key, KEY_SIZE ); memcpy( dvdcss->css.p_title_key, p_key, KEY_SIZE );
CSSPrintKey( dvdcss, dvdcss->css.p_title_key );
} }
return 0; return 0;
...@@ -558,29 +560,25 @@ int CSSDescrambleSector( dvd_key_t p_key, u8* p_sec ) ...@@ -558,29 +560,25 @@ int CSSDescrambleSector( dvd_key_t p_key, u8* p_sec )
*****************************************************************************/ *****************************************************************************/
static int CSSGetASF( dvdcss_handle dvdcss ) static int CSSGetASF( dvdcss_handle dvdcss )
{ {
int i_agid;
int i_asf = 0; int i_asf = 0;
for( i_agid = 0 ; i_agid < 4 ; i_agid++ ) if( ioctl_ReportASF( dvdcss->i_fd, NULL, &i_asf ) != 0 )
{
if( ioctl_ReportASF( dvdcss->i_fd, &i_agid, &i_asf ) == 0 )
{ {
/* The ioctl process has failed */
_dvdcss_error( dvdcss, "GetASF fatal error" );
return -1;
}
if( i_asf ) if( i_asf )
{ {
_dvdcss_debug( dvdcss, "GetASF authenticated" ); _dvdcss_debug( dvdcss, "GetASF authenticated (ASF=1)" );
} }
else else
{ {
_dvdcss_debug( dvdcss, "GetASF not authenticated" ); _dvdcss_debug( dvdcss, "GetASF not authenticated (ASF=0)" );
} }
return i_asf; return i_asf;
}
}
/* The ioctl process has failed */
_dvdcss_error( dvdcss, "GetASF fatal error" );
return -1;
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* css.h: Structures for DVD authentification and unscrambling * css.h: Structures for DVD authentification and unscrambling
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: css.h,v 1.7 2002/01/14 22:06:57 stef Exp $ * $Id: css.h,v 1.8 2002/01/23 03:15:31 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -30,16 +30,6 @@ ...@@ -30,16 +30,6 @@
typedef u8 dvd_key_t[KEY_SIZE]; typedef u8 dvd_key_t[KEY_SIZE];
typedef struct disc_s
{
u8 p_challenge[2*KEY_SIZE];
dvd_key_t p_key1;
dvd_key_t p_key2;
dvd_key_t p_key_check;
u8 i_varient;
u8 p_disc_key[2048];
} disc_t;
typedef struct dvd_title_s typedef struct dvd_title_s
{ {
int i_startlb; int i_startlb;
...@@ -49,10 +39,11 @@ typedef struct dvd_title_s ...@@ -49,10 +39,11 @@ typedef struct dvd_title_s
typedef struct css_s typedef struct css_s
{ {
int i_agid; int i_agid; /* Current Authenication Grant ID. */
disc_t disc; dvd_key_t p_bus_key; /* Current session key. */
dvd_key_t p_unenc_key; /* title key before decryption */ dvd_key_t p_disc_key; /* This DVD disc's key. */
dvd_key_t p_title_key; /* title key after decryption */ dvd_key_t p_unenc_key; /* Current title key before decryption. */
dvd_key_t p_title_key; /* Current title key. */
} css_t; } css_t;
/***************************************************************************** /*****************************************************************************
...@@ -61,7 +52,6 @@ typedef struct css_s ...@@ -61,7 +52,6 @@ typedef struct css_s
struct css_s; struct css_s;
int CSSTest ( dvdcss_handle ); int CSSTest ( dvdcss_handle );
int CSSAuth ( dvdcss_handle );
int CSSGetDiscKey ( dvdcss_handle ); int CSSGetDiscKey ( dvdcss_handle );
int CSSGetTitleKey ( dvdcss_handle, int ); int CSSGetTitleKey ( dvdcss_handle, int );
int CSSDescrambleSector ( u8 * , u8 * ); int CSSDescrambleSector ( u8 * , u8 * );
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* libdvdcss.c: DVD reading library. * libdvdcss.c: DVD reading library.
***************************************************************************** *****************************************************************************
* Copyright (C) 1998-2001 VideoLAN * Copyright (C) 1998-2001 VideoLAN
* $Id: libdvdcss.c,v 1.29 2002/01/21 07:00:21 gbazin Exp $ * $Id: libdvdcss.c,v 1.30 2002/01/23 03:15:31 stef Exp $
* *
* Authors: Stphane Borel <stef@via.ecp.fr> * Authors: Stphane Borel <stef@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org> * Samuel Hocevar <sam@zoy.org>
...@@ -191,7 +191,6 @@ extern dvdcss_handle dvdcss_open ( char *psz_target ) ...@@ -191,7 +191,6 @@ extern dvdcss_handle dvdcss_open ( char *psz_target )
dvdcss->i_method = DVDCSS_METHOD_TITLE; dvdcss->i_method = DVDCSS_METHOD_TITLE;
dvdcss->b_ioctls = 0; dvdcss->b_ioctls = 0;
dvdcss->b_encrypted = 1; dvdcss->b_encrypted = 1;
memset( &dvdcss->css.disc, 0, sizeof(dvdcss->css.disc) );
} }
/* If disc is CSS protected and the ioctls work, authenticate the drive */ /* If disc is CSS protected and the ioctls work, authenticate the drive */
...@@ -208,6 +207,7 @@ extern dvdcss_handle dvdcss_open ( char *psz_target ) ...@@ -208,6 +207,7 @@ extern dvdcss_handle dvdcss_open ( char *psz_target )
memset( dvdcss->css.p_unenc_key, 0, KEY_SIZE ); memset( dvdcss->css.p_unenc_key, 0, KEY_SIZE );
} }
memset( dvdcss->css.p_title_key, 0, KEY_SIZE );
#ifndef WIN32 #ifndef WIN32
if( psz_raw_device != NULL ) if( psz_raw_device != NULL )
......
...@@ -25,7 +25,7 @@ CFLAGS := -I../../include -I../../extras $(CFLAGS) ...@@ -25,7 +25,7 @@ CFLAGS := -I../../include -I../../extras $(CFLAGS)
# Objects # Objects
# #
OBJ_C = dvdread.o dvd_udf.o nav_print.o nav_read.o ifo_print.o ifo_read.o OBJ_C = dvd_setup.o dvd_reader.o dvd_udf.o nav_print.o nav_read.o ifo_print.o ifo_read.o
ALL_OBJ = $(OBJ_C) $(OBJ_LIBDVDREAD) ALL_OBJ = $(OBJ_C) $(OBJ_LIBDVDREAD)
# #
...@@ -52,7 +52,7 @@ $(C_DEP): %.d: FORCE ...@@ -52,7 +52,7 @@ $(C_DEP): %.d: FORCE
$(OBJ_C): %.o: .dep/%.d $(OBJ_C): %.o: .dep/%.d
$(OBJ_C): %.o: %.c $(OBJ_C): %.o: %.c
$(CC) $(CFLAGS) $(CFLAGS_LIBDVDREAD) $(PCFLAGS) -c -o $@ $< $(CC) $(CFLAGS) $(CFLAGS_DVDREAD) $(CFLAGS_LIBDVDREAD) $(PCFLAGS) -c -o $@ $<
../../lib/$(FULL_SO): $(OBJ_C) $(OBJ_LIBDVDREAD) ../../lib/$(FULL_SO): $(OBJ_C) $(OBJ_LIBDVDREAD)
$(CC) $(PCFLAGS) $(ALL_SOFLAGS) -o $@ $^ $(PLCFLAGS) $(LIB_LIBDVDREAD) $(CC) $(PCFLAGS) $(ALL_SOFLAGS) -o $@ $^ $(PLCFLAGS) $(LIB_LIBDVDREAD)
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#ifndef BSWAP_H_INCLUDED #ifndef BSWAP_H_INCLUDED
#define BSWAP_H_INCLUDED #define BSWAP_H_INCLUDED
#include <defs.h>
#include <config.h> #include <config.h>
#if defined(WORDS_BIGENDIAN) #if defined(WORDS_BIGENDIAN)
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> /* For the timing of dvdcss_title crack. */ #include <sys/uio.h> /* readv() */
#include <fcntl.h> #include <fcntl.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <limits.h> #include <limits.h>
#include <dlfcn.h>
#include <dirent.h> #include <dirent.h>
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__) #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
...@@ -47,45 +46,17 @@ typedef off_t off64_t; ...@@ -47,45 +46,17 @@ typedef off_t off64_t;
#define stat64 stat #define stat64 stat
#endif #endif
/* #include "dvdcss.h" */
typedef struct dvdcss_s* dvdcss_handle;
#define DVDCSS_NOFLAGS 0
#define DVDCSS_INIT_QUIET (1 << 0)
#define DVDCSS_INIT_DEBUG (1 << 1)
#define DVDCSS_READ_DECRYPT (1 << 0)
#include "dvd_udf.h" #include "dvd_udf.h"
#include "dvd_reader.h" #include "dvd_reader.h"
/** #include "dvd_setup.h"
* Handle to the loaded dvdcss library.
*/
void *dvdcss_library = 0;
/**
* libdvdcss functions.
*/
static dvdcss_handle (*dvdcss_open) ( char *psz_target,
int i_flags );
static int (*dvdcss_close) ( dvdcss_handle );
static int (*dvdcss_title) ( dvdcss_handle,
int i_block );
static int (*dvdcss_seek) ( dvdcss_handle,
int i_blocks );
static int (*dvdcss_read) ( dvdcss_handle,
void *p_buffer,
int i_blocks,
int i_title );
static char * (*dvdcss_error) ( dvdcss_handle );
struct dvd_reader_s { struct dvd_reader_s {
/* Basic information. */ /* Basic information. */
int isImageFile; int isImageFile;
/* Information required for an image file. */ /* Information required for an image file. */
dvdcss_handle dev; dvd_handle dev;
int init_keys;
int fd;
/* Information required for a directory path drive. */ /* Information required for a directory path drive. */
char *path_root; char *path_root;
...@@ -100,168 +71,32 @@ struct dvd_file_s { ...@@ -100,168 +71,32 @@ struct dvd_file_s {
uint32_t seek_pos; uint32_t seek_pos;
/* Information required for a directory path drive. */ /* Information required for a directory path drive. */
dvd_handle title_devs[9];
size_t title_sizes[ 9 ]; size_t title_sizes[ 9 ];
int title_fds[ 9 ];
/* Calculated at open-time, size in blocks. */ /* Calculated at open-time, size in blocks. */
ssize_t filesize; ssize_t filesize;
}; };
static void setupCSS( void )
{
if( !dvdcss_library ) {
dvdcss_library = dlopen( "libdvdcss.so.0", RTLD_LAZY );
if( !dvdcss_library ) {
fprintf( stderr, "libdvdread: Can't open libdvdcss: %s.\n",
dlerror() );
} else {
#if defined(__OpenBSD__)
#define U_S "_"
#else
#define U_S
#endif
dvdcss_open = (dvdcss_handle (*)(char*, int))
dlsym( dvdcss_library, U_S "dvdcss_open" );
dvdcss_close = (int (*)(dvdcss_handle))
dlsym( dvdcss_library, U_S "dvdcss_close" );
dvdcss_title = (int (*)(dvdcss_handle, int))
dlsym( dvdcss_library, U_S "dvdcss_title" );
dvdcss_seek = (int (*)(dvdcss_handle, int))
dlsym( dvdcss_library, U_S "dvdcss_seek" );
dvdcss_read = (int (*)(dvdcss_handle, void*, int, int))
dlsym( dvdcss_library, U_S "dvdcss_read" );
dvdcss_error = (char* (*)(dvdcss_handle))
dlsym( dvdcss_library, U_S "dvdcss_error" );
if( dlsym( dvdcss_library, U_S "dvdcss_crack" ) ) {
fprintf( stderr, "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 = 0;
} else if( !dvdcss_open || !dvdcss_close || !dvdcss_seek ||
!dvdcss_title || !dvdcss_read || !dvdcss_error ) {
fprintf( stderr, "libdvdread: Unknown incompatible version "
"of libdvdcss found.\n"
"libdvdread: Try to find a "
"newer version of libdvdread?\n" );
dlclose( dvdcss_library );
dvdcss_library = 0;
}
}
}
if( !dvdcss_library ) {
fprintf( stderr, "libdvdread: Encrypted DVD support unavailable.\n" );
}
}
/* Loop over all titles and call dvdcss_title to crack the keys. */
static int initAllCSSKeys( dvd_reader_t *dvd )
{
if( dvdcss_library ) {
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;
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);
for( title = 0; title < 100; title++ ) {
gettimeofday( &t_s, NULL );
if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
}
start = UDFFindFile( dvd, filename, &len );
if( start != 0 && len != 0 ) {
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( dvdcss_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key!!\n");
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) t_e.tv_sec - t_s.tv_sec );
}
if( title == 0 ) continue;
gettimeofday( &t_s, NULL );
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
start = UDFFindFile( dvd, filename, &len );
if( start == 0 || len == 0 ) break;
/* Perform CSS key cracking for this title. */
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
filename, start );
if( dvdcss_title( dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key!!\n");
}
gettimeofday( &t_e, NULL );
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) t_e.tv_sec - t_s.tv_sec );
}
title--;
fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
gettimeofday(&all_e, NULL);
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
(long int) all_e.tv_sec - all_s.tv_sec );
}
return 0;
}
/** /**
* Open a DVD image or block device file. * Open a DVD image or block device file.
*/ */
static dvd_reader_t *DVDOpenImageFile( const char *location ) static dvd_reader_t *DVDOpenImageFile( const char *location )
{ {
dvd_reader_t *dvd; dvd_reader_t *dvd;
dvdcss_handle dev = 0; dvd_handle dev = 0;
int fd = -1;
setupCSS();
if( dvdcss_library ) { dev = pf_dvd_open( (char *) location );
dev = dvdcss_open( (char *) location, DVDCSS_INIT_DEBUG );
if( !dev ) { if( !dev ) {
fprintf( stderr, "libdvdread: Can't open %s for reading.\n", fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
location ); location );
return 0; return 0;
} }
} else {
fd = open( location, O_RDONLY );
if( fd < 0 ) {
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
location );
return 0;
}
}
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0; if( !dvd ) return 0;
dvd->isImageFile = 1; dvd->isImageFile = 1;
dvd->dev = dev; dvd->dev = dev;
dvd->init_keys = 0;
dvd->fd = fd;
dvd->path_root = 0; dvd->path_root = 0;
return dvd; return dvd;
...@@ -271,12 +106,11 @@ static dvd_reader_t *DVDOpenPath( const char *path_root ) ...@@ -271,12 +106,11 @@ static dvd_reader_t *DVDOpenPath( const char *path_root )
{ {
dvd_reader_t *dvd; dvd_reader_t *dvd;
fprintf(stderr, "libdvdread: opening %s as folder\n", path_root );
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) ); dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0; if( !dvd ) return 0;
dvd->isImageFile = 0; dvd->isImageFile = 0;
dvd->dev = 0; dvd->dev = 0;
dvd->init_keys = 0;
dvd->fd = -1;
dvd->path_root = strdup( path_root ); dvd->path_root = strdup( path_root );
return dvd; return dvd;
...@@ -341,7 +175,10 @@ dvd_reader_t *DVDOpen( const char *path ) ...@@ -341,7 +175,10 @@ dvd_reader_t *DVDOpen( const char *path )
return 0; return 0;
} }
/* First check if this is a block/char device or a file*/ /* Try to open libdvdcss or fall back to standard functions */
DVDSetupRead();
/* First check if this is a block/char device or a file */
if( S_ISBLK( fileinfo.st_mode ) || if( S_ISBLK( fileinfo.st_mode ) ||
S_ISCHR( fileinfo.st_mode ) || S_ISCHR( fileinfo.st_mode ) ||
S_ISREG( fileinfo.st_mode ) ) { S_ISREG( fileinfo.st_mode ) ) {
...@@ -366,6 +203,7 @@ dvd_reader_t *DVDOpen( const char *path ) ...@@ -366,6 +203,7 @@ dvd_reader_t *DVDOpen( const char *path )
FILE *mntfile; FILE *mntfile;
#endif #endif
fprintf(stderr, "libdvdread: file is directory\n" );
/* XXX: We should scream real loud here. */ /* XXX: We should scream real loud here. */
if( !(path_copy = strdup( path ) ) ) return 0; if( !(path_copy = strdup( path ) ) ) return 0;
...@@ -451,6 +289,7 @@ dvd_reader_t *DVDOpen( const char *path ) ...@@ -451,6 +289,7 @@ dvd_reader_t *DVDOpen( const char *path )
break; break;
} }
} }
fprintf(stderr, "libdvdread: mounted device %p\n", me );
fclose( mntfile ); fclose( mntfile );
} }
#endif #endif
...@@ -481,8 +320,7 @@ dvd_reader_t *DVDOpen( const char *path ) ...@@ -481,8 +320,7 @@ dvd_reader_t *DVDOpen( const char *path )
void DVDClose( dvd_reader_t *dvd ) void DVDClose( dvd_reader_t *dvd )
{ {
if( dvd ) { if( dvd ) {
if( dvd->dev ) dvdcss_close( dvd->dev ); if( dvd->dev ) pf_dvd_close( dvd->dev );
if( dvd->fd >= 0 ) close( dvd->fd );
if( dvd->path_root ) free( dvd->path_root ); if( dvd->path_root ) free( dvd->path_root );
free( dvd ); free( dvd );
dvd = 0; dvd = 0;
...@@ -500,12 +338,13 @@ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename ) ...@@ -500,12 +338,13 @@ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
start = UDFFindFile( dvd, filename, &len ); start = UDFFindFile( dvd, filename, &len );
if( !start ) return 0; if( !start ) return 0;
fprintf( stderr, "libdvdread: opening %s as image\n", filename );
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0; if( !dvd_file ) return 0;
dvd_file->dvd = dvd; dvd_file->dvd = dvd;
dvd_file->lb_start = start; dvd_file->lb_start = start;
dvd_file->seek_pos = 0; dvd_file->seek_pos = 0;
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) ); //memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN; dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
return dvd_file; return dvd_file;
...@@ -576,13 +415,14 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) ...@@ -576,13 +415,14 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
char full_path[ PATH_MAX + 1 ]; char full_path[ PATH_MAX + 1 ];
dvd_file_t *dvd_file; dvd_file_t *dvd_file;
struct stat fileinfo; struct stat fileinfo;
int fd; dvd_handle dev;
/* Get the full path of the file. */ /* Get the full path of the file. */
if( !findDVDFile( dvd, filename, full_path ) ) return 0; if( !findDVDFile( dvd, filename, full_path ) ) return 0;
fd = open( full_path, O_RDONLY ); fprintf( stderr, "libdvdread: opening %s as file\n", full_path );
if( fd < 0 ) return 0; dev = pf_dvd_open( full_path );
if( dev == NULL ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0; if( !dvd_file ) return 0;
...@@ -590,7 +430,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) ...@@ -590,7 +430,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
dvd_file->lb_start = 0; dvd_file->lb_start = 0;
dvd_file->seek_pos = 0; dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) ); memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = 0; dvd_file->filesize = 0;
if( stat( full_path, &fileinfo ) < 0 ) { if( stat( full_path, &fileinfo ) < 0 ) {
...@@ -599,19 +439,19 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename ) ...@@ -599,19 +439,19 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
return 0; return 0;
} }
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd; dvd_file->title_devs[ 0 ] = dev;
dvd_file->filesize = dvd_file->title_sizes[ 0 ]; dvd_file->filesize = dvd_file->title_sizes[ 0 ];
return dvd_file; return dvd_file;
} }
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
int title, int menu )
{ {
char filename[ MAX_UDF_FILE_NAME_LEN ]; char filename[ MAX_UDF_FILE_NAME_LEN ];
uint32_t start, len; uint32_t start, len;
dvd_file_t *dvd_file; dvd_file_t *dvd_file;
fprintf( stderr, "libdvdread: opening VOB as image\n" );
if( title == 0 ) { if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" ); sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else { } else {
...@@ -626,7 +466,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, ...@@ -626,7 +466,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
dvd_file->lb_start = start; dvd_file->lb_start = start;
dvd_file->seek_pos = 0; dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) ); memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN; dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
/* Calculate the complete file size for every file in the VOBS */ /* Calculate the complete file size for every file in the VOBS */
...@@ -640,27 +480,15 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, ...@@ -640,27 +480,15 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
} }
} }
/* Hack to crack all the keys on the first open. */ if( pf_dvd_seek( dvd_file->dvd->dev, (int)start, DVDCSS_SEEK_KEY ) < 0 ) {
if( dvdcss_library ) {
if( !dvd_file->dvd->init_keys ) {
initAllCSSKeys( dvd_file->dvd );
dvd_file->dvd->init_keys = 1;
}
}
/* Perform CSS key cracking for this title. */
if( dvdcss_library ) {
if( dvdcss_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n", fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
filename ); filename );
} }
}
return dvd_file; return dvd_file;
} }
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
int title, int menu )
{ {
char filename[ MAX_UDF_FILE_NAME_LEN ]; char filename[ MAX_UDF_FILE_NAME_LEN ];
char full_path[ PATH_MAX + 1 ]; char full_path[ PATH_MAX + 1 ];
...@@ -668,17 +496,18 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, ...@@ -668,17 +496,18 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
dvd_file_t *dvd_file; dvd_file_t *dvd_file;
int i; int i;
fprintf( stderr, "libdvdread: opening VOB as file\n" );
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) ); dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0; if( !dvd_file ) return 0;
dvd_file->dvd = dvd; dvd_file->dvd = dvd;
dvd_file->lb_start = 0; dvd_file->lb_start = 0;
dvd_file->seek_pos = 0; dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) ); memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) ); memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
dvd_file->filesize = 0; dvd_file->filesize = 0;
if( menu ) { if( menu ) {
int fd; dvd_handle dev;
if( title == 0 ) { if( title == 0 ) {
sprintf( filename, "VIDEO_TS.VOB" ); sprintf( filename, "VIDEO_TS.VOB" );
...@@ -690,8 +519,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, ...@@ -690,8 +519,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
return 0; return 0;
} }
fd = open( full_path, O_RDONLY ); dev = pf_dvd_open( full_path );
if( fd < 0 ) { if( dev == NULL ) {
free( dvd_file ); free( dvd_file );
return 0; return 0;
} }
...@@ -702,7 +531,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, ...@@ -702,7 +531,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
return 0; return 0;
} }
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd; dvd_file->title_devs[ 0 ] = dev;
pf_dvd_title( dvd_file->title_devs[0], 0 );
dvd_file->filesize = dvd_file->title_sizes[ 0 ]; dvd_file->filesize = dvd_file->title_sizes[ 0 ];
} else { } else {
...@@ -719,7 +549,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, ...@@ -719,7 +549,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
} }
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN; dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ i ] = open( full_path, O_RDONLY ); dvd_file->title_devs[ i ] = pf_dvd_open( full_path );
pf_dvd_title( dvd_file->title_devs[i], 0 );
dvd_file->filesize += dvd_file->title_sizes[ i ]; dvd_file->filesize += dvd_file->title_sizes[ i ];
} }
if( !(dvd_file->title_sizes[ 0 ]) ) { if( !(dvd_file->title_sizes[ 0 ]) ) {
...@@ -785,8 +616,9 @@ void DVDCloseFile( dvd_file_t *dvd_file ) ...@@ -785,8 +616,9 @@ void DVDCloseFile( dvd_file_t *dvd_file )
if( dvd_file ) { if( dvd_file ) {
if( !dvd_file->dvd->isImageFile ) { if( !dvd_file->dvd->isImageFile ) {
for( i = 0; i < 9; ++i ) { for( i = 0; i < 9; ++i ) {
if( dvd_file->title_fds[ i ] >= 0 ) if( dvd_file->title_devs[ i ] ) {
close( dvd_file->title_fds[ i ] ); pf_dvd_close( dvd_file->title_devs[i] );
}
} }
} }
...@@ -799,7 +631,6 @@ int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, ...@@ -799,7 +631,6 @@ int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data, size_t block_count, unsigned char *data,
int encrypted ) int encrypted )
{ {
if( dvdcss_library ) {
int ret; int ret;
if( !device->dev ) { if( !device->dev ) {
...@@ -807,34 +638,16 @@ int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, ...@@ -807,34 +638,16 @@ int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
return 0; return 0;
} }
ret = dvdcss_seek( device->dev, (int) lb_number ); ret = pf_dvd_seek( device->dev, (int) lb_number, DVDCSS_NOFLAGS );
if( ret != (int) lb_number ) { if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n", fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number ); lb_number );
return 0; return 0;
} }
return (int64_t) ( dvdcss_read( device->dev, (char *) data, return (int64_t) ( pf_dvd_read( device->dev, (char *) data,
(int) block_count, encrypted ) (int) block_count, encrypted )
* (uint64_t) DVD_VIDEO_LB_LEN ); * (uint64_t) DVD_VIDEO_LB_LEN );
} else {
off64_t off;
if( device->fd < 0) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
off = lseek64( device->fd, lb_number * (int64_t) DVD_VIDEO_LB_LEN,
SEEK_SET );
if( off != ( lb_number * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number );
return 0;
}
return (int64_t) ( read( device->fd, data,
block_count * DVD_VIDEO_LB_LEN ) );
}
} }
static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset, static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
...@@ -858,39 +671,39 @@ static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset, ...@@ -858,39 +671,39 @@ static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
if( offset < dvd_file->title_sizes[ i ] ) { if( offset < dvd_file->title_sizes[ i ] ) {
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) { if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
off = lseek64( dvd_file->title_fds[ i ], off = pf_dvd_seek( dvd_file->title_devs[ i ], (int)offset, 0 );
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET ); if( off != (int)offset ) {
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n", fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset ); offset );
return 0; return 0;
} }
ret = read( dvd_file->title_fds[ i ], data, ret = pf_dvd_read( dvd_file->title_devs[ i ], data,
block_count * DVD_VIDEO_LB_LEN ); (int)block_count, DVDCSS_READ_DECRYPT );
break; break;
} else { } else {
size_t part1_size size_t part1_size = dvd_file->title_sizes[ i ] - offset;
= ( dvd_file->title_sizes[ i ] - offset ) * DVD_VIDEO_LB_LEN;
/* FIXME: Really needs to be a while loop. /* FIXME: Really needs to be a while loop.
(This is only true if you try and read >1GB at a time) */ * (This is only true if you try and read >1GB at a time) */
/* Read part 1 */ /* Read part 1 */
off = lseek64( dvd_file->title_fds[ i ], off = pf_dvd_seek( dvd_file->title_devs[ i ], offset, 0 );
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET ); if( off != offset ) {
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n", fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset ); offset );
return 0; return 0;
} }
ret = read( dvd_file->title_fds[ i ], data, part1_size ); ret = pf_dvd_read( dvd_file->title_devs[ i ], data,
part1_size, DVDCSS_READ_DECRYPT );
if( ret < 0 ) return ret; if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set. /* FIXME: This is wrong if i is the last file in the set.
also error from this read will not show in ret. */ * also error from this read will not show in ret. */
/* Read part 2 */ /* Read part 2 */
lseek64( dvd_file->title_fds[ i + 1 ], (off64_t)0, SEEK_SET ); pf_dvd_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
ret2 = read( dvd_file->title_fds[ i + 1 ], data + part1_size, ret2 = pf_dvd_read( dvd_file->title_devs[ i + 1 ], data +
block_count * DVD_VIDEO_LB_LEN - part1_size ); ( part1_size * (int64_t)DVD_VIDEO_LB_LEN ),
block_count - part1_size,
DVDCSS_READ_DECRYPT );
if( ret2 < 0 ) return ret2; if( ret2 < 0 ) return ret2;
break; break;
} }
...@@ -899,7 +712,7 @@ static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset, ...@@ -899,7 +712,7 @@ static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
} }
} }
return ( (int64_t) ret + (int64_t) ret2 ); return ( (int64_t) ret + (int64_t) ret2 ) * DVD_VIDEO_LB_LEN;
} }
/* These are broken for some cases reading more than 2Gb at a time. */ /* These are broken for some cases reading more than 2Gb at a time. */
...@@ -918,6 +731,7 @@ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, ...@@ -918,6 +731,7 @@ ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
if( ret <= 0 ) { if( ret <= 0 ) {
return (ssize_t) ret; return (ssize_t) ret;
} }
{ {
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN ); ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
if( sret == 0 ) { if( sret == 0 ) {
...@@ -933,8 +747,8 @@ int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset ) ...@@ -933,8 +747,8 @@ int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
dvd_file->seek_pos = (uint32_t) offset; dvd_file->seek_pos = (uint32_t) offset;
return offset; return offset;
} else { } else {
return (int32_t) ( lseek( dvd_file->title_fds[ 0 ], return (int32_t) ( lseek( dvd_file->title_devs[0]->i_fd,
(off_t) offset, SEEK_SET ) ); (off_t)offset, SEEK_SET ) );
} }
} }
...@@ -974,7 +788,7 @@ static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data, ...@@ -974,7 +788,7 @@ static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data, static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data,
size_t byte_size ) size_t byte_size )
{ {
return read( dvd_file->title_fds[ 0 ], data, byte_size ); return read( dvd_file->title_devs[0]->i_fd, data, byte_size );
} }
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
...@@ -991,3 +805,121 @@ ssize_t DVDFileSize( dvd_file_t *dvd_file ) ...@@ -991,3 +805,121 @@ ssize_t DVDFileSize( dvd_file_t *dvd_file )
return dvd_file->filesize; return dvd_file->filesize;
} }
int64_t DVDReadVLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, struct iovec * vector, int encrypted )
{
int ret;
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
ret = pf_dvd_seek( device->dev, (int) lb_number, 0 );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number );
return 0;
}
return (int64_t) ( pf_dvd_readv( device->dev, vector,
(int)block_count, encrypted )
* (uint64_t) DVD_VIDEO_LB_LEN );
}
static int64_t DVDReadVBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, struct iovec *vector )
{
return DVDReadVLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, vector, DVDCSS_READ_DECRYPT );
}
static int64_t DVDReadVBlocksPath( dvd_file_t *dvd_file, size_t offset,
size_t block_count, struct iovec *vector )
{
int i;
int ret, ret2;
int off;
ret = 0;
ret2 = 0;
for( i = 0 ; i < 9 ; ++i ) {
if( !dvd_file->title_sizes[ i ] ) {
return 0;
}
if( offset < dvd_file->title_sizes[ i ] ) {
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
off = pf_dvd_seek( dvd_file->title_devs[ i ],
(int)offset, 0 );
if( off != (int)offset ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = pf_dvd_readv( dvd_file->title_devs[ i ], vector,
(int)block_count, DVDCSS_READ_DECRYPT );
break;
} else {
int part1_size = 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) */
/* Read part 1 */
off = pf_dvd_seek( dvd_file->title_devs[ i ], offset, 0 );
if( off != offset ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = pf_dvd_readv( dvd_file->title_devs[ i ], vector,
part1_size, DVDCSS_READ_DECRYPT );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
* also error from this read will not show in ret. */
/* Read part 2 */
pf_dvd_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
ret2 = pf_dvd_readv( dvd_file->title_devs[ i + 1 ],
vector + part1_size,
(int)(block_count - part1_size),
DVDCSS_READ_DECRYPT );
if( ret2 < 0 ) return ret2;
break;
}
} else {
offset -= dvd_file->title_sizes[ i ];
}
}
return ( ret + ret2 ) * (int64_t) DVD_VIDEO_LB_LEN;
}
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, struct iovec * vector )
{
int64_t ret;
if( dvd_file->dvd->isImageFile ) {
ret = DVDReadVBlocksUDF( dvd_file, (uint32_t)offset,
block_count, vector );
} else {
ret = DVDReadVBlocksPath( dvd_file, (size_t) offset,
block_count, vector );
}
if( ret <= 0 ) {
return (ssize_t) ret;
}
{
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
if( sret == 0 )
{
fprintf(stderr, "libdvdread: DVDReadVBlocks got %d bytes\n", (int)ret );
}
return sret;
}
}
...@@ -111,6 +111,12 @@ void DVDCloseFile( dvd_file_t *dvd_file ); ...@@ -111,6 +111,12 @@ void DVDCloseFile( dvd_file_t *dvd_file );
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset, ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, unsigned char *data ); size_t block_count, unsigned char *data );
/**
* The same calling a readv-like function to fill a struct iovec.
*/
struct iovec;
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, struct iovec * vector );
/** /**
* Seek to the given position in the file. Returns the resulting position in * Seek to the given position in the file. Returns the resulting position in
* bytes from the beginning of the file. The seek position is only used for * bytes from the beginning of the file. The seek position is only used for
......
/**
* dvd_setup.c: setup read functions with either libdvdcss
* or minimal DVD access.
*/
/**
* Copyright (C) 2001 VideoLAN
* $Id: dvd_setup.c,v 1.1 2002/01/23 03:15:31 stef Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
* 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, USA.
*/
/**
* Preamble
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/uio.h> /* struct iovec */
#include "dvd_reader.h"
#include "dvd_setup.h"
#ifdef GOD_DAMN_DMCA
/**
* dvd_open: initialize library, open a DVD device.
*/
static dvd_handle dvd_open ( char *psz_target )
{
dvd_handle dev;
/* Allocate the library structure */
dev = malloc( sizeof( dvd_handle ) );
if( dev == NULL )
{
fprintf( stderr, "libdvdread: Could not allocate memory.\n" );
return NULL;
}
/* Open the device */
dev->i_fd = open( psz_target, 0 );
if( dev->i_fd < 0 )
{
fprintf( stderr, "libdvdread: Could not open device.\n" );
free( dev );
return NULL;
}
return dev;
}
/**
* dvd_error: return the last error message
*/
static char * dvd_error ( dvd_handle dev )
{
return "unknown error";
}
/**
* dvd_seek: seek into the device.
*/
static int dvd_seek ( dvd_handle dev, int i_blocks, int i_flags )
{
off_t i_read;
i_read = lseek( dev->i_fd,
(off_t)i_blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET );
return i_read / DVD_VIDEO_LB_LEN;
}
/**
* dvd_title: crack the current title key if needed.
*/
static int dvd_title ( dvd_handle dev, int i_block )
{
return 0;
}
/**
* dvd_read: read data from the device.
*/
static int dvd_read ( dvd_handle dev, void *p_buffer,
int i_blocks,
int i_flags )
{
int i_bytes;
i_bytes = read( dev->i_fd, p_buffer,
(size_t)i_blocks * DVD_VIDEO_LB_LEN );
return i_bytes / DVD_VIDEO_LB_LEN;
}
/**
* dvd_readv: read data to an iovec structure.
*/
static int dvd_readv ( dvd_handle dev, void *p_iovec,
int i_blocks,
int i_flags )
{
int i_read;
i_read = readv( dev->i_fd, (struct iovec*)p_iovec, i_blocks );
return i_read / DVD_VIDEO_LB_LEN;
}
/**
* dvd_close: close the DVD device and clean up the library.
*/
static int dvd_close ( dvd_handle dev )
{
int i_ret;
i_ret = close( dev->i_fd );
if( i_ret < 0 )
{
return i_ret;
}
free( dev );
return 0;
}
void DVDSetupRead( void )
{
void * dvdcss_library = NULL;
if( ( dvdcss_library = dlopen( "libdvdcss.so.1", RTLD_LAZY ) ) )
{
pf_dvd_open = dlsym( dvdcss_library, "dvdcss_open" );
pf_dvd_close = dlsym( dvdcss_library, "dvdcss_close" );
pf_dvd_title = dlsym( dvdcss_library, "dvdcss_title" );
pf_dvd_seek = dlsym( dvdcss_library, "dvdcss_seek" );
pf_dvd_read = dlsym( dvdcss_library, "dvdcss_read" );
pf_dvd_readv = dlsym( dvdcss_library, "dvdcss_readv" );
pf_dvd_error = dlsym( dvdcss_library, "dvdcss_error" );
if( pf_dvd_open == NULL || pf_dvd_close == NULL
|| pf_dvd_title == NULL || pf_dvd_seek == NULL
|| pf_dvd_read == NULL || pf_dvd_readv == NULL
|| pf_dvd_error == NULL )
{
fprintf( stderr, "libdvdread: Missing symbols in libdvdcss.so.1, "
"this shouldn't happen !" );
dlclose( dvdcss_library );
dvdcss_library = NULL;
}
else
{
printf( "libdvdread: Using libdvdcss.so.1 for DVD access\n" );
}
}
else
{
fprintf( stderr, "libdvdread: Can't open libdvdcss.so.1: %s.\n",
dlerror() );
}
if( !dvdcss_library )
{
/* Replacement functions */
pf_dvd_open = dvd_open;
pf_dvd_close = dvd_close;
pf_dvd_title = dvd_title;
pf_dvd_seek = dvd_seek;
pf_dvd_read = dvd_read;
pf_dvd_readv = dvd_readv;
pf_dvd_error = dvd_error;
}
}
#else
void DVDSetupRead( void )
{
pf_dvd_open = dvdcss_open;
pf_dvd_close = dvdcss_close;
pf_dvd_title = dvdcss_title;
pf_dvd_seek = dvdcss_seek;
pf_dvd_read = dvdcss_read;
pf_dvd_readv = dvdcss_readv;
pf_dvd_error = dvdcss_error;
}
#endif
/***************************************************************************** /**
* libdvdcss.h: DVD reading library, exported functions. * dvd_setup.h: setup functions header.
***************************************************************************** */
* Copyright (C) 1998-2001 VideoLAN
* $Id: dvdcss.h,v 1.1 2001/11/25 05:04:38 stef Exp $ /* Copyright (C) 2001 VideoLAN
* $Id: dvd_setup.h,v 1.1 2002/01/23 03:15:31 stef Exp $
* *
* Authors: Stphane Borel <stef@via.ecp.fr> * Authors: Samuel Hocevar <sam@zoy.org>
* Samuel Hocevar <sam@zoy.org>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -20,22 +20,45 @@ ...@@ -20,22 +20,45 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/ */
/***************************************************************************** /**
* The libdvdcss structure * The libdvdcss structure.
*****************************************************************************/ */
typedef struct dvdcss_s* dvdcss_handle; struct dvdcss_s
{
/* File descriptor */
int i_fd;
};
/***************************************************************************** #ifdef GOD_DAMN_DMCA
* Flags /**
*****************************************************************************/ * Defines and flags.
#define DVDCSS_NOFLAGS 0 */
# define DVDCSS_NOFLAGS 0
# define DVDCSS_READ_DECRYPT (1 << 0)
# define DVDCSS_SEEK_MPEG (1 << 0)
# define DVDCSS_SEEK_KEY (1 << 1)
#define DVDCSS_INIT_QUIET (1 << 0) #else
#define DVDCSS_INIT_DEBUG (1 << 1) # include <videolan/dvdcss.h>
#endif
#define DVDCSS_READ_DECRYPT (1 << 0) typedef struct dvdcss_s* dvd_handle;
#define DVDCSS_BLOCK_SIZE 2048 /**
* Pointers which will be filled either with dummy functions or
* with the dlopen()ed ones.
*/
dvd_handle (*pf_dvd_open) ( char * );
int (*pf_dvd_close) ( dvd_handle );
int (*pf_dvd_title) ( dvd_handle, int );
int (*pf_dvd_seek) ( dvd_handle, int, int );
int (*pf_dvd_read) ( dvd_handle, void *, int, int );
int (*pf_dvd_readv) ( dvd_handle, void *, int, int );
char * (*pf_dvd_error) ( dvd_handle );
/**
* Setup function accessed by dvd_reader.c
*/
void DVDSetupRead( void );
/*****************************************************************************
* dvdread.c: replacement for dvd_reader.c that always takes dvdcss functions
* (hard-linked) and adds a readv call function to tha API.
*****************************************************************************
* Copyright (C) 2001 Billy Biggs <vektor@dumbterm.net>.
* $Id: dvdread.c,v 1.3 2002/01/15 05:22:21 stef Exp $
*
* Author: Billy Biggs <vektor@dumbterm.net>
* Stphane Borel <stef@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.
*
* 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.
*****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h> /* readv() */
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <dlfcn.h>
#include <dirent.h>
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
#define SYS_BSD 1
#endif
#if defined(__sun)
#include <sys/mnttab.h>
#elif defined(SYS_BSD)
#include <fstab.h>
#elif defined(__linux__)
#include <mntent.h>
#endif
#if defined(SYS_BSD)
typedef off_t off64_t;
#define lseek64 lseek
#define stat64 stat
#endif
#include "dvd_udf.h"
#include "dvd_reader.h"
#include "../libdvdcss/videolan/dvdcss.h"
struct dvd_reader_s {
/* Basic information. */
int isImageFile;
/* Information required for an image file. */
dvdcss_handle dev;
int init_keys;
int fd;
/* Information required for a directory path drive. */
char *path_root;
};
struct dvd_file_s {
/* Basic information. */
dvd_reader_t *dvd;
/* Information required for an image file. */
uint32_t lb_start;
uint32_t seek_pos;
/* Information required for a directory path drive. */
dvdcss_handle title_devs[9];
size_t title_sizes[ 9 ];
int title_fds[ 9 ];
/* Calculated at open-time, size in blocks. */
ssize_t filesize;
};
/**
* Open a DVD image or block device file.
*/
static dvd_reader_t *DVDOpenImageFile( const char *location )
{
dvd_reader_t *dvd;
dvdcss_handle dev = 0;
int fd = -1;
dev = dvdcss_open( (char *) location );
if( !dev ) {
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
location );
return 0;
}
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 1;
dvd->dev = dev;
dvd->init_keys = 0;
dvd->fd = fd;
dvd->path_root = 0;
return dvd;
}
static dvd_reader_t *DVDOpenPath( const char *path_root )
{
dvd_reader_t *dvd;
fprintf(stderr, "libdvdread: opening %s as folder\n", path_root );
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 0;
dvd->dev = 0;
dvd->init_keys = 0;
dvd->fd = -1;
dvd->path_root = strdup( path_root );
return dvd;
}
#if defined(__sun)
/* /dev/rdsk/c0t6d0s0 (link to /devices/...)
/vol/dev/rdsk/c0t6d0/??
/vol/rdsk/<name> */
static char *sun_block2char( const char *path )
{
char *new_path;
/* Must contain "/dsk/" */
if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
/* Replace "/dsk/" with "/rdsk/" */
new_path = 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/" ) );
return new_path;
}
#endif
#if defined(SYS_BSD)
/* FreeBSD /dev/(r)(a)cd0 (a is for atapi, should work without r)
OpenBSD /dev/rcd0c
NetBSD /dev/rcd0d or /dev/rcd0c (for non x86)
BSD/OS /dev/sr0 (if not mounted) or /dev/rsr0 */
static char *bsd_block2char( const char *path )
{
char *new_path;
/* If it doesn't start with "/dev/" or does start with "/dev/r" exit */
if( !strncmp( path, "/dev/", 5 ) || strncmp( path, "/dev/r", 6 ) )
return (char *) strdup( path );
/* Replace "/dev/" with "/dev/r" */
new_path = malloc( strlen(path) + 2 );
strcpy( new_path, "/dev/r" );
strcat( new_path, path + strlen( "/dev/" ) );
return new_path;
}
#endif
dvd_reader_t *DVDOpen( const char *path )
{
struct stat64 fileinfo;
int ret;
if( !path ) return 0;
ret = stat64( path, &fileinfo );
if( ret < 0 ) {
/* If we can't stat the file, give up */
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
perror("");
return 0;
}
/* First check if this is a block/char device or a file*/
if( S_ISBLK( fileinfo.st_mode ) ||
S_ISCHR( fileinfo.st_mode ) ||
S_ISREG( fileinfo.st_mode ) ) {
/**
* Block devices and regular files are assumed to be DVD-Video images.
*/
#if defined(__sun)
return DVDOpenImageFile( sun_block2char( path ) );
#elif defined(SYS_BSD)
return DVDOpenImageFile( bsd_block2char( path ) );
#else
return DVDOpenImageFile( path );
#endif
} else if( S_ISDIR( fileinfo.st_mode ) ) {
dvd_reader_t *auth_drive = 0;
char *path_copy;
#if defined(SYS_BSD)
struct fstab* fe;
#elif defined(__sun) || defined(__linux__)
FILE *mntfile;
#endif
/* XXX: We should scream real loud here. */
if( !(path_copy = strdup( path ) ) ) return 0;
/* Resolve any symlinks and get the absolut dir name. */
{
char *new_path;
int cdir = open( ".", O_RDONLY );
if( cdir >= 0 ) {
chdir( path_copy );
new_path = getcwd( NULL, PATH_MAX );
fchdir( cdir );
close( cdir );
if( new_path ) {
free( path_copy );
path_copy = new_path;
}
}
}
/**
* 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.
*/
if( strlen( path_copy ) > 1 ) {
if( path[ strlen( path_copy ) - 1 ] == '/' )
path_copy[ strlen( path_copy ) - 1 ] = '\0';
}
if( strlen( path_copy ) > 9 ) {
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
"/video_ts" ) ) {
path_copy[ strlen( path_copy ) - 9 ] = '\0';
}
}
#if defined(SYS_BSD)
if( ( fe = getfsfile( path_copy ) ) ) {
char *dev_name = bsd_block2char( fe->fs_spec );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
fe->fs_file );
auth_drive = DVDOpenImageFile( dev_name );
free( dev_name );
}
#elif defined(__sun)
mntfile = fopen( MNTTAB, "r" );
if( mntfile ) {
struct mnttab mp;
int res;
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
char *dev_name = sun_block2char( mp.mnt_special );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
mp.mnt_mountp );
auth_drive = DVDOpenImageFile( dev_name );
free( dev_name );
break;
}
}
fclose( mntfile );
}
#elif defined(__linux__)
mntfile = fopen( MOUNTED, "r" );
if( mntfile ) {
struct mntent *me;
while( ( me = getmntent( mntfile ) ) ) {
if( !strcmp( me->mnt_dir, path_copy ) ) {
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
me->mnt_fsname,
me->mnt_dir );
auth_drive = DVDOpenImageFile( me->mnt_fsname );
break;
}
}
fclose( mntfile );
}
#endif
if( !auth_drive ) {
fprintf( stderr, "libdvdread: Device inaccessible, "
"CSS authentication not available.\n" );
}
free( path_copy );
/**
* 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.
*/
fprintf( stderr, "libdvdread: Using normal filesystem access.\n" );
return DVDOpenPath( path );
}
/* If it's none of the above, screw it. */
fprintf( stderr, "libdvdread: Could not open %s\n", path );
return 0;
}
void DVDClose( dvd_reader_t *dvd )
{
if( dvd ) {
if( dvd->dev ) dvdcss_close( dvd->dev );
if( dvd->fd >= 0 ) close( dvd->fd );
if( dvd->path_root ) free( dvd->path_root );
free( dvd );
dvd = 0;
}
}
/**
* 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;
start = UDFFindFile( dvd, filename, &len );
if( !start ) return 0;
fprintf( stderr, "libdvdread: opening %s as image\n", filename );
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
return dvd_file;
}
/**
* Searches for <file> in directory <path>, ignoring case.
* Returns 0 and full filename in <filename>.
* or -1 on file not found.
* or -2 on path not found.
*/
static int findDirFile( const char *path, const char *file, char *filename )
{
DIR *dir;
struct dirent *ent;
dir = opendir( path );
if( !dir ) return -2;
while( ( ent = readdir( dir ) ) != NULL ) {
if( !strcasecmp( ent->d_name, file ) ) {
sprintf( filename, "%s%s%s", path,
( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
ent->d_name );
return 0;
}
}
return -1;
}
static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
{
char video_path[ PATH_MAX + 1 ];
const char *nodirfile;
int ret;
/* Strip off the directory for our search */
if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
nodirfile = &(file[ 10 ]);
} else {
nodirfile = file;
}
ret = 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 = 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 = findDirFile( video_path, nodirfile, filename );
if( ret < 0 ) {
return 0;
}
}
}
return 1;
}
/**
* Open an unencrypted file from a DVD directory tree.
*/
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;
int fd;
/* Get the full path of the file. */
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
fprintf( stderr, "libdvdread: opening %s as file\n", full_path );
fd = open( full_path, O_RDONLY );
if( fd < 0 ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = 0;
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd;
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
return dvd_file;
}
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;
fprintf( stderr, "libdvdread: opening VOB as image\n" );
if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
}
start = UDFFindFile( dvd, filename, &len );
if( start == 0 ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
/* Calculate the complete file size for every file in the VOBS */
if( !menu ) {
int cur;
for( cur = 2; cur < 10; cur++ ) {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
if( !UDFFindFile( dvd, filename, &len ) ) break;
dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
}
}
if( dvdcss_seek( dvd_file->dvd->dev, (int)start, DVDCSS_SEEK_KEY ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
filename );
}
return dvd_file;
}
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
char full_path[ PATH_MAX + 1 ];
struct stat fileinfo;
dvd_file_t *dvd_file;
int i;
fprintf( stderr, "libdvdread: opening VOB as file\n" );
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = 0;
if( menu ) {
int fd;
if( title == 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;
}
fd = open( full_path, O_RDONLY );
if( fd < 0 ) {
free( dvd_file );
return 0;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd;
dvd_file->title_devs[ 0 ] = dvdcss_open( full_path );
dvdcss_title( dvd_file->title_devs[0], 0 );
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
} else {
for( i = 0; i < 9; ++i ) {
sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
if( !findDVDFile( dvd, filename, full_path ) ) {
break;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
break;
}
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ i ] = open( full_path, O_RDONLY );
dvd_file->title_devs[ i ] = dvdcss_open( full_path );
dvdcss_title( dvd_file->title_devs[i], 0 );
dvd_file->filesize += dvd_file->title_sizes[ i ];
}
if( !(dvd_file->title_sizes[ 0 ]) ) {
free( dvd_file );
return 0;
}
}
return dvd_file;
}
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
dvd_read_domain_t domain )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
switch( domain ) {
case DVD_READ_INFO_FILE:
if( titlenum == 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 == 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 == 0 ) return 0;
if( dvd->isImageFile ) {
return DVDOpenVOBUDF( dvd, titlenum, 0 );
} else {
return DVDOpenVOBPath( dvd, titlenum, 0 );
}
break;
default:
fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
return 0;
}
if( dvd->isImageFile ) {
return DVDOpenFileUDF( dvd, filename );
} else {
return DVDOpenFilePath( dvd, filename );
}
}
void DVDCloseFile( dvd_file_t *dvd_file )
{
int i;
if( dvd_file ) {
if( !dvd_file->dvd->isImageFile ) {
for( i = 0; i < 9; ++i ) {
if( dvd_file->title_fds[ i ] >= 0 )
{
close( dvd_file->title_fds[ i ] );
dvdcss_close( dvd_file->title_devs[i] );
}
}
}
free( dvd_file );
dvd_file = 0;
}
}
int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted )
{
int ret;
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
ret = dvdcss_seek( device->dev, (int) lb_number, DVDCSS_NOFLAGS );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number );
return 0;
}
return (int64_t) ( dvdcss_read( device->dev, (char *) data,
(int) block_count, encrypted )
* (uint64_t) DVD_VIDEO_LB_LEN );
}
static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, unsigned char *data )
{
return DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, data, DVDCSS_READ_DECRYPT );
}
static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
size_t block_count, unsigned char *data )
{
int i;
ssize_t ret, ret2;
off64_t off;
ret = 0;
ret2 = 0;
for( i = 0; i < 9; ++i ) {
if( !dvd_file->title_sizes[ i ] ) return 0;
if( offset < dvd_file->title_sizes[ i ] ) {
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
off = lseek64( dvd_file->title_fds[ i ],
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = read( dvd_file->title_fds[ i ], data,
block_count * DVD_VIDEO_LB_LEN );
break;
} else {
size_t part1_size
= ( dvd_file->title_sizes[ i ] - offset ) * DVD_VIDEO_LB_LEN;
/* FIXME: Really needs to be a while loop.
(This is only true if you try and read >1GB at a time) */
/* Read part 1 */
off = lseek64( dvd_file->title_fds[ i ],
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = read( dvd_file->title_fds[ i ], data, part1_size );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
also error from this read will not show in ret. */
/* Read part 2 */
lseek64( dvd_file->title_fds[ i + 1 ], (off64_t)0, SEEK_SET );
ret2 = read( dvd_file->title_fds[ i + 1 ], data + part1_size,
block_count * DVD_VIDEO_LB_LEN - part1_size );
if( ret2 < 0 ) return ret2;
break;
}
} else {
offset -= dvd_file->title_sizes[ i ];
}
}
return ( (int64_t) ret + (int64_t) ret2 );
}
/* These are broken for some cases reading more than 2Gb at a time. */
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, unsigned char *data )
{
int64_t ret;
if( dvd_file->dvd->isImageFile ) {
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
block_count, data );
} else {
ret = DVDReadBlocksPath( dvd_file, (size_t) offset,
block_count, data );
}
if( ret <= 0 ) {
return (ssize_t) ret;
}
{
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
if( sret == 0 ) {
fprintf(stderr, "libdvdread: DVDReadBlocks got %d bytes\n", (int)ret );
}
return sret;
}
}
int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
{
if( dvd_file->dvd->isImageFile ) {
dvd_file->seek_pos = (uint32_t) offset;
return offset;
} else {
return (int32_t) ( lseek( dvd_file->title_fds[ 0 ],
(off_t) offset, SEEK_SET ) );
}
}
static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
size_t byte_size )
{
unsigned char *secbuf;
unsigned int numsec, seek_sector, seek_byte;
int64_t len;
seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1;
secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
if( !secbuf ) {
fprintf( stderr, "libdvdread: Can't allocate memory "
"for file read!\n" );
return 0;
}
len = DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + seek_sector,
numsec, secbuf, DVDCSS_NOFLAGS );
if( len != numsec * (int64_t) DVD_VIDEO_LB_LEN ) {
free( secbuf );
return 0;
}
dvd_file->seek_pos += byte_size;
memcpy( data, &(secbuf[ seek_byte ]), byte_size );
free( secbuf );
return byte_size;
}
static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data,
size_t byte_size )
{
return read( dvd_file->title_fds[ 0 ], data, byte_size );
}
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
{
if( dvd_file->dvd->isImageFile ) {
return DVDReadBytesUDF( dvd_file, data, byte_size );
} else {
return DVDReadBytesPath( dvd_file, data, byte_size );
}
}
ssize_t DVDFileSize( dvd_file_t *dvd_file )
{
return dvd_file->filesize;
}
int64_t DVDReadVLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, struct iovec * vector,
int encrypted )
{
int ret;
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
ret = dvdcss_seek( device->dev, (int) lb_number, 0 );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number );
return 0;
}
return (int64_t) ( dvdcss_readv( device->dev, vector,
(int)block_count, encrypted )
* (uint64_t) DVD_VIDEO_LB_LEN );
}
static int64_t DVDReadVBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, struct iovec *vector )
{
return DVDReadVLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, vector, DVDCSS_READ_DECRYPT );
}
static int64_t DVDReadVBlocksPath( dvd_file_t *dvd_file, size_t offset,
size_t block_count, struct iovec *vector )
{
int i;
int ret, ret2;
int off;
ret = 0;
ret2 = 0;
for( i = 0 ; i < 9 ; ++i )
{
if( !dvd_file->title_sizes[ i ] )
{
return 0;
}
if( offset < dvd_file->title_sizes[ i ] )
{
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] )
{
off = dvdcss_seek( dvd_file->title_devs[ i ],
(int)offset, 0 );
if( off != (int)offset )
{
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
(int)block_count, DVDCSS_READ_DECRYPT );
break;
}
else
{
int part1_size = 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) */
/* Read part 1 */
off = dvdcss_seek( dvd_file->title_devs[ i ], offset, 0 );
if( off != offset )
{
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
part1_size, DVDCSS_READ_DECRYPT );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
also error from this read will not show in ret. */
/* Read part 2 */
dvdcss_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
ret2 = dvdcss_readv( dvd_file->title_devs[ i + 1 ],
vector + part1_size, (int)(block_count - part1_size),
DVDCSS_READ_DECRYPT );
if( ret2 < 0 ) return ret2;
break;
}
}
else
{
offset -= dvd_file->title_sizes[ i ];
}
}
return ( ret + ret2 ) * (int64_t) DVD_VIDEO_LB_LEN;
}
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, struct iovec * vector )
{
int64_t ret;
if( dvd_file->dvd->isImageFile )
{
ret = DVDReadVBlocksUDF( dvd_file, (uint32_t)offset,
block_count, vector );
}
else
{
ret = DVDReadVBlocksPath( dvd_file, (size_t) offset,
block_count, vector );
}
if( ret <= 0 )
{
return (ssize_t) ret;
}
{
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
if( sret == 0 )
{
fprintf(stderr, "libdvdread: DVDReadVBlocks got %d bytes\n", (int)ret );
}
return sret;
}
}
...@@ -20,10 +20,8 @@ ...@@ -20,10 +20,8 @@
#ifndef IFO_PRINT_H_INCLUDED #ifndef IFO_PRINT_H_INCLUDED
#define IFO_PRINT_H_INCLUDED #define IFO_PRINT_H_INCLUDED
//#include <dvdread/ifo_types.h> #include <dvdread/ifo_types.h>
//#include <dvdread/dvd_reader.h> #include <dvdread/dvd_reader.h>
#include "ifo_types.h"
#include "dvd_reader.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
...@@ -20,10 +20,8 @@ ...@@ -20,10 +20,8 @@
#ifndef IFO_READ_H_INCLUDED #ifndef IFO_READ_H_INCLUDED
#define IFO_READ_H_INCLUDED #define IFO_READ_H_INCLUDED
//#include <dvdread/ifo_types.h> #include <dvdread/ifo_types.h>
//#include <dvdread/dvd_reader.h> #include <dvdread/dvd_reader.h>
#include "ifo_types.h"
#include "dvd_reader.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
#define IFO_TYPES_H_INCLUDED #define IFO_TYPES_H_INCLUDED
#include <inttypes.h> #include <inttypes.h>
//#include <dvdread/dvd_reader.h> #include <dvdread/dvd_reader.h>
#include "dvd_reader.h"
#undef ATTRIBUTE_PACKED #undef ATTRIBUTE_PACKED
......
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
#define NAV_PRINT_H_INCLUDED #define NAV_PRINT_H_INCLUDED
#include <stdio.h> #include <stdio.h>
//#include <dvdread/nav_types.h> #include <dvdread/nav_types.h>
#include "nav_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
...@@ -19,8 +19,7 @@ ...@@ -19,8 +19,7 @@
#ifndef NAV_READ_H_INCLUDED #ifndef NAV_READ_H_INCLUDED
#define NAV_READ_H_INCLUDED #define NAV_READ_H_INCLUDED
//#include <dvdread/nav_types.h> #include <dvdread/nav_types.h>
#include "nav_types.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
......
...@@ -30,8 +30,8 @@ ...@@ -30,8 +30,8 @@
#define NAV_TYPES_H_INCLUDED #define NAV_TYPES_H_INCLUDED
#include <inttypes.h> #include <inttypes.h>
//#include <dvdread/ifo_types.h> // only dvd_time_t, vm_cmd_t and user_ops_t #include <dvdread/ifo_types.h> // only dvd_time_t, vm_cmd_t and user_ops_t
#include "ifo_types.h"
#undef ATTRIBUTE_PACKED #undef ATTRIBUTE_PACKED
#undef PRAGMA_PACK_BEGIN #undef PRAGMA_PACK_BEGIN
......
/*****************************************************************************
* dvdread.c: replacement for dvd_reader.c that always takes dvdcss functions
* (hard-linked) and adds a readv call function to tha API.
*****************************************************************************
* Copyright (C) 2001 Billy Biggs <vektor@dumbterm.net>.
* $Id: dvdread.c,v 1.2 2002/01/15 05:22:21 stef Exp $
*
* Author: Billy Biggs <vektor@dumbterm.net>
* Stphane Borel <stef@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.
*
* 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.
*****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/uio.h> /* readv() */
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <dlfcn.h>
#include <dirent.h>
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
#define SYS_BSD 1
#endif
#if defined(__sun)
#include <sys/mnttab.h>
#elif defined(SYS_BSD)
#include <fstab.h>
#elif defined(__linux__)
#include <mntent.h>
#endif
#if defined(SYS_BSD)
typedef off_t off64_t;
#define lseek64 lseek
#define stat64 stat
#endif
#include "dvd_udf.h"
#include "dvd_reader.h"
#include "../libdvdcss/videolan/dvdcss.h"
struct dvd_reader_s {
/* Basic information. */
int isImageFile;
/* Information required for an image file. */
dvdcss_handle dev;
int init_keys;
int fd;
/* Information required for a directory path drive. */
char *path_root;
};
struct dvd_file_s {
/* Basic information. */
dvd_reader_t *dvd;
/* Information required for an image file. */
uint32_t lb_start;
uint32_t seek_pos;
/* Information required for a directory path drive. */
dvdcss_handle title_devs[9];
size_t title_sizes[ 9 ];
int title_fds[ 9 ];
/* Calculated at open-time, size in blocks. */
ssize_t filesize;
};
/**
* Open a DVD image or block device file.
*/
static dvd_reader_t *DVDOpenImageFile( const char *location )
{
dvd_reader_t *dvd;
dvdcss_handle dev = 0;
int fd = -1;
dev = dvdcss_open( (char *) location );
if( !dev ) {
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
location );
return 0;
}
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 1;
dvd->dev = dev;
dvd->init_keys = 0;
dvd->fd = fd;
dvd->path_root = 0;
return dvd;
}
static dvd_reader_t *DVDOpenPath( const char *path_root )
{
dvd_reader_t *dvd;
fprintf(stderr, "libdvdread: opening %s as folder\n", path_root );
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
if( !dvd ) return 0;
dvd->isImageFile = 0;
dvd->dev = 0;
dvd->init_keys = 0;
dvd->fd = -1;
dvd->path_root = strdup( path_root );
return dvd;
}
#if defined(__sun)
/* /dev/rdsk/c0t6d0s0 (link to /devices/...)
/vol/dev/rdsk/c0t6d0/??
/vol/rdsk/<name> */
static char *sun_block2char( const char *path )
{
char *new_path;
/* Must contain "/dsk/" */
if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
/* Replace "/dsk/" with "/rdsk/" */
new_path = 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/" ) );
return new_path;
}
#endif
#if defined(SYS_BSD)
/* FreeBSD /dev/(r)(a)cd0 (a is for atapi, should work without r)
OpenBSD /dev/rcd0c
NetBSD /dev/rcd0d or /dev/rcd0c (for non x86)
BSD/OS /dev/sr0 (if not mounted) or /dev/rsr0 */
static char *bsd_block2char( const char *path )
{
char *new_path;
/* If it doesn't start with "/dev/" or does start with "/dev/r" exit */
if( !strncmp( path, "/dev/", 5 ) || strncmp( path, "/dev/r", 6 ) )
return (char *) strdup( path );
/* Replace "/dev/" with "/dev/r" */
new_path = malloc( strlen(path) + 2 );
strcpy( new_path, "/dev/r" );
strcat( new_path, path + strlen( "/dev/" ) );
return new_path;
}
#endif
dvd_reader_t *DVDOpen( const char *path )
{
struct stat64 fileinfo;
int ret;
if( !path ) return 0;
ret = stat64( path, &fileinfo );
if( ret < 0 ) {
/* If we can't stat the file, give up */
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
perror("");
return 0;
}
/* First check if this is a block/char device or a file*/
if( S_ISBLK( fileinfo.st_mode ) ||
S_ISCHR( fileinfo.st_mode ) ||
S_ISREG( fileinfo.st_mode ) ) {
/**
* Block devices and regular files are assumed to be DVD-Video images.
*/
#if defined(__sun)
return DVDOpenImageFile( sun_block2char( path ) );
#elif defined(SYS_BSD)
return DVDOpenImageFile( bsd_block2char( path ) );
#else
return DVDOpenImageFile( path );
#endif
} else if( S_ISDIR( fileinfo.st_mode ) ) {
dvd_reader_t *auth_drive = 0;
char *path_copy;
#if defined(SYS_BSD)
struct fstab* fe;
#elif defined(__sun) || defined(__linux__)
FILE *mntfile;
#endif
/* XXX: We should scream real loud here. */
if( !(path_copy = strdup( path ) ) ) return 0;
/* Resolve any symlinks and get the absolut dir name. */
{
char *new_path;
int cdir = open( ".", O_RDONLY );
if( cdir >= 0 ) {
chdir( path_copy );
new_path = getcwd( NULL, PATH_MAX );
fchdir( cdir );
close( cdir );
if( new_path ) {
free( path_copy );
path_copy = new_path;
}
}
}
/**
* 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.
*/
if( strlen( path_copy ) > 1 ) {
if( path[ strlen( path_copy ) - 1 ] == '/' )
path_copy[ strlen( path_copy ) - 1 ] = '\0';
}
if( strlen( path_copy ) > 9 ) {
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
"/video_ts" ) ) {
path_copy[ strlen( path_copy ) - 9 ] = '\0';
}
}
#if defined(SYS_BSD)
if( ( fe = getfsfile( path_copy ) ) ) {
char *dev_name = bsd_block2char( fe->fs_spec );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
fe->fs_file );
auth_drive = DVDOpenImageFile( dev_name );
free( dev_name );
}
#elif defined(__sun)
mntfile = fopen( MNTTAB, "r" );
if( mntfile ) {
struct mnttab mp;
int res;
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
char *dev_name = sun_block2char( mp.mnt_special );
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
dev_name,
mp.mnt_mountp );
auth_drive = DVDOpenImageFile( dev_name );
free( dev_name );
break;
}
}
fclose( mntfile );
}
#elif defined(__linux__)
mntfile = fopen( MOUNTED, "r" );
if( mntfile ) {
struct mntent *me;
while( ( me = getmntent( mntfile ) ) ) {
if( !strcmp( me->mnt_dir, path_copy ) ) {
fprintf( stderr,
"libdvdread: Attempting to use device %s"
" mounted on %s for CSS authentication\n",
me->mnt_fsname,
me->mnt_dir );
auth_drive = DVDOpenImageFile( me->mnt_fsname );
break;
}
}
fclose( mntfile );
}
#endif
if( !auth_drive ) {
fprintf( stderr, "libdvdread: Device inaccessible, "
"CSS authentication not available.\n" );
}
free( path_copy );
/**
* 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.
*/
fprintf( stderr, "libdvdread: Using normal filesystem access.\n" );
return DVDOpenPath( path );
}
/* If it's none of the above, screw it. */
fprintf( stderr, "libdvdread: Could not open %s\n", path );
return 0;
}
void DVDClose( dvd_reader_t *dvd )
{
if( dvd ) {
if( dvd->dev ) dvdcss_close( dvd->dev );
if( dvd->fd >= 0 ) close( dvd->fd );
if( dvd->path_root ) free( dvd->path_root );
free( dvd );
dvd = 0;
}
}
/**
* 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;
start = UDFFindFile( dvd, filename, &len );
if( !start ) return 0;
fprintf( stderr, "libdvdread: opening %s as image\n", filename );
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
return dvd_file;
}
/**
* Searches for <file> in directory <path>, ignoring case.
* Returns 0 and full filename in <filename>.
* or -1 on file not found.
* or -2 on path not found.
*/
static int findDirFile( const char *path, const char *file, char *filename )
{
DIR *dir;
struct dirent *ent;
dir = opendir( path );
if( !dir ) return -2;
while( ( ent = readdir( dir ) ) != NULL ) {
if( !strcasecmp( ent->d_name, file ) ) {
sprintf( filename, "%s%s%s", path,
( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
ent->d_name );
return 0;
}
}
return -1;
}
static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
{
char video_path[ PATH_MAX + 1 ];
const char *nodirfile;
int ret;
/* Strip off the directory for our search */
if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
nodirfile = &(file[ 10 ]);
} else {
nodirfile = file;
}
ret = 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 = 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 = findDirFile( video_path, nodirfile, filename );
if( ret < 0 ) {
return 0;
}
}
}
return 1;
}
/**
* Open an unencrypted file from a DVD directory tree.
*/
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;
int fd;
/* Get the full path of the file. */
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
fprintf( stderr, "libdvdread: opening %s as file\n", full_path );
fd = open( full_path, O_RDONLY );
if( fd < 0 ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = 0;
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd;
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
return dvd_file;
}
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;
fprintf( stderr, "libdvdread: opening VOB as image\n" );
if( title == 0 ) {
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
} else {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
}
start = UDFFindFile( dvd, filename, &len );
if( start == 0 ) return 0;
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = start;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
/* Calculate the complete file size for every file in the VOBS */
if( !menu ) {
int cur;
for( cur = 2; cur < 10; cur++ ) {
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
if( !UDFFindFile( dvd, filename, &len ) ) break;
dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
}
}
if( dvdcss_seek( dvd_file->dvd->dev, (int)start, DVDCSS_SEEK_KEY ) < 0 ) {
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
filename );
}
return dvd_file;
}
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
int title, int menu )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
char full_path[ PATH_MAX + 1 ];
struct stat fileinfo;
dvd_file_t *dvd_file;
int i;
fprintf( stderr, "libdvdread: opening VOB as file\n" );
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
if( !dvd_file ) return 0;
dvd_file->dvd = dvd;
dvd_file->lb_start = 0;
dvd_file->seek_pos = 0;
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
dvd_file->filesize = 0;
if( menu ) {
int fd;
if( title == 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;
}
fd = open( full_path, O_RDONLY );
if( fd < 0 ) {
free( dvd_file );
return 0;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
free( dvd_file );
return 0;
}
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ 0 ] = fd;
dvd_file->title_devs[ 0 ] = dvdcss_open( full_path );
dvdcss_title( dvd_file->title_devs[0], 0 );
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
} else {
for( i = 0; i < 9; ++i ) {
sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
if( !findDVDFile( dvd, filename, full_path ) ) {
break;
}
if( stat( full_path, &fileinfo ) < 0 ) {
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
break;
}
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
dvd_file->title_fds[ i ] = open( full_path, O_RDONLY );
dvd_file->title_devs[ i ] = dvdcss_open( full_path );
dvdcss_title( dvd_file->title_devs[i], 0 );
dvd_file->filesize += dvd_file->title_sizes[ i ];
}
if( !(dvd_file->title_sizes[ 0 ]) ) {
free( dvd_file );
return 0;
}
}
return dvd_file;
}
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
dvd_read_domain_t domain )
{
char filename[ MAX_UDF_FILE_NAME_LEN ];
switch( domain ) {
case DVD_READ_INFO_FILE:
if( titlenum == 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 == 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 == 0 ) return 0;
if( dvd->isImageFile ) {
return DVDOpenVOBUDF( dvd, titlenum, 0 );
} else {
return DVDOpenVOBPath( dvd, titlenum, 0 );
}
break;
default:
fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
return 0;
}
if( dvd->isImageFile ) {
return DVDOpenFileUDF( dvd, filename );
} else {
return DVDOpenFilePath( dvd, filename );
}
}
void DVDCloseFile( dvd_file_t *dvd_file )
{
int i;
if( dvd_file ) {
if( !dvd_file->dvd->isImageFile ) {
for( i = 0; i < 9; ++i ) {
if( dvd_file->title_fds[ i ] >= 0 )
{
close( dvd_file->title_fds[ i ] );
dvdcss_close( dvd_file->title_devs[i] );
}
}
}
free( dvd_file );
dvd_file = 0;
}
}
int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, unsigned char *data,
int encrypted )
{
int ret;
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
ret = dvdcss_seek( device->dev, (int) lb_number, DVDCSS_NOFLAGS );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number );
return 0;
}
return (int64_t) ( dvdcss_read( device->dev, (char *) data,
(int) block_count, encrypted )
* (uint64_t) DVD_VIDEO_LB_LEN );
}
static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, unsigned char *data )
{
return DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, data, DVDCSS_READ_DECRYPT );
}
static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
size_t block_count, unsigned char *data )
{
int i;
ssize_t ret, ret2;
off64_t off;
ret = 0;
ret2 = 0;
for( i = 0; i < 9; ++i ) {
if( !dvd_file->title_sizes[ i ] ) return 0;
if( offset < dvd_file->title_sizes[ i ] ) {
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
off = lseek64( dvd_file->title_fds[ i ],
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = read( dvd_file->title_fds[ i ], data,
block_count * DVD_VIDEO_LB_LEN );
break;
} else {
size_t part1_size
= ( dvd_file->title_sizes[ i ] - offset ) * DVD_VIDEO_LB_LEN;
/* FIXME: Really needs to be a while loop.
(This is only true if you try and read >1GB at a time) */
/* Read part 1 */
off = lseek64( dvd_file->title_fds[ i ],
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = read( dvd_file->title_fds[ i ], data, part1_size );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
also error from this read will not show in ret. */
/* Read part 2 */
lseek64( dvd_file->title_fds[ i + 1 ], (off64_t)0, SEEK_SET );
ret2 = read( dvd_file->title_fds[ i + 1 ], data + part1_size,
block_count * DVD_VIDEO_LB_LEN - part1_size );
if( ret2 < 0 ) return ret2;
break;
}
} else {
offset -= dvd_file->title_sizes[ i ];
}
}
return ( (int64_t) ret + (int64_t) ret2 );
}
/* These are broken for some cases reading more than 2Gb at a time. */
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, unsigned char *data )
{
int64_t ret;
if( dvd_file->dvd->isImageFile ) {
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
block_count, data );
} else {
ret = DVDReadBlocksPath( dvd_file, (size_t) offset,
block_count, data );
}
if( ret <= 0 ) {
return (ssize_t) ret;
}
{
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
if( sret == 0 ) {
fprintf(stderr, "libdvdread: DVDReadBlocks got %d bytes\n", (int)ret );
}
return sret;
}
}
int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
{
if( dvd_file->dvd->isImageFile ) {
dvd_file->seek_pos = (uint32_t) offset;
return offset;
} else {
return (int32_t) ( lseek( dvd_file->title_fds[ 0 ],
(off_t) offset, SEEK_SET ) );
}
}
static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
size_t byte_size )
{
unsigned char *secbuf;
unsigned int numsec, seek_sector, seek_byte;
int64_t len;
seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1;
secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
if( !secbuf ) {
fprintf( stderr, "libdvdread: Can't allocate memory "
"for file read!\n" );
return 0;
}
len = DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + seek_sector,
numsec, secbuf, DVDCSS_NOFLAGS );
if( len != numsec * (int64_t) DVD_VIDEO_LB_LEN ) {
free( secbuf );
return 0;
}
dvd_file->seek_pos += byte_size;
memcpy( data, &(secbuf[ seek_byte ]), byte_size );
free( secbuf );
return byte_size;
}
static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data,
size_t byte_size )
{
return read( dvd_file->title_fds[ 0 ], data, byte_size );
}
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
{
if( dvd_file->dvd->isImageFile ) {
return DVDReadBytesUDF( dvd_file, data, byte_size );
} else {
return DVDReadBytesPath( dvd_file, data, byte_size );
}
}
ssize_t DVDFileSize( dvd_file_t *dvd_file )
{
return dvd_file->filesize;
}
int64_t DVDReadVLBUDF( dvd_reader_t *device, uint32_t lb_number,
size_t block_count, struct iovec * vector,
int encrypted )
{
int ret;
if( !device->dev ) {
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
return 0;
}
ret = dvdcss_seek( device->dev, (int) lb_number, 0 );
if( ret != (int) lb_number ) {
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
lb_number );
return 0;
}
return (int64_t) ( dvdcss_readv( device->dev, vector,
(int)block_count, encrypted )
* (uint64_t) DVD_VIDEO_LB_LEN );
}
static int64_t DVDReadVBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
size_t block_count, struct iovec *vector )
{
return DVDReadVLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
block_count, vector, DVDCSS_READ_DECRYPT );
}
static int64_t DVDReadVBlocksPath( dvd_file_t *dvd_file, size_t offset,
size_t block_count, struct iovec *vector )
{
int i;
int ret, ret2;
int off;
ret = 0;
ret2 = 0;
for( i = 0 ; i < 9 ; ++i )
{
if( !dvd_file->title_sizes[ i ] )
{
return 0;
}
if( offset < dvd_file->title_sizes[ i ] )
{
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] )
{
off = dvdcss_seek( dvd_file->title_devs[ i ],
(int)offset, 0 );
if( off != (int)offset )
{
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
(int)block_count, DVDCSS_READ_DECRYPT );
break;
}
else
{
int part1_size = 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) */
/* Read part 1 */
off = dvdcss_seek( dvd_file->title_devs[ i ], offset, 0 );
if( off != offset )
{
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
offset );
return 0;
}
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
part1_size, DVDCSS_READ_DECRYPT );
if( ret < 0 ) return ret;
/* FIXME: This is wrong if i is the last file in the set.
also error from this read will not show in ret. */
/* Read part 2 */
dvdcss_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
ret2 = dvdcss_readv( dvd_file->title_devs[ i + 1 ],
vector + part1_size, (int)(block_count - part1_size),
DVDCSS_READ_DECRYPT );
if( ret2 < 0 ) return ret2;
break;
}
}
else
{
offset -= dvd_file->title_sizes[ i ];
}
}
return ( ret + ret2 ) * (int64_t) DVD_VIDEO_LB_LEN;
}
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, struct iovec * vector )
{
int64_t ret;
if( dvd_file->dvd->isImageFile )
{
ret = DVDReadVBlocksUDF( dvd_file, (uint32_t)offset,
block_count, vector );
}
else
{
ret = DVDReadVBlocksPath( dvd_file, (size_t) offset,
block_count, vector );
}
if( ret <= 0 )
{
return (ssize_t) ret;
}
{
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
if( sret == 0 )
{
fprintf(stderr, "libdvdread: DVDReadVBlocks got %d bytes\n", (int)ret );
}
return sret;
}
}
/*****************************************************************************
* dvdread.h: DVD reading library, exported functions.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: dvdread.h,v 1.1 2001/11/25 05:04:38 stef Exp $
*
* Authors: Stéphane Borel <stef@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.
*
* 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.
*****************************************************************************/
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
size_t block_count, struct iovec * vector );
/* include/defs.h.in. Generated automatically from configure.in by autoheader. */ /* include/defs.h.in. Generated automatically from configure.in by autoheader 2.13. */
/* Define if using alloca.c. */ /* Define if using alloca.c. */
#undef C_ALLOCA #undef C_ALLOCA
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dummy_dvdcss.h: Dummy libdvdcss header. * dummy_dvdcss.h: Dummy libdvdcss header.
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: dummy_dvdcss.h,v 1.6 2002/01/07 02:12:29 sam Exp $ * $Id: dummy_dvdcss.h,v 1.7 2002/01/23 03:15:31 stef Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -51,6 +51,14 @@ char * dummy_dvdcss_error ( dvdcss_handle ); ...@@ -51,6 +51,14 @@ char * dummy_dvdcss_error ( dvdcss_handle );
* Pointers which will be filled either with dummy_dvdcss functions or * Pointers which will be filled either with dummy_dvdcss functions or
* with the dlopen()ed ones. * with the dlopen()ed ones.
*****************************************************************************/ *****************************************************************************/
#define ____dvdcss_open dvdcss_open
#define ____dvdcss_close dvdcss_close
#define ____dvdcss_title dvdcss_title
#define ____dvdcss_seek dvdcss_seek
#define ____dvdcss_read dvdcss_read
#define ____dvdcss_readv dvdcss_readv
#define ____dvdcss_error dvdcss_error
dvdcss_handle (* ____dvdcss_open ) ( char * ); dvdcss_handle (* ____dvdcss_open ) ( char * );
int (* ____dvdcss_close ) ( dvdcss_handle ); int (* ____dvdcss_close ) ( dvdcss_handle );
int (* ____dvdcss_title ) ( dvdcss_handle, int ); int (* ____dvdcss_title ) ( dvdcss_handle, int );
...@@ -59,11 +67,4 @@ int (* ____dvdcss_read ) ( dvdcss_handle, void *, int, int ); ...@@ -59,11 +67,4 @@ int (* ____dvdcss_read ) ( dvdcss_handle, void *, int, int );
int (* ____dvdcss_readv ) ( dvdcss_handle, void *, int, int ); int (* ____dvdcss_readv ) ( dvdcss_handle, void *, int, int );
char * (* ____dvdcss_error ) ( dvdcss_handle ); char * (* ____dvdcss_error ) ( dvdcss_handle );
#define ____dvdcss_open dvdcss_open
#define ____dvdcss_close dvdcss_close
#define ____dvdcss_title dvdcss_title
#define ____dvdcss_seek dvdcss_seek
#define ____dvdcss_read dvdcss_read
#define ____dvdcss_readv dvdcss_readv
#define ____dvdcss_error dvdcss_error
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dvdread.c : DvdRead input module for vlc * dvdread.c : DvdRead input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: dvdread.c,v 1.7 2002/01/08 23:34:06 stef Exp $ * $Id: dvdread.c,v 1.8 2002/01/23 03:15:31 stef Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -29,25 +29,11 @@ ...@@ -29,25 +29,11 @@
#include <videolan/vlc.h> #include <videolan/vlc.h>
#ifdef GOD_DAMN_DMCA
# include <dlfcn.h>
# include "dummy_dvdcss.h"
#endif
/***************************************************************************** /*****************************************************************************
* Capabilities defined in the other files. * Capabilities defined in the other files.
*****************************************************************************/ *****************************************************************************/
void _M( input_getfunctions )( function_list_t * p_function_list ); void _M( input_getfunctions )( function_list_t * p_function_list );
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
#ifdef GOD_DAMN_DMCA
static void *p_libdvdcss;
static void ProbeLibDVDCSS ( void );
static void UnprobeLibDVDCSS( void );
#endif
/***************************************************************************** /*****************************************************************************
* Build configuration tree. * Build configuration tree.
*****************************************************************************/ *****************************************************************************/
...@@ -55,130 +41,15 @@ MODULE_CONFIG_START ...@@ -55,130 +41,15 @@ MODULE_CONFIG_START
MODULE_CONFIG_STOP MODULE_CONFIG_STOP
MODULE_INIT_START MODULE_INIT_START
#ifdef GOD_DAMN_DMCA SET_DESCRIPTION( "DVDRead input module" )
SET_DESCRIPTION( "DVDRead input module, uses libdvdcss if present" )
ADD_CAPABILITY( INPUT, 70 )
#else
SET_DESCRIPTION( "DVDRead input module, linked with libdvdcss" )
ADD_CAPABILITY( INPUT, 110 ) ADD_CAPABILITY( INPUT, 110 )
#endif
ADD_SHORTCUT( "dvdread" ) ADD_SHORTCUT( "dvdread" )
MODULE_INIT_STOP MODULE_INIT_STOP
MODULE_ACTIVATE_START MODULE_ACTIVATE_START
_M( input_getfunctions )( &p_module->p_functions->input ); _M( input_getfunctions )( &p_module->p_functions->input );
#ifdef GOD_DAMN_DMCA
ProbeLibDVDCSS();
#endif
MODULE_ACTIVATE_STOP MODULE_ACTIVATE_STOP
MODULE_DEACTIVATE_START MODULE_DEACTIVATE_START
#ifdef GOD_DAMN_DMCA
UnprobeLibDVDCSS();
#endif
MODULE_DEACTIVATE_STOP MODULE_DEACTIVATE_STOP
/* Following functions are local */
#ifdef GOD_DAMN_DMCA
/*****************************************************************************
* ProbeLibDVDCSS: look for a libdvdcss object.
*****************************************************************************
* This functions looks for libdvdcss, using dlopen(), and fills function
* pointers with what it finds. On failure, uses the dummy libdvdcss
* replacement provided by vlc.
*****************************************************************************/
static void ProbeLibDVDCSS( void )
{
char *pp_filelist[4] = { "libdvdcss.so.0",
"./libdvdcss.so.0",
"./lib/libdvdcss.so.0",
NULL };
char **pp_file = pp_filelist;
/* Try to open the dynamic object */
do
{
p_libdvdcss = dlopen( *pp_file, RTLD_LAZY );
if( p_libdvdcss != NULL )
{
intf_WarnMsg( 2, "module: builtin module `dvd' found libdvdcss "
"in `%s'", *pp_file );
break;
}
pp_file++;
} while( *pp_file != NULL );
/* If libdvdcss.so was found, check that it's valid */
if( p_libdvdcss == NULL )
{
intf_ErrMsg( "dvd warning: libdvdcss.so.0 not present" );
}
else
{
/* Check for libdvdcss 0.0.1 */
if( dlsym( p_libdvdcss, "dvdcss_crack" ) != NULL )
{
intf_ErrMsg( "dvd warning: libdvdcss.so.0 has deprecated symbol "
"dvdcss_crack(), please upgrade" );
dlclose( p_libdvdcss );
p_libdvdcss = NULL;
}
else
{
dvdcss_open = dlsym( p_libdvdcss, "dvdcss_open" );
dvdcss_close = dlsym( p_libdvdcss, "dvdcss_close" );
dvdcss_title = dlsym( p_libdvdcss, "dvdcss_title" );
dvdcss_seek = dlsym( p_libdvdcss, "dvdcss_seek" );
dvdcss_read = dlsym( p_libdvdcss, "dvdcss_read" );
dvdcss_readv = dlsym( p_libdvdcss, "dvdcss_readv" );
dvdcss_error = dlsym( p_libdvdcss, "dvdcss_error" );
if( dvdcss_open == NULL || dvdcss_close == NULL
|| dvdcss_title == NULL || dvdcss_seek == NULL
|| dvdcss_read == NULL || dvdcss_readv == NULL
|| dvdcss_error == NULL )
{
intf_ErrMsg( "dvd warning: missing symbols in libdvdcss.so.0, "
"please upgrade libdvdcss or vlc" );
dlclose( p_libdvdcss );
p_libdvdcss = NULL;
}
}
}
/* If libdvdcss was not found or was not valid, use the dummy
* replacement functions. */
if( p_libdvdcss == NULL )
{
intf_ErrMsg( "dvd warning: no valid libdvdcss found, "
"I will only play unencrypted DVDs" );
intf_ErrMsg( "dvd warning: get libdvdcss at "
"http://www.videolan.org/libdvdcss/" );
dvdcss_open = dummy_dvdcss_open;
dvdcss_close = dummy_dvdcss_close;
dvdcss_title = dummy_dvdcss_title;
dvdcss_seek = dummy_dvdcss_seek;
dvdcss_read = dummy_dvdcss_read;
dvdcss_readv = dummy_dvdcss_readv;
dvdcss_error = dummy_dvdcss_error;
}
}
/*****************************************************************************
* UnprobeLibDVDCSS: free resources allocated by ProbeLibDVDCSS, if any.
*****************************************************************************/
static void UnprobeLibDVDCSS( void )
{
if( p_libdvdcss != NULL )
{
dlclose( p_libdvdcss );
p_libdvdcss = NULL;
}
}
#endif
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* input_dvdread.h: thread structure of the DVD plugin * input_dvdread.h: thread structure of the DVD plugin
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: input_dvdread.h,v 1.3 2001/12/29 22:22:01 massiot Exp $ * $Id: input_dvdread.h,v 1.4 2002/01/23 03:15:31 stef Exp $
* *
* Author: Stphane Borel <stef@via.ecp.fr> * Author: Stphane Borel <stef@via.ecp.fr>
* *
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include "dvd_udf.h" #include "dvd_udf.h"
#include "nav_read.h" #include "nav_read.h"
#include "nav_print.h" #include "nav_print.h"
#include "videolan/dvdread.h"
/* Logical block size for DVD-VIDEO */ /* Logical block size for DVD-VIDEO */
#define LB2OFF(x) ((off_t)(x) * (off_t)(DVD_VIDEO_LB_LEN)) #define LB2OFF(x) ((off_t)(x) * (off_t)(DVD_VIDEO_LB_LEN))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment