]> git.sesse.net Git - vlc/blobdiff - extras/libdvdcss/libdvdcss.c
*With DVDCSS_METHOD=disc or key, the keys are no longer buffered on start.
[vlc] / extras / libdvdcss / libdvdcss.c
index f698209eab5fc2622055ac2aeded8c764e643d96..638fb8c0b4ddc975c9f9c3c5701f7a0dea087d80 100644 (file)
@@ -2,7 +2,7 @@
  * libdvdcss.c: DVD reading library.
  *****************************************************************************
  * Copyright (C) 1998-2001 VideoLAN
- * $Id: libdvdcss.c,v 1.17 2001/10/14 03:26:20 stef Exp $
+ * $Id: libdvdcss.c,v 1.27 2002/01/14 22:06:57 stef Exp $
  *
  * Authors: Stéphane Borel <stef@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -26,8 +26,6 @@
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include "defs.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,6 +33,8 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include <videolan/vlc.h>
+
 #ifdef HAVE_UNISTD_H
 #   include <unistd.h>
 #endif
@@ -45,9 +45,6 @@
 #   include <sys/uio.h>                                      /* struct iovec */
 #endif
 
-#include "config.h"
-#include "common.h"
-
 #if defined( WIN32 )
 #   include "input_iovec.h"
 #endif
@@ -61,8 +58,6 @@
  *****************************************************************************/
 static int _dvdcss_open  ( dvdcss_handle, char *psz_target );
 static int _dvdcss_close ( dvdcss_handle );
-static int _dvdcss_seek  ( dvdcss_handle, int i_blocks );
-static int _dvdcss_read  ( dvdcss_handle, void *p_buffer, int i_blocks );
 static int _dvdcss_readv ( dvdcss_handle, struct iovec *p_iovec, int i_blocks );
 
 /*****************************************************************************
@@ -75,16 +70,22 @@ static int _win32_dvdcss_aopen  ( char c_drive, dvdcss_handle dvdcss );
 static int _win32_dvdcss_aclose ( int i_fd );
 static int _win32_dvdcss_aseek  ( int i_fd, int i_blocks, int i_method );
 static int _win32_dvdcss_aread  ( int i_fd, void *p_data, int i_blocks );
+#else
+static int _dvdcss_raw_open     ( dvdcss_handle, char *psz_target );
 #endif
 
 /*****************************************************************************
  * dvdcss_open: initialize library, open a DVD device, crack CSS key
  *****************************************************************************/
