Mercurial > libdvdnav.hg
annotate dvdread/dvd_input.c @ 249:5d643668f1e3 src
I added this code myself a long time ago, but now I am quite convinced that
it is wrong: Why would we filter out SPU stream change events that switch
SPUs off? This breaks watching the trailer on the RC2 of "Girl, interrupted",
because you always get unwanted subtitles.
When I added this code, it fixed a problem with the RC2 of "Terminator", but
I cannot reproduce this problem any more. Back then, the menu highlights would
not show up, but they do now. I assume the problem really got fixed with proper
support for forced subtitles in xine, so this crappy workaround here can go
away.
After all, this way it is more symmetric to audio stream change events,
because these are not filtered.
author | mroi |
---|---|
date | Sun, 12 Sep 2004 15:12:43 +0000 |
parents | a27c81078c3c |
children | 6853c398600c |
rev | line source |
---|---|
225 | 1 /* |
2 * Copyright (C) 2002 Samuel Hocevar <sam@zoy.org>, | |
3 * Håkan Hjort <d95hjort@dtek.chalmers.se> | |
4 * | |
5 * This program is free software; you can redistribute it and/or modify | |
6 * it under the terms of the GNU General Public License as published by | |
7 * the Free Software Foundation; either version 2 of the License, or | |
8 * (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU General Public License | |
16 * along with this program; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. | |
18 */ | |
19 | |
20 #include "config.h" | |
21 | |
22 #include <stdio.h> | |
23 #include <stdlib.h> | |
24 #include <fcntl.h> | |
25 #include <unistd.h> | |
26 | |
27 #include "dvd_reader.h" | |
28 #include "dvd_input.h" | |
29 | |
30 | |
31 /* The function pointers that is the exported interface of this file. */ | |
32 dvd_input_t (*dvdinput_open) (const char *); | |
33 int (*dvdinput_close) (dvd_input_t); | |
34 int (*dvdinput_seek) (dvd_input_t, int); | |
35 int (*dvdinput_title) (dvd_input_t, int); | |
36 int (*dvdinput_read) (dvd_input_t, void *, int, int); | |
37 char * (*dvdinput_error) (dvd_input_t); | |
38 | |
39 #ifdef HAVE_DVDCSS_DVDCSS_H | |
40 /* linking to libdvdcss */ | |
41 #include <dvdcss/dvdcss.h> | |
42 #define DVDcss_open(a) dvdcss_open((char*)(a)) | |
43 #define DVDcss_close dvdcss_close | |
44 #define DVDcss_seek dvdcss_seek | |
45 #define DVDcss_title dvdcss_title | |
46 #define DVDcss_read dvdcss_read | |
47 #define DVDcss_error dvdcss_error | |
48 #else | |
49 | |
50 /* dlopening libdvdcss */ | |
238 | 51 #ifdef HAVE_DLFCN_H |
225 | 52 #include <dlfcn.h> |
238 | 53 #else |
54 /* Only needed on MINGW at the moment */ | |
55 #include "../../msvc/contrib/dlfcn.c" | |
56 #endif | |
225 | 57 |
58 typedef struct dvdcss_s *dvdcss_handle; | |
59 static dvdcss_handle (*DVDcss_open) (const char *); | |
60 static int (*DVDcss_close) (dvdcss_handle); | |
61 static int (*DVDcss_seek) (dvdcss_handle, int, int); | |
62 static int (*DVDcss_title) (dvdcss_handle, int); | |
63 static int (*DVDcss_read) (dvdcss_handle, void *, int, int); | |
64 static char * (*DVDcss_error) (dvdcss_handle); | |
65 #endif | |
66 | |
67 /* The DVDinput handle, add stuff here for new input methods. */ | |
68 struct dvd_input_s { | |
69 /* libdvdcss handle */ | |
70 dvdcss_handle dvdcss; | |
71 | |
72 /* dummy file input */ | |
73 int fd; | |
74 }; | |
75 | |
76 | |
77 /** | |
78 * initialize and open a DVD device or file. | |
79 */ | |
80 static dvd_input_t css_open(const char *target) | |
81 { | |
82 dvd_input_t dev; | |
83 | |
84 /* Allocate the handle structure */ | |
85 dev = (dvd_input_t) malloc(sizeof(*dev)); | |
86 if(dev == NULL) { | |
87 fprintf(stderr, "libdvdread: Could not allocate memory.\n"); | |
88 return NULL; | |
89 } | |
90 | |
91 /* Really open it with libdvdcss */ | |
92 dev->dvdcss = DVDcss_open(target); | |
93 if(dev->dvdcss == 0) { | |
94 fprintf(stderr, "libdvdread: Could not open %s with libdvdcss.\n", target); | |
95 free(dev); | |
96 return NULL; | |
97 } | |
98 | |
99 return dev; | |
100 } | |
101 | |
102 /** | |
103 * return the last error message | |
104 */ | |
105 static char *css_error(dvd_input_t dev) | |
106 { | |
107 return DVDcss_error(dev->dvdcss); | |
108 } | |
109 | |
110 /** | |
111 * seek into the device. | |
112 */ | |
113 static int css_seek(dvd_input_t dev, int blocks) | |
114 { | |
115 /* DVDINPUT_NOFLAGS should match the DVDCSS_NOFLAGS value. */ | |
116 return DVDcss_seek(dev->dvdcss, blocks, DVDINPUT_NOFLAGS); | |
117 } | |
118 | |
119 /** | |
120 * set the block for the begining of a new title (key). | |
121 */ | |
122 static int css_title(dvd_input_t dev, int block) | |
123 { | |
124 return DVDcss_title(dev->dvdcss, block); | |
125 } | |
126 | |
127 /** | |
128 * read data from the device. | |
129 */ | |
130 static int css_read(dvd_input_t dev, void *buffer, int blocks, int flags) | |
131 { | |
132 return DVDcss_read(dev->dvdcss, buffer, blocks, flags); | |
133 } | |
134 | |
135 /** | |
136 * close the DVD device and clean up the library. | |
137 */ | |
138 static int css_close(dvd_input_t dev) | |
139 { | |
140 int ret; | |
141 | |
142 ret = DVDcss_close(dev->dvdcss); | |
143 | |
144 if(ret < 0) | |
145 return ret; | |
146 | |
147 free(dev); | |
148 | |
149 return 0; | |
150 } | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 /** | |
158 * initialize and open a DVD device or file. | |
159 */ | |
160 static dvd_input_t file_open(const char *target) | |
161 { | |
162 dvd_input_t dev; | |
163 | |
164 /* Allocate the library structure */ | |
165 dev = (dvd_input_t) malloc(sizeof(*dev)); | |
166 if(dev == NULL) { | |
167 fprintf(stderr, "libdvdread: Could not allocate memory.\n"); | |
168 return NULL; | |
169 } | |
170 | |
171 /* Open the device */ | |
233 | 172 #ifndef WIN32 |
244
a27c81078c3c
removing O_EXCL, since it does not work with DVD images
mroi
parents:
238
diff
changeset
|
173 dev->fd = open(target, O_RDONLY); |
225 | 174 #else |
175 dev->fd = open(target, O_RDONLY | O_BINARY); | |
176 #endif | |
177 if(dev->fd < 0) { | |
178 perror("libdvdread: Could not open input"); | |
179 free(dev); | |
180 return NULL; | |
181 } | |
182 | |
183 return dev; | |
184 } | |
185 | |
186 /** | |
187 * return the last error message | |
188 */ | |
189 static char *file_error(dvd_input_t dev) | |
190 { | |
191 /* use strerror(errno)? */ | |
192 return (char *)"unknown error"; | |
193 } | |
194 | |
195 /** | |
196 * seek into the device. | |
197 */ | |
198 static int file_seek(dvd_input_t dev, int blocks) | |
199 { | |
200 off_t pos; | |
201 | |
202 pos = lseek(dev->fd, (off_t)blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET); | |
203 if(pos < 0) { | |
204 return pos; | |
205 } | |
206 /* assert pos % DVD_VIDEO_LB_LEN == 0 */ | |
207 return (int) (pos / DVD_VIDEO_LB_LEN); | |
208 } | |
209 | |
210 /** | |
211 * set the block for the begining of a new title (key). | |
212 */ | |
213 static int file_title(dvd_input_t dev, int block) | |
214 { | |
215 return -1; | |
216 } | |
217 | |
218 /** | |
219 * read data from the device. | |
220 */ | |
221 static int file_read(dvd_input_t dev, void *buffer, int blocks, int flags) | |
222 { | |
223 size_t len; | |
224 ssize_t ret; | |
225 | |
226 len = (size_t)blocks * DVD_VIDEO_LB_LEN; | |
227 | |
228 while(len > 0) { | |
229 | |
230 ret = read(dev->fd, buffer, len); | |
231 | |
232 if(ret < 0) { | |
233 /* One of the reads failed, too bad. We won't even bother | |
234 * returning the reads that went ok, and as in the posix spec | |
235 * the file postition is left unspecified after a failure. */ | |
236 return ret; | |
237 } | |
238 | |
239 if(ret == 0) { | |
240 /* Nothing more to read. Return the whole blocks, if any, that we got. | |
241 and adjust the file possition back to the previous block boundary. */ | |
242 size_t bytes = (size_t)blocks * DVD_VIDEO_LB_LEN - len; | |
243 off_t over_read = -(bytes % DVD_VIDEO_LB_LEN); | |
244 /*off_t pos =*/ lseek(dev->fd, over_read, SEEK_CUR); | |
245 /* should have pos % 2048 == 0 */ | |
246 return (int) (bytes / DVD_VIDEO_LB_LEN); | |
247 } | |
248 | |
249 len -= ret; | |
250 } | |
251 | |
252 return blocks; | |
253 } | |
254 | |
255 /** | |
256 * close the DVD device and clean up. | |
257 */ | |
258 static int file_close(dvd_input_t dev) | |
259 { | |
260 int ret; | |
261 | |
262 ret = close(dev->fd); | |
263 | |
264 if(ret < 0) | |
265 return ret; | |
266 | |
267 free(dev); | |
268 | |
269 return 0; | |
270 } | |
271 | |
272 | |
273 /** | |
274 * Setup read functions with either libdvdcss or minimal DVD access. | |
275 */ | |
276 int dvdinput_setup(void) | |
277 { | |
278 void *dvdcss_library = NULL; | |
279 char **dvdcss_version = NULL; | |
280 | |
281 #ifdef HAVE_DVDCSS_DVDCSS_H | |
282 /* linking to libdvdcss */ | |
283 dvdcss_library = &dvdcss_library; /* Give it some value != NULL */ | |
284 /* the DVDcss_* functions have been #defined at the top */ | |
285 dvdcss_version = &dvdcss_interface_2; | |
286 | |
287 #else | |
288 /* dlopening libdvdcss */ | |
289 | |
233 | 290 #ifndef WIN32 |
225 | 291 dvdcss_library = dlopen("libdvdcss.so.2", RTLD_LAZY); |
292 #else | |
293 dvdcss_library = dlopen("libdvdcss.dll", RTLD_LAZY); | |
294 #endif | |
295 | |
296 if(dvdcss_library != NULL) { | |
297 #if defined(__OpenBSD__) && !defined(__ELF__) | |
298 #define U_S "_" | |
299 #else | |
300 #define U_S | |
301 #endif | |
302 DVDcss_open = (dvdcss_handle (*)(const char*)) | |
303 dlsym(dvdcss_library, U_S "dvdcss_open"); | |
304 DVDcss_close = (int (*)(dvdcss_handle)) | |
305 dlsym(dvdcss_library, U_S "dvdcss_close"); | |
306 DVDcss_title = (int (*)(dvdcss_handle, int)) | |
307 dlsym(dvdcss_library, U_S "dvdcss_title"); | |
308 DVDcss_seek = (int (*)(dvdcss_handle, int, int)) | |
309 dlsym(dvdcss_library, U_S "dvdcss_seek"); | |
310 DVDcss_read = (int (*)(dvdcss_handle, void*, int, int)) | |
311 dlsym(dvdcss_library, U_S "dvdcss_read"); | |
312 DVDcss_error = (char* (*)(dvdcss_handle)) | |
313 dlsym(dvdcss_library, U_S "dvdcss_error"); | |
314 | |
315 dvdcss_version = (char **)dlsym(dvdcss_library, U_S "dvdcss_interface_2"); | |
316 | |
317 if(dlsym(dvdcss_library, U_S "dvdcss_crack")) { | |
318 fprintf(stderr, | |
319 "libdvdread: Old (pre-0.0.2) version of libdvdcss found.\n" | |
320 "libdvdread: You should get the latest version from " | |
321 "http://www.videolan.org/\n" ); | |
322 dlclose(dvdcss_library); | |
323 dvdcss_library = NULL; | |
324 } else if(!DVDcss_open || !DVDcss_close || !DVDcss_title || !DVDcss_seek | |
325 || !DVDcss_read || !DVDcss_error || !dvdcss_version) { | |
326 fprintf(stderr, "libdvdread: Missing symbols in libdvdcss.so.2, " | |
327 "this shouldn't happen !\n"); | |
328 dlclose(dvdcss_library); | |
329 } | |
330 } | |
331 #endif /* HAVE_DVDCSS_DVDCSS_H */ | |
332 | |
333 if(dvdcss_library != NULL) { | |
334 /* | |
335 char *psz_method = getenv( "DVDCSS_METHOD" ); | |
336 char *psz_verbose = getenv( "DVDCSS_VERBOSE" ); | |
337 fprintf(stderr, "DVDCSS_METHOD %s\n", psz_method); | |
338 fprintf(stderr, "DVDCSS_VERBOSE %s\n", psz_verbose); | |
339 */ | |
340 fprintf(stderr, "libdvdread: Using libdvdcss version %s for DVD access\n", | |
341 *dvdcss_version); | |
342 | |
343 /* libdvdcss wrapper functions */ | |
344 dvdinput_open = css_open; | |
345 dvdinput_close = css_close; | |
346 dvdinput_seek = css_seek; | |
347 dvdinput_title = css_title; | |
348 dvdinput_read = css_read; | |
349 dvdinput_error = css_error; | |
350 return 1; | |
351 | |
352 } else { | |
353 fprintf(stderr, "libdvdread: Encrypted DVD support unavailable.\n"); | |
354 | |
355 /* libdvdcss replacement functions */ | |
356 dvdinput_open = file_open; | |
357 dvdinput_close = file_close; | |
358 dvdinput_seek = file_seek; | |
359 dvdinput_title = file_title; | |
360 dvdinput_read = file_read; | |
361 dvdinput_error = file_error; | |
362 return 0; | |
363 } | |
364 } |