summaryrefslogtreecommitdiff
path: root/misc/cdda_server.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/cdda_server.c')
-rw-r--r--misc/cdda_server.c201
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;
}