00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "config.h"
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026
00027 #include "dvd_reader.h"
00028 #include "dvd_input.h"
00029
00030
00031
00032 dvd_input_t (*dvdinput_open) (const char *);
00033 int (*dvdinput_close) (dvd_input_t);
00034 int (*dvdinput_seek) (dvd_input_t, int);
00035 int (*dvdinput_title) (dvd_input_t, int);
00036 int (*dvdinput_read) (dvd_input_t, void *, int, int);
00037 char * (*dvdinput_error) (dvd_input_t);
00038
00039 #ifdef HAVE_DVDCSS_DVDCSS_H
00040
00041 #include <dvdcss/dvdcss.h>
00042 #define DVDcss_open(a) dvdcss_open((char*)(a))
00043 #define DVDcss_close dvdcss_close
00044 #define DVDcss_seek dvdcss_seek
00045 #define DVDcss_title dvdcss_title
00046 #define DVDcss_read dvdcss_read
00047 #define DVDcss_error dvdcss_error
00048 #else
00049
00050
00051 #include "compat.h"
00052 #ifndef USING_MINGW
00053 #include <dlfcn.h>
00054 #endif
00055
00056 typedef struct dvdcss_s *dvdcss_handle;
00057 static dvdcss_handle (*DVDcss_open) (const char *);
00058 static int (*DVDcss_close) (dvdcss_handle);
00059 static int (*DVDcss_seek) (dvdcss_handle, int, int);
00060 static int (*DVDcss_title) (dvdcss_handle, int);
00061 static int (*DVDcss_read) (dvdcss_handle, void *, int, int);
00062 static char * (*DVDcss_error) (dvdcss_handle);
00063 #endif
00064
00065
00066 struct dvd_input_s {
00067
00068 dvdcss_handle dvdcss;
00069
00070
00071 int fd;
00072 };
00073
00074
00078 static dvd_input_t css_open(const char *target)
00079 {
00080 dvd_input_t dev;
00081
00082
00083 dev = (dvd_input_t) malloc(sizeof(*dev));
00084 if(dev == NULL) {
00085 fprintf(stderr, "libdvdread: Could not allocate memory.\n");
00086 return NULL;
00087 }
00088
00089
00090 dev->dvdcss = DVDcss_open(target);
00091 if(dev->dvdcss == 0) {
00092 fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target);
00093 free(dev);
00094 return NULL;
00095 }
00096
00097 return dev;
00098 }
00099
00103 static char *css_error(dvd_input_t dev)
00104 {
00105 return DVDcss_error(dev->dvdcss);
00106 }
00107
00111 static int css_seek(dvd_input_t dev, int blocks)
00112 {
00113
00114 return DVDcss_seek(dev->dvdcss, blocks, DVDINPUT_NOFLAGS);
00115 }
00116
00120 static int css_title(dvd_input_t dev, int block)
00121 {
00122 return DVDcss_title(dev->dvdcss, block);
00123 }
00124
00128 static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags)
00129 {
00130 return DVDcss_read(dev->dvdcss, buffer, blocks, flags);
00131 }
00132
00136 static int css_close(dvd_input_t dev)
00137 {
00138 int ret;
00139
00140 ret = DVDcss_close(dev->dvdcss);
00141
00142 if(ret < 0)
00143 return ret;
00144
00145 free(dev);
00146
00147 return 0;
00148 }
00149
00150
00151
00152
00153
00154
00158 static dvd_input_t file_open(const char *target)
00159 {
00160 dvd_input_t dev;
00161
00162
00163 dev = (dvd_input_t) malloc(sizeof(*dev));
00164 if(dev == NULL) {
00165 fprintf(stderr, "libdvdread: Could not allocate memory.\n");
00166 return NULL;
00167 }
00168
00169
00170 #ifndef WIN32
00171 dev->fd = open(target, O_RDONLY);
00172 #else
00173 dev->fd = open(target, O_RDONLY | O_BINARY);
00174 #endif
00175 if(dev->fd < 0) {
00176 perror("libdvdread: Could not open input");
00177 free(dev);
00178 return NULL;
00179 }
00180
00181 return dev;
00182 }
00183
00187 static char *file_error(dvd_input_t dev)
00188 {
00189
00190 return (char *)"unknown error";
00191 }
00192
00196 static int file_seek(dvd_input_t dev, int blocks)
00197 {
00198
00199 off64_t pos;
00200 pos = lseek64(
00201 dev->fd, (off64_t)blocks * (off64_t)DVD_VIDEO_LB_LEN, SEEK_SET);
00202
00203
00204 if(pos < 0) {
00205 return pos;
00206 }
00207
00208 return (int) (pos / DVD_VIDEO_LB_LEN);
00209 }
00210
00214 static int file_title(dvd_input_t dev, int block)
00215 {
00216 return -1;
00217 }
00218
00222 static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags)
00223 {
00224 size_t len;
00225 ssize_t ret;
00226
00227 len = (size_t)blocks * DVD_VIDEO_LB_LEN;
00228
00229 while(len > 0) {
00230
00231 ret = read(dev->fd, buffer, len);
00232
00233 if(ret < 0) {
00234
00235
00236
00237 return ret;
00238 }
00239
00240 if(ret == 0) {
00241
00242
00243 size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len;
00244 off_t over_read = -(bytes % DVD_VIDEO_LB_LEN);
00245 lseek(dev->fd, over_read, SEEK_CUR);
00246
00247 return (int) (bytes / DVD_VIDEO_LB_LEN);
00248 }
00249
00250 len -= ret;
00251 }
00252
00253 return blocks;
00254 }
00255
00259 static int file_close(dvd_input_t dev)
00260 {
00261 int ret;
00262
00263 ret = close(dev->fd);
00264
00265 if(ret < 0)
00266 return ret;
00267
00268 free(dev);
00269
00270 return 0;
00271 }
00272
00273
00277 int dvdinput_setup(void)
00278 {
00279 void *dvdcss_library = NULL;
00280 char **dvdcss_version = NULL;
00281
00282 #ifdef HAVE_DVDCSS_DVDCSS_H
00283
00284 dvdcss_library = &dvdcss_library;
00285
00286 dvdcss_version = &dvdcss_interface_2;
00287
00288 #else
00289
00290
00291 #if defined(linux) || defined(__FreeBSD__)
00292 dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY);
00293 #endif
00294 #ifdef CONFIG_DARWIN
00295 dvdcss_library = dlopen("libdvdcss.2.dylib", RTLD_LAZY);
00296 #endif
00297 #ifdef _WIN32
00298 dvdcss_library = dlopen("libdvdcss.dll", RTLD_LAZY);
00299 #endif
00300
00301 if(dvdcss_library != NULL) {
00302 #if defined(__OpenBSD__) && !defined(__ELF__)
00303 #define U_S "_"
00304 #else
00305 #define U_S
00306 #endif
00307 DVDcss_open = (dvdcss_handle (*)(const char*))
00308 dlsym(dvdcss_library, U_S "dvdcss_open");
00309 DVDcss_close = (int (*)(dvdcss_handle))
00310 dlsym(dvdcss_library, U_S "dvdcss_close");
00311 DVDcss_title = (int (*)(dvdcss_handle, int))
00312 dlsym(dvdcss_library, U_S "dvdcss_title");
00313 DVDcss_seek = (int (*)(dvdcss_handle, int, int))
00314 dlsym(dvdcss_library, U_S "dvdcss_seek");
00315 DVDcss_read = (int (*)(dvdcss_handle, void*, int, int))
00316 dlsym(dvdcss_library, U_S "dvdcss_read");
00317 DVDcss_error = (char* (*)(dvdcss_handle))
00318 dlsym(dvdcss_library, U_S "dvdcss_error");
00319
00320 dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2");
00321
00322 if(dlsym(dvdcss_library, U_S "dvdcss_crack")) {
00323 fprintf(stderr,
00324 "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n"
00325 "libdvdread: You should get the latest version from "
00326 "http://www.videolan.org/\n" );
00327 dlclose(dvdcss_library);
00328 dvdcss_library = NULL;
00329 } else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek
00330 || !DVDcss_read || !DVDcss_error || !dvdcss_version) {
00331 fprintf(stderr, "libdvdread: Missing symbols in libdvdcss.so.2, "
00332 "this shouldn't happen !\n");
00333 dlclose(dvdcss_library);
00334 }
00335 }
00336 #endif
00337
00338 if(dvdcss_library != NULL) {
00339
00340
00341
00342
00343
00344
00345 fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n",
00346 *dvdcss_version);
00347
00348
00349 dvdinput_open = css_open;
00350 dvdinput_close = css_close;
00351 dvdinput_seek = css_seek;
00352 dvdinput_title = css_title;
00353 dvdinput_read = css_read;
00354 dvdinput_error = css_error;
00355 return 1;
00356
00357 } else {
00358 fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n");
00359
00360
00361 dvdinput_open = file_open;
00362 dvdinput_close = file_close;
00363 dvdinput_seek = file_seek;
00364 dvdinput_title = file_title;
00365 dvdinput_read = file_read;
00366 dvdinput_error = file_error;
00367 return 0;
00368 }
00369 }