-extern dvdcss_handle dvdcss_open ( char *psz_target, int i_flags )
+extern dvdcss_handle dvdcss_open ( char *psz_target )
 {
     int i_ret;
 
-    char    psz_method[16] = "dvdcss_method";
+    char *psz_method = getenv( "DVDCSS_METHOD" );
+    char *psz_verbose = getenv( "DVDCSS_VERBOSE" );
+#ifndef WIN32
+    char *psz_raw_device = getenv( "DVDCSS_RAW_DEVICE" );
+#endif
 
     dvdcss_handle dvdcss;
 
@@ -92,37 +93,63 @@ extern dvdcss_handle dvdcss_open ( char *psz_target, int i_flags )
     dvdcss = malloc( sizeof( struct dvdcss_s ) );
     if( dvdcss == NULL )
     {
-        if( ! (i_flags & DVDCSS_INIT_QUIET) )
-        {
-            DVDCSS_ERROR( "could not initialize library" );
-        }
-
         return NULL;
     }
 
-    /* Initialize structure */
+    /* Initialize structure with default values */
     dvdcss->p_titles = NULL;
-    dvdcss->b_debug = i_flags & DVDCSS_INIT_DEBUG;
-    dvdcss->b_errors = !(i_flags & DVDCSS_INIT_QUIET);
     dvdcss->psz_error = "no error";
+    dvdcss->i_method = DVDCSS_METHOD_TITLE;
+    dvdcss->b_debug = 0;
+    dvdcss->b_errors = 1;
 
-
-
-    /* find method from DVDCSS_METHOD environment variable */
-    dvdcss->i_method = DVDCSS_TITLE;
-
-    if( getenv( psz_method ) )
+    /* Find method from DVDCSS_METHOD environment variable */
+    if( psz_method != NULL )
     {
-        if( !strncmp( getenv( psz_method ), "key", 3 ) )
+        if( !strncmp( psz_method, "key", 4 ) )
         {
-            dvdcss->i_method = DVDCSS_KEY;
+            dvdcss->i_method = DVDCSS_METHOD_KEY;
         }
-        else if( !strncmp( getenv( psz_method ), "disc", 4 ) )
+        else if( !strncmp( psz_method, "disc", 5 ) )
         {
-            dvdcss->i_method = DVDCSS_DISC;
+            dvdcss->i_method = DVDCSS_METHOD_DISC;
+        }
+        else if( !strncmp( psz_method, "title", 5 ) )
+        {
+            dvdcss->i_method = DVDCSS_METHOD_TITLE;
+        }
+        else
+        {
+            _dvdcss_error( dvdcss, "unknown decrypt method, please choose "
+                                   "from 'title', 'key' or 'disc'" );
+            free( dvdcss );
+            return NULL;
+        }
+    }
+
+    /* Find verbosity from DVDCSS_VERBOSE environment variable */
+    if( psz_verbose != NULL )
+    {
+        switch( atoi( psz_verbose ) )
+        {
+        case 0:
+            dvdcss->b_errors = 0;
+            break;
+        case 1:
+            break;
+        case 2:
+            dvdcss->b_debug = 1;
+            break;
+        default:
+            _dvdcss_error( dvdcss, "unknown verbose level, please choose "
+                                   "from '0', '1' or '2'" );
+            free( dvdcss );
+            return NULL;
+            break;
         }
     }
 
+    /* Open device */
     i_ret = _dvdcss_open( dvdcss, psz_target );
     if( i_ret < 0 )
     {
@@ -157,6 +184,15 @@ extern dvdcss_handle dvdcss_open ( char *psz_target, int i_flags )
         }
     }
 
+    memset( dvdcss->css.p_unenc_key, 0, KEY_SIZE );
+
+#ifndef WIN32
+    if( psz_raw_device != NULL )
+    {
+        _dvdcss_raw_open( dvdcss, psz_raw_device );
+    }
+#endif
+
     return dvdcss;
 }
 
