diff options
Diffstat (limited to 'misc/cdda_server.c')
| -rw-r--r-- | misc/cdda_server.c | 201 | 
1 files changed, 186 insertions, 15 deletions
| diff --git a/misc/cdda_server.c b/misc/cdda_server.c index 3ce9c126f..96dc57842 100644 --- a/misc/cdda_server.c +++ b/misc/cdda_server.c @@ -1,11 +1,12 @@ -/* cdda_server.c +/* CDDA / DVD server   *   * This is a TCP server that can be used with xine's cdda input plugin to - * play audio cds over the network. + * play audio CDs over the network. It also supports playing DVDs with a + * patched version of libdvdcss.   *   * quick howto:   * - compile it: - *   gcc -o cdda_server cdda_server.c + *   gcc -o cdda_server cdda_server.c -ldl   *   * - start the server:   *   ./cdda_server /dev/cdrom 3000 @@ -18,6 +19,8 @@   *   * 6 May 2003 - Miguel Freitas   * This feature was sponsored by 1Control + * + * note: see also libdvdcss-1.2.6-network.patch   */  #include <stdio.h> @@ -37,19 +40,32 @@  #include <netinet/in.h>  #include <arpa/inet.h>  #include <netdb.h> +#include <dlfcn.h>  #define QLEN 5    /* maximum connection queue length */  #define _BUFSIZ 300 -static int            msock; -static int            cdda_fd; -static char          *cdrom_device; -  /* CD-relevant defines and data structures */  #define CD_SECONDS_PER_MINUTE   60  #define CD_FRAMES_PER_SECOND    75  #define CD_RAW_FRAME_SIZE       2352  #define CD_LEADOUT_TRACK        0xAA +#define DVD_BLOCK_SIZE          2048 + +/* functions from external DVD lib */ +typedef struct dvd_s *dvd_handle; +static dvd_handle    (*dvd_open)  (const char *); +static int           (*dvd_close) (dvd_handle); +static int           (*dvd_seek)  (dvd_handle, int, int); +static int           (*dvd_title) (dvd_handle, int); +static int           (*dvd_read)  (dvd_handle, void *, int, int); +static char *        (*dvd_error) (dvd_handle); + +static int            dvd_support; +static int            msock; +static int            cdda_fd; +static dvd_handle     dvd; +static char          *cdrom_device;  #if defined (__linux__) @@ -307,15 +323,87 @@ int sock_string_write(int socket, char *msg, ...) {  } +/** + * Setup dvd read functions + */ +int dvdinput_setup(void) +{ +  void *dvdcss_library = NULL; +  char **dvdcss_version = NULL; + +  /* dlopening libdvdcss */ + +#ifndef _MSC_VER +  dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY); +#else +  dvdcss_library = dlopen("libdvdcss.dll", RTLD_LAZY); +#endif + +  if(dvdcss_library != NULL) { +#if defined(__OpenBSD__) && !defined(__ELF__) +#define U_S "_" +#else +#define U_S +#endif +    dvd_open = (dvd_handle (*)(const char*)) +      dlsym(dvdcss_library, U_S "dvdcss_open"); +    dvd_close = (int (*)(dvd_handle)) +      dlsym(dvdcss_library, U_S "dvdcss_close"); +    dvd_title = (int (*)(dvd_handle, int)) +      dlsym(dvdcss_library, U_S "dvdcss_title"); +    dvd_seek = (int (*)(dvd_handle, int, int)) +      dlsym(dvdcss_library, U_S "dvdcss_seek"); +    dvd_read = (int (*)(dvd_handle, void*, int, int)) +      dlsym(dvdcss_library, U_S "dvdcss_read"); +    dvd_error = (char* (*)(dvd_handle)) +      dlsym(dvdcss_library, U_S "dvdcss_error"); + +    dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2"); + +    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 = NULL; +    } else if(!dvd_open  || !dvd_close || !dvd_title || !dvd_seek +	      || !dvd_read || !dvd_error || !dvdcss_version) { +      fprintf(stderr,  "libdvdread: Missing symbols in libdvdcss.so.2, " +	      "this shouldn't happen !\n"); +      dlclose(dvdcss_library); +    } +  } + +  if(dvdcss_library != NULL) { +    printf("Using libdvdcss version %s for DVD access\n", +            *dvdcss_version); + +    return 1; + +  } else { +    printf("No libdvdcss: DVD support unavailable.\n"); + +    return 0; +  } +} + + +#define CMD_CDDA_OPEN       "cdda_open"  #define CMD_CDDA_READ       "cdda_read"  #define CMD_CDDA_TOCHDR     "cdda_tochdr"  #define CMD_CDDA_TOCENTRY   "cdda_tocentry" -#define CMD_CDDA_OPEN       "cdda_open" +#define CMD_DVD_OPEN        "dvd_open" +#define CMD_DVD_ERROR       "dvd_error" +#define CMD_DVD_SEEK        "dvd_seek" +#define CMD_DVD_READ        "dvd_read" +#define CMD_DVD_TITLE       "dvd_title"  static int process_commands( int socket )  {    char     cmd[_BUFSIZ];    int      start_frame, num_frames, i; +  int      blocks, flags;    int      ret, n;    while( sock_has_data(socket) ) @@ -342,6 +430,25 @@ static int process_commands( int socket )        continue;      } +    if( dvd_support && !strncmp(cmd, CMD_DVD_OPEN, strlen(CMD_DVD_OPEN)) ) { + +      if( dvd != NULL ) +        dvd_close(dvd); + +      dvd = dvd_open ( cdrom_device ); +      if( !dvd ) +      { +        printf( "argh ! couldn't open DVD (%s)\n", cdrom_device ); +        if( sock_string_write(socket,"-1 0") < 0 ) +          return -1; +      } +      else { +        if( sock_string_write(socket,"0 0") < 0 ) +          return -1; +      } +      continue; +    } +      if( cdda_fd != -1 ) {        if( !strncmp(cmd, CMD_CDDA_READ, strlen(CMD_CDDA_READ)) ) { @@ -395,14 +502,72 @@ static int process_commands( int socket )          continue;        } -    } else { +    } else if ( dvd != NULL ) { + +      if( !strncmp(cmd, CMD_DVD_ERROR, strlen(CMD_DVD_ERROR)) ) { +        char *errmsg = dvd_error( dvd ); + +        n = strlen(errmsg)+1; +        if( sock_string_write(socket,"0 %d", n) < 0 ) +          return -1; + +        if( sock_data_write(socket,errmsg,n) < 0 ) +          return -1; + +        continue; +      } + +      if( !strncmp(cmd, CMD_DVD_SEEK, strlen(CMD_DVD_SEEK)) ) { + +        sscanf(cmd,"%*s %d %d", &blocks, &flags); +        ret = dvd_seek(dvd, blocks, flags); + +        if( sock_string_write(socket,"%d 0", ret) < 0 ) +          return -1; + +        continue; +      } + +      if( !strncmp(cmd, CMD_DVD_READ, strlen(CMD_DVD_READ)) ) { +        char *buf; -      /* no device open. return error */ -      if( sock_string_write(socket,"-1 0") < 0 ) -        return -1; +        sscanf(cmd,"%*s %d %d", &blocks, &flags); + +        n = blocks * DVD_BLOCK_SIZE; +        buf = malloc( n ); +        if( !buf ) +        { +          printf("fatal error: could not allocate memory\n"); +          exit(1); +        } +        ret = dvd_read(dvd, buf, blocks, flags); +        if( sock_string_write(socket,"%d %d", ret, n) < 0 ) +          return -1; + +        if( sock_data_write(socket,buf,n) < 0 ) +          return -1; + +        free(buf); +        continue; +      } + +      if( !strncmp(cmd, CMD_DVD_TITLE, strlen(CMD_DVD_TITLE)) ) { + +        sscanf(cmd,"%*s %d", &blocks); + +        ret = dvd_title(dvd, blocks); + +        if( sock_string_write(socket,"%d 0", ret) < 0 ) +          return -1; + +        continue; +      }      } +    /* no device open, or unknown command. return error */ +    if( sock_string_write(socket,"-1 0") < 0 ) +      return -1;    }    return 0;  } @@ -457,6 +622,11 @@ static void server_loop()              close(cdda_fd);              cdda_fd = -1;            } + +          if( dvd != NULL ) { +            dvd_close(dvd); +            dvd = NULL; +          }          }      }    } @@ -466,11 +636,11 @@ static void server_loop()  int main( int argc, char *argv[] )  {    unsigned int   port; -  int            ret;    struct sockaddr_in servAddr;    /* Print version number */ -  printf( "CDDA TCP Server\n" ); +  printf( "CDDA / DVD tcp server v0.1\n" ); +  dvd_support = dvdinput_setup();    /* Check for 2 arguments */    if( argc != 3 ) @@ -482,6 +652,7 @@ int main( int argc, char *argv[] )    port = atoi( argv[2] );    cdda_fd = -1; +  dvd = NULL;    cdrom_device = argv[1];    msock = socket(PF_INET, SOCK_STREAM, 0); @@ -508,6 +679,6 @@ int main( int argc, char *argv[] )    close(msock); -  return ret; +  return 0;  } | 
