00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <fcntl.h>
00025 #include <unistd.h>
00026
00027 #include "config.h"
00028 #include "dvdread/dvd_reader.h"
00029 #include "dvd_input.h"
00030 #include "mythiowrapper.h"
00031
00032
00033
00034 dvd_input_t (*dvdinput_open) (const char *);
00035 int (*dvdinput_close) (dvd_input_t);
00036 int (*dvdinput_seek) (dvd_input_t, int);
00037 int (*dvdinput_title) (dvd_input_t, int);
00038 int (*dvdinput_read) (dvd_input_t, void *, int, int);
00039 char * (*dvdinput_error) (dvd_input_t);
00040
00041 #ifdef HAVE_DVDCSS_DVDCSS_H
00042
00043 #include <dvdcss/dvdcss.h>
00044 #define DVDcss_open(a) dvdcss_open((char*)(a))
00045 #define DVDcss_close dvdcss_close
00046 #define DVDcss_seek dvdcss_seek
00047 #define DVDcss_title dvdcss_title
00048 #define DVDcss_read dvdcss_read
00049 #define DVDcss_error dvdcss_error
00050 #else
00051
00052
00053 #if HAVE_DLFCN_H
00054 #include <dlfcn.h>
00055 #else
00056
00057 #include "compat.h"
00058 #endif
00059
00060 #ifdef __APPLE__
00061 #include <CoreFoundation/CFBundle.h>
00062 #endif
00063
00064 typedef struct dvdcss_s *dvdcss_handle;
00065 static dvdcss_handle (*DVDcss_open) (const char *);
00066 static int (*DVDcss_close) (dvdcss_handle);
00067 static int (*DVDcss_seek) (dvdcss_handle, int, int);
00068 static int (*DVDcss_title) (dvdcss_handle, int);
00069 static int (*DVDcss_read) (dvdcss_handle, void *, int, int);
00070 static char * (*DVDcss_error) (dvdcss_handle);
00071 #endif
00072
00073
00074 struct dvd_input_s {
00075
00076 dvdcss_handle dvdcss;
00077
00078
00079 int fd;
00080 };
00081
00082
00086 static dvd_input_t css_open(const char *target)
00087 {
00088 dvd_input_t dev;
00089
00090
00091 dev = (dvd_input_t) malloc(sizeof(*dev));
00092 if(dev == NULL) {
00093 fprintf(stderr, "libdvdread: Could not allocate memory.\n");
00094 return NULL;
00095 }
00096
00097
00098 dev->dvdcss = DVDcss_open(target);
00099 if(dev->dvdcss == 0) {
00100 fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target);
00101 free(dev);
00102 return NULL;
00103 }
00104
00105 return dev;
00106 }
00107
00111 static char *css_error(dvd_input_t dev)
00112 {
00113 return DVDcss_error(dev->dvdcss);
00114 }
00115
00119 static int css_seek(dvd_input_t dev, int blocks)
00120 {
00121
00122 return DVDcss_seek(dev->dvdcss, blocks, DVDINPUT_NOFLAGS);
00123 }
00124
00128 static int css_title(dvd_input_t dev, int block)
00129 {
00130 return DVDcss_title(dev->dvdcss, block);
00131 }
00132
00136 static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags)
00137 {
00138 return DVDcss_read(dev->dvdcss, buffer, blocks, flags);
00139 }
00140
00144 static int css_close(dvd_input_t dev)
00145 {
00146 int ret;
00147
00148 ret = DVDcss_close(dev->dvdcss);
00149
00150 if(ret < 0)
00151 return ret;
00152
00153 free(dev);
00154
00155 return 0;
00156 }
00157
00161 static dvd_input_t file_open(const char *target)
00162 {
00163 dvd_input_t dev;
00164
00165
00166 dev = (dvd_input_t) malloc(sizeof(*dev));
00167 if(dev == NULL) {
00168 fprintf(stderr, "libdvdread: Could not allocate memory.\n");
00169 return NULL;
00170 }
00171
00172
00173 #if !defined(WIN32) && !defined(__OS2__)
00174 dev->fd = mythfile_open(target, O_RDONLY);
00175 #else
00176 dev->fd = mythfile_open(target, O_RDONLY | O_BINARY);
00177 #endif
00178 if(dev->fd < 0) {
00179 perror("libdvdread: Could not open input");
00180 free(dev);
00181 return NULL;
00182 }
00183
00184 return dev;
00185 }
00186
00190 static char *file_error(dvd_input_t dev)
00191 {
00192
00193 return (char *)"unknown error";
00194 }
00195
00199 static int file_seek(dvd_input_t dev, int blocks)
00200 {
00201 off_t pos;
00202
00203 pos = mythfile_seek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET);
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 = mythfile_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 mythfile_seek(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 = mythfile_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(const char *path)
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 #ifdef __APPLE__
00292 #define CSS_LIB "libdvdcss.2.dylib"
00293 #elif defined(WIN32)
00294 #define CSS_LIB "libdvdcss.dll"
00295 #elif defined(__OS2__)
00296 #define CSS_LIB "dvdcss.dll"
00297 #else
00298 #define CSS_LIB "libdvdcss.so.2"
00299 #endif
00300 dvdcss_library = dlopen(CSS_LIB, RTLD_LAZY);
00301
00302 #ifdef __APPLE__
00303 if (!dvdcss_library)
00304 {
00305 fprintf(stderr, "libdvdread: dlopen(%s) failed.\n", CSS_LIB);
00306 CFURLRef appUrlRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
00307 CFStringRef macPath = CFURLCopyFileSystemPath(appUrlRef,
00308 kCFURLPOSIXPathStyle);
00309 static char *paths[] = {
00310 "%s/Contents/Frameworks/%s",
00311 "%s/Contents/PlugIns/%s",
00312 "%s/Contents/Plugins/%s",
00313 NULL
00314 };
00315 char path[FILENAME_MAX];
00316 for (int i = 0; paths[i] != NULL && dvdcss_library == NULL; i++)
00317 {
00318 snprintf(path, FILENAME_MAX-1, paths[i],
00319 CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding()),
00320 CSS_LIB);
00321 fprintf(stderr, "Trying %s\n", path);
00322 dvdcss_library = dlopen(path, RTLD_LAZY);
00323 }
00324 CFRelease(appUrlRef);
00325 CFRelease(macPath);
00326 }
00327 #endif
00328
00329 if(dvdcss_library != NULL) {
00330 #if defined(__OpenBSD__) && !defined(__ELF__) || defined(__OS2__)
00331 #define U_S "_"
00332 #else
00333 #define U_S
00334 #endif
00335 DVDcss_open = (dvdcss_handle (*)(const char*))
00336 dlsym(dvdcss_library, U_S "dvdcss_open");
00337 DVDcss_close = (int (*)(dvdcss_handle))
00338 dlsym(dvdcss_library, U_S "dvdcss_close");
00339 DVDcss_title = (int (*)(dvdcss_handle, int))
00340 dlsym(dvdcss_library, U_S "dvdcss_title");
00341 DVDcss_seek = (int (*)(dvdcss_handle, int, int))
00342 dlsym(dvdcss_library, U_S "dvdcss_seek");
00343 DVDcss_read = (int (*)(dvdcss_handle, void*, int, int))
00344 dlsym(dvdcss_library, U_S "dvdcss_read");
00345 DVDcss_error = (char* (*)(dvdcss_handle))
00346 dlsym(dvdcss_library, U_S "dvdcss_error");
00347
00348 dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2");
00349
00350 if(dlsym(dvdcss_library, U_S "dvdcss_crack")) {
00351 fprintf(stderr,
00352 "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n"
00353 "libdvdread: You should get the latest version from "
00354 "http://www.videolan.org/\n" );
00355 dlclose(dvdcss_library);
00356 dvdcss_library = NULL;
00357 } else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek
00358 || !DVDcss_read || !DVDcss_error || !dvdcss_version) {
00359 fprintf(stderr, "libdvdread: Missing symbols in %s, "
00360 "this shouldn't happen !\n", CSS_LIB);
00361 dlclose(dvdcss_library);
00362 }
00363 }
00364 #endif
00365
00366
00367 if(strncmp(path, "myth://", 7) && dvdcss_library != NULL) {
00368
00369
00370
00371
00372
00373
00374 fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n",
00375 dvdcss_version ? *dvdcss_version : "");
00376
00377
00378 dvdinput_open = css_open;
00379 dvdinput_close = css_close;
00380 dvdinput_seek = css_seek;
00381 dvdinput_title = css_title;
00382 dvdinput_read = css_read;
00383 dvdinput_error = css_error;
00384 return 1;
00385
00386 } else {
00387 fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n");
00388
00389
00390 dvdinput_open = file_open;
00391 dvdinput_close = file_close;
00392 dvdinput_seek = file_seek;
00393 dvdinput_title = file_title;
00394 dvdinput_read = file_read;
00395 dvdinput_error = file_error;
00396 return 0;
00397 }
00398 }