Mercurial > libdvdread4.hg
annotate dvd_input.c @ 64:70c34d162e6e src
Replaces the hard-coded values
The parental management structure has ratings levels. The size
of the bit mask is constant but magic values were being used
instead of named constants. This commit changes them to named
constants. This is based on a patch submitted by Frederic Marchal,
fmarchal at perso dot be. Thanks for this tidy cleanup.
author | erik |
---|---|
date | Sun, 30 Jan 2011 23:44:13 +0000 |
parents | ce7056d60f01 |
children | dbfcd120bf24 |
rev | line source |
---|---|
3 | 1 /* |
2 * Copyright (C) 2002 Samuel Hocevar <sam@zoy.org>, | |
22 | 3 * HÃ¥kan Hjort <d95hjort@dtek.chalmers.se> |
3 | 4 * |
21
4aa618ae094f
Use consistent license headers everywhere: Fix FSF address and boilerplate.
diego
parents:
20
diff
changeset
|
5 * This file is part of libdvdread. |
4aa618ae094f
Use consistent license headers everywhere: Fix FSF address and boilerplate.
diego
parents:
20
diff
changeset
|
6 * |
4aa618ae094f
Use consistent license headers everywhere: Fix FSF address and boilerplate.
diego
parents:
20
diff
changeset
|
7 * libdvdread is free software; you can redistribute it and/or modify |
3 | 8 * it under the terms of the GNU General Public License as published by |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
20 | 11 * |
21
4aa618ae094f
Use consistent license headers everywhere: Fix FSF address and boilerplate.
diego
parents:
20
diff
changeset
|
12 * libdvdread is distributed in the hope that it will be useful, |
3 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
21
4aa618ae094f
Use consistent license headers everywhere: Fix FSF address and boilerplate.
diego
parents:
20
diff
changeset
|
17 * You should have received a copy of the GNU General Public License along |
4aa618ae094f
Use consistent license headers everywhere: Fix FSF address and boilerplate.
diego
parents:
20
diff
changeset
|
18 * with libdvdread; if not, write to the Free Software Foundation, Inc., |
4aa618ae094f
Use consistent license headers everywhere: Fix FSF address and boilerplate.
diego
parents:
20
diff
changeset
|
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
3 | 20 */ |
21 | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <fcntl.h> | |
25 #include <unistd.h> | |
26 | |
39
caef08851d58
Add #include for config.h. Several preprocessor definitions were used without
diego
parents:
38
diff
changeset
|
27 #include "config.h" |
33
c743d79f187b
Move installed headers into dvdread directory to make them easier to
reimar
parents:
30
diff
changeset
|
28 #include "dvdread/dvd_reader.h" |
3 | 29 #include "dvd_input.h" |
30 | |
31 | |
32 /* The function pointers that is the exported interface of this file. */ | |
33 dvd_input_t (*dvdinput_open) (const char *); | |
34 int (*dvdinput_close) (dvd_input_t); | |
35 int (*dvdinput_seek) (dvd_input_t, int); | |
20 | 36 int (*dvdinput_title) (dvd_input_t, int); |
3 | 37 int (*dvdinput_read) (dvd_input_t, void *, int, int); |
38 char * (*dvdinput_error) (dvd_input_t); | |
39 | |
40 #ifdef HAVE_DVDCSS_DVDCSS_H | |
41 /* linking to libdvdcss */ | |
42 #include <dvdcss/dvdcss.h> | |
43 #define DVDcss_open(a) dvdcss_open((char*)(a)) | |
44 #define DVDcss_close dvdcss_close | |
45 #define DVDcss_seek dvdcss_seek | |
46 #define DVDcss_title dvdcss_title | |
47 #define DVDcss_read dvdcss_read | |
48 #define DVDcss_error dvdcss_error | |
49 #else | |
50 | |
51 /* dlopening libdvdcss */ | |
52 #ifdef HAVE_DLFCN_H | |
53 #include <dlfcn.h> | |
54 #else | |
55 /* Only needed on MINGW at the moment */ | |
56 #include "../../msvc/contrib/dlfcn.c" | |
57 #endif | |
58 | |
59 typedef struct dvdcss_s *dvdcss_handle; | |
60 static dvdcss_handle (*DVDcss_open) (const char *); | |
61 static int (*DVDcss_close) (dvdcss_handle); | |
62 static int (*DVDcss_seek) (dvdcss_handle, int, int); | |
20 | 63 static int (*DVDcss_title) (dvdcss_handle, int); |
3 | 64 static int (*DVDcss_read) (dvdcss_handle, void *, int, int); |
65 static char * (*DVDcss_error) (dvdcss_handle); | |
66 #endif | |
67 | |
68 /* The DVDinput handle, add stuff here for new input methods. */ | |
69 struct dvd_input_s { | |
70 /* libdvdcss handle */ | |
71 dvdcss_handle dvdcss; | |
20 | 72 |
3 | 73 /* dummy file input */ |
74 int fd; | |
75 }; | |
76 | |
77 | |
78 /** | |
79 * initialize and open a DVD device or file. | |
80 */ | |
81 static dvd_input_t css_open(const char *target) | |
82 { | |
83 dvd_input_t dev; | |
20 | 84 |
3 | 85 /* Allocate the handle structure */ |
86 dev = (dvd_input_t) malloc(sizeof(*dev)); | |
87 if(dev == NULL) { | |
88 fprintf(stderr, "libdvdread: Could not allocate memory.\n"); | |
89 return NULL; | |
90 } | |
20 | 91 |
3 | 92 /* Really open it with libdvdcss */ |
93 dev->dvdcss = DVDcss_open(target); | |
94 if(dev->dvdcss == 0) { | |
95 fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target); | |
96 free(dev); | |
97 return NULL; | |
98 } | |
20 | 99 |
3 | 100 return dev; |
101 } | |
102 | |
103 /** | |
104 * return the last error message | |
105 */ | |
106 static char *css_error(dvd_input_t dev) | |
107 { | |
108 return DVDcss_error(dev->dvdcss); | |
109 } | |
110 | |
111 /** | |
112 * seek into the device. | |
113 */ | |
114 static int css_seek(dvd_input_t dev, int blocks) | |
115 { | |
116 /* DVDINPUT_NOFLAGS should match the DVDCSS_NOFLAGS value. */ | |
117 return DVDcss_seek(dev->dvdcss, blocks, DVDINPUT_NOFLAGS); | |
118 } | |
119 | |
120 /** | |
18 | 121 * set the block for the beginning of a new title (key). |
3 | 122 */ |
123 static int css_title(dvd_input_t dev, int block) | |
124 { | |
125 return DVDcss_title(dev->dvdcss, block); | |
126 } | |
127 | |
128 /** | |
129 * read data from the device. | |
130 */ | |
131 static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags) | |
132 { | |
133 return DVDcss_read(dev->dvdcss, buffer, blocks, flags); | |
134 } | |
135 | |
136 /** | |
137 * close the DVD device and clean up the library. | |
138 */ | |
139 static int css_close(dvd_input_t dev) | |
140 { | |
141 int ret; | |
142 | |
143 ret = DVDcss_close(dev->dvdcss); | |
144 | |
145 if(ret < 0) | |
146 return ret; | |
147 | |
148 free(dev); | |
149 | |
150 return 0; | |
151 } | |
152 | |
153 /** | |
154 * initialize and open a DVD device or file. | |
155 */ | |
156 static dvd_input_t file_open(const char *target) | |
157 { | |
158 dvd_input_t dev; | |
20 | 159 |
3 | 160 /* Allocate the library structure */ |
161 dev = (dvd_input_t) malloc(sizeof(*dev)); | |
162 if(dev == NULL) { | |
163 fprintf(stderr, "libdvdread: Could not allocate memory.\n"); | |
164 return NULL; | |
165 } | |
20 | 166 |
3 | 167 /* Open the device */ |
40
ce7056d60f01
in OS/2 the device must be opened in binary mode; patch by KO Myung-Hun - komh chollian net
nicodvb
parents:
39
diff
changeset
|
168 #if !defined(WIN32) && !defined(__OS2__) |
3 | 169 dev->fd = open(target, O_RDONLY); |
170 #else | |
171 dev->fd = open(target, O_RDONLY | O_BINARY); | |
172 #endif | |
173 if(dev->fd < 0) { | |
174 perror("libdvdread: Could not open input"); | |
175 free(dev); | |
176 return NULL; | |
177 } | |
20 | 178 |
3 | 179 return dev; |
180 } | |
181 | |
182 /** | |
183 * return the last error message | |
184 */ | |
185 static char *file_error(dvd_input_t dev) | |
186 { | |
187 /* use strerror(errno)? */ | |
188 return (char *)"unknown error"; | |
189 } | |
190 | |
191 /** | |
192 * seek into the device. | |
193 */ | |
194 static int file_seek(dvd_input_t dev, int blocks) | |
195 { | |
196 off_t pos; | |
197 | |
198 pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); | |
199 if(pos < 0) { | |
27
98951f8ec89c
cosmetics: Sync indentation and similar changes from libdvdread 0.9.5.
diego
parents:
26
diff
changeset
|
200 return pos; |
3 | 201 } |
202 /* assert pos % DVD_VIDEO_LB_LEN == 0 */ | |
203 return (int) (pos / DVD_VIDEO_LB_LEN); | |
204 } | |
205 | |
206 /** | |
18 | 207 * set the block for the beginning of a new title (key). |
3 | 208 */ |
209 static int file_title(dvd_input_t dev, int block) | |
210 { | |
211 return -1; | |
212 } | |
213 | |
214 /** | |
215 * read data from the device. | |
216 */ | |
217 static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags) | |
218 { | |
219 size_t len; | |
220 ssize_t ret; | |
20 | 221 |
3 | 222 len = (size_t)blocks * DVD_VIDEO_LB_LEN; |
20 | 223 |
3 | 224 while(len > 0) { |
20 | 225 |
3 | 226 ret = read(dev->fd, buffer, len); |
20 | 227 |
3 | 228 if(ret < 0) { |
229 /* One of the reads failed, too bad. We won't even bother | |
18 | 230 * returning the reads that went OK, and as in the POSIX spec |
231 * the file position is left unspecified after a failure. */ | |
3 | 232 return ret; |
233 } | |
20 | 234 |
3 | 235 if(ret == 0) { |
18 | 236 /* Nothing more to read. Return all of the whole blocks, if any. |
237 * Adjust the file position back to the previous block boundary. */ | |
3 | 238 size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len; |
239 off_t over_read = -(bytes % DVD_VIDEO_LB_LEN); | |
240 /*off_t pos =*/ lseek(dev->fd, over_read, SEEK_CUR); | |
241 /* should have pos % 2048 == 0 */ | |
242 return (int) (bytes / DVD_VIDEO_LB_LEN); | |
243 } | |
20 | 244 |
3 | 245 len -= ret; |
246 } | |
247 | |
248 return blocks; | |
249 } | |
250 | |
251 /** | |
252 * close the DVD device and clean up. | |
253 */ | |
254 static int file_close(dvd_input_t dev) | |
255 { | |
256 int ret; | |
257 | |
258 ret = close(dev->fd); | |
259 | |
260 if(ret < 0) | |
261 return ret; | |
262 | |
263 free(dev); | |
264 | |
265 return 0; | |
266 } | |
267 | |
268 | |
269 /** | |
270 * Setup read functions with either libdvdcss or minimal DVD access. | |
271 */ | |
272 int dvdinput_setup(void) | |
273 { | |
274 void *dvdcss_library = NULL; | |
275 char **dvdcss_version = NULL; | |
276 | |
277 #ifdef HAVE_DVDCSS_DVDCSS_H | |
278 /* linking to libdvdcss */ | |
279 dvdcss_library = &dvdcss_library; /* Give it some value != NULL */ | |
280 /* the DVDcss_* functions have been #defined at the top */ | |
281 dvdcss_version = &dvdcss_interface_2; | |
282 | |
283 #else | |
284 /* dlopening libdvdcss */ | |
285 | |
286 #ifdef __APPLE__ | |
287 #define CSS_LIB "libdvdcss.2.dylib" | |
288 #elif defined(WIN32) | |
289 #define CSS_LIB "libdvdcss.dll" | |
30 | 290 #elif defined(__OS2__) |
291 #define CSS_LIB "dvdcss.dll" | |
3 | 292 #else |
293 #define CSS_LIB "libdvdcss.so.2" | |
294 #endif | |
295 dvdcss_library = dlopen(CSS_LIB, RTLD_LAZY); | |
296 | |
297 if(dvdcss_library != NULL) { | |
30 | 298 #if defined(__OpenBSD__) && !defined(__ELF__) || defined(__OS2__) |
3 | 299 #define U_S "_" |
300 #else | |
301 #define U_S | |
302 #endif | |
303 DVDcss_open = (dvdcss_handle (*)(const char*)) | |
304 dlsym(dvdcss_library, U_S "dvdcss_open"); | |
305 DVDcss_close = (int (*)(dvdcss_handle)) | |
306 dlsym(dvdcss_library, U_S "dvdcss_close"); | |
307 DVDcss_title = (int (*)(dvdcss_handle, int)) | |
308 dlsym(dvdcss_library, U_S "dvdcss_title"); | |
309 DVDcss_seek = (int (*)(dvdcss_handle, int, int)) | |
310 dlsym(dvdcss_library, U_S "dvdcss_seek"); | |
311 DVDcss_read = (int (*)(dvdcss_handle, void*, int, int)) | |
312 dlsym(dvdcss_library, U_S "dvdcss_read"); | |
313 DVDcss_error = (char* (*)(dvdcss_handle)) | |
314 dlsym(dvdcss_library, U_S "dvdcss_error"); | |
20 | 315 |
3 | 316 dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2"); |
317 | |
318 if(dlsym(dvdcss_library, U_S "dvdcss_crack")) { | |
20 | 319 fprintf(stderr, |
26 | 320 "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n" |
321 "libdvdread: You should get the latest version from " | |
322 "http://www.videolan.org/\n" ); | |
3 | 323 dlclose(dvdcss_library); |
324 dvdcss_library = NULL; | |
325 } else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek | |
26 | 326 || !DVDcss_read || !DVDcss_error || !dvdcss_version) { |
3 | 327 fprintf(stderr, "libdvdread: Missing symbols in %s, " |
26 | 328 "this shouldn't happen !\n", CSS_LIB); |
3 | 329 dlclose(dvdcss_library); |
330 } | |
331 } | |
332 #endif /* HAVE_DVDCSS_DVDCSS_H */ | |
20 | 333 |
3 | 334 if(dvdcss_library != NULL) { |
335 /* | |
336 char *psz_method = getenv( "DVDCSS_METHOD" ); | |
337 char *psz_verbose = getenv( "DVDCSS_VERBOSE" ); | |
338 fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method); | |
339 fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose); | |
340 */ | |
341 fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n", | |
26 | 342 dvdcss_version ? *dvdcss_version : ""); |
20 | 343 |
3 | 344 /* libdvdcss wrapper functions */ |
345 dvdinput_open = css_open; | |
346 dvdinput_close = css_close; | |
347 dvdinput_seek = css_seek; | |
348 dvdinput_title = css_title; | |
349 dvdinput_read = css_read; | |
350 dvdinput_error = css_error; | |
351 return 1; | |
20 | 352 |
3 | 353 } else { |
354 fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"); | |
355 | |
356 /* libdvdcss replacement functions */ | |
357 dvdinput_open = file_open; | |
358 dvdinput_close = file_close; | |
359 dvdinput_seek = file_seek; | |
360 dvdinput_title = file_title; | |
361 dvdinput_read = file_read; | |
362 dvdinput_error = file_error; | |
363 return 0; | |
364 } | |
365 } |