@@ -174,11 +210,32 @@ extern char * dvdcss_error ( dvdcss_handle dvdcss )
 extern int dvdcss_seek ( dvdcss_handle dvdcss, int i_blocks, int i_flags )
 {
     /* title cracking method is too slow to be used at each seek */
-    if( ( ( i_flags & DVDCSS_SEEK_MPEG ) && ( dvdcss->i_method != DVDCSS_TITLE ) )
-       || ( i_flags & DVDCSS_SEEK_INI ) )
+    if( ( ( i_flags & DVDCSS_SEEK_MPEG )
+             && ( dvdcss->i_method != DVDCSS_METHOD_TITLE ) ) )
+    {
+        int     i_ret;
+
+        /* Crack or decrypt CSS title key for current VTS */
+        i_ret = CSSGetTitleKey( dvdcss, i_blocks );
+
+        if( i_ret < 0 )
+        {
+            _dvdcss_error( dvdcss, "fatal error in vts css key" );
+            return i_ret;
+        }
+        else if( i_ret > 0 )
+        {
+            _dvdcss_error( dvdcss, "decryption unavailable" );
+            return -1;
+        }
+    }
+    else if( i_flags & DVDCSS_SEEK_KEY )
     {
         /* check the title key */
-        dvdcss_title( dvdcss, i_blocks );
+        if( dvdcss_title( dvdcss, i_blocks ) ) 
+        {
+            return -1;
+        }
     }
 
     return _dvdcss_seek( dvdcss, i_blocks );
@@ -428,7 +485,7 @@ static int _dvdcss_open ( dvdcss_handle dvdcss, char *psz_target )
     dvdcss->i_readv_buf_size = 0;
 
 #else
-    dvdcss->i_fd = open( psz_target, 0 );
+    dvdcss->i_fd = dvdcss->i_read_fd = open( psz_target, 0 );
 
     if( dvdcss->i_fd == -1 )
     {
@@ -441,6 +498,25 @@ static int _dvdcss_open ( dvdcss_handle dvdcss, char *psz_target )
     return 0;
 }
 
+#ifndef WIN32
+static int _dvdcss_raw_open ( dvdcss_handle dvdcss, char *psz_target )
+{
+    dvdcss->i_raw_fd = open( psz_target, 0 );
+
+    if( dvdcss->i_raw_fd == -1 )
+    {
+        _dvdcss_error( dvdcss, "failed opening raw device, continuing" );
+        return -1;
+    }
+    else
+    {
+        dvdcss->i_read_fd = dvdcss->i_raw_fd;
+    }
+
+    return 0;
+}
+#endif
+
 static int _dvdcss_close ( dvdcss_handle dvdcss )
 {
 #if defined( WIN32 )
@@ -464,12 +540,18 @@ static int _dvdcss_close ( dvdcss_handle dvdcss )
 #else
     close( dvdcss->i_fd );
 
+    if( dvdcss->i_raw_fd >= 0 )
+    {
+        close( dvdcss->i_raw_fd );
+        dvdcss->i_raw_fd = -1;
+    }
+
 #endif
 
     return 0;
 }
 
-static int _dvdcss_seek ( dvdcss_handle dvdcss, int i_blocks )
+int _dvdcss_seek ( dvdcss_handle dvdcss, int i_blocks )
 {
 #if defined( WIN32 )
     dvdcss->i_seekpos = i_blocks;
@@ -501,11 +583,11 @@ static int _dvdcss_seek ( dvdcss_handle dvdcss, int i_blocks )
         return ( _win32_dvdcss_aseek( dvdcss->i_fd, i_blocks, SEEK_SET ) );
     }
 #else
-    off_t i_read;
+    off_t   i_read;
 
     dvdcss->i_seekpos = i_blocks;
 
-    i_read = lseek( dvdcss->i_fd,
+    i_read = lseek( dvdcss->i_read_fd,
                     (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
 
     return i_read / DVDCSS_BLOCK_SIZE;
@@ -513,7 +595,7 @@ static int _dvdcss_seek ( dvdcss_handle dvdcss, int i_blocks )
 
 }
 
-static int _dvdcss_read ( dvdcss_handle dvdcss, void *p_buffer, int i_blocks )
+int _dvdcss_read ( dvdcss_handle dvdcss, void *p_buffer, int i_blocks )
 {
 #if defined( WIN32 ) 
     if( WIN2K )
@@ -536,7 +618,7 @@ static int _dvdcss_read ( dvdcss_handle dvdcss, void *p_buffer, int i_blocks )
 #else
     int i_bytes;
 
-    i_bytes = read( dvdcss->i_fd, p_buffer,
+    i_bytes = read( dvdcss->i_read_fd, p_buffer,
                     (size_t)i_blocks * DVDCSS_BLOCK_SIZE );
     return i_bytes / DVDCSS_BLOCK_SIZE;
 #endif
@@ -572,7 +654,7 @@ static int _dvdcss_readv ( dvdcss_handle dvdcss, struct iovec *p_iovec,
     return i_read;
 
 #else
-    i_read = readv( dvdcss->i_fd, p_iovec, i_blocks );
+    i_read = readv( dvdcss->i_read_fd, p_iovec, i_blocks );
     return i_read / DVDCSS_BLOCK_SIZE;
 
 #endif