Mercurial > sdl-ios-xcode
annotate src/cdrom/openbsd/SDL_syscdrom.c @ 1076:8d3b95ece376
[PATCH] SDL_GetVideoMode() do not find the best video mode
The current GetVideoMode() function stops at the first mode which has any
dimensions smaller than the one asked, and gives the previous in the list.
If I ask 336x224 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200
SDL will give me 640x400, because 640x200 as height smaller than what I
asked.
However the best mode is the smaller which has both dimensions bigger
than the one asked (384x240 in my example).
This patch fixes this, plus it does not rely on a sorted video mode list.
author | Patrice Mandin <patmandin@gmail.com> |
---|---|
date | Sun, 12 Jun 2005 16:12:55 +0000 |
parents | 0f3aa6ab3341 |
children | c9b51268668f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library 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 GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
25
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* Functions for system-level CD-ROM audio control */ | |
29 | |
30 #include <sys/types.h> | |
31 #include <sys/ioctl.h> | |
32 #include <stdlib.h> | |
33 #include <sys/stat.h> | |
34 #include <fcntl.h> | |
35 #include <stdio.h> | |
36 #include <string.h> | |
37 #include <errno.h> | |
38 #include <unistd.h> | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
39 #include <sys/ioctl.h> |
0 | 40 #include <sys/cdio.h> |
41 | |
42 #include "SDL_error.h" | |
43 #include "SDL_cdrom.h" | |
44 #include "SDL_syscdrom.h" | |
45 | |
46 | |
47 /* The maximum number of CD-ROM drives we'll detect */ | |
48 #define MAX_DRIVES 16 | |
49 | |
50 /* A list of available CD-ROM drives */ | |
51 static char *SDL_cdlist[MAX_DRIVES]; | |
52 static dev_t SDL_cdmode[MAX_DRIVES]; | |
53 | |
54 /* The system-dependent CD control functions */ | |
55 static const char *SDL_SYS_CDName(int drive); | |
56 static int SDL_SYS_CDOpen(int drive); | |
57 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); | |
58 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); | |
59 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); | |
60 static int SDL_SYS_CDPause(SDL_CD *cdrom); | |
61 static int SDL_SYS_CDResume(SDL_CD *cdrom); | |
62 static int SDL_SYS_CDStop(SDL_CD *cdrom); | |
63 static int SDL_SYS_CDEject(SDL_CD *cdrom); | |
64 static void SDL_SYS_CDClose(SDL_CD *cdrom); | |
65 | |
66 /* Some ioctl() errno values which occur when the tray is empty */ | |
67 #define ERRNO_TRAYEMPTY(errno) \ | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
68 ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL) || \ |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
69 (errno == ENODEV)) |
0 | 70 |
71 /* Check a drive to see if it is a CD-ROM */ | |
72 static int CheckDrive(char *drive, struct stat *stbuf) | |
73 { | |
74 int is_cd, cdfd; | |
75 struct ioc_read_subchannel info; | |
76 | |
77 /* If it doesn't exist, return -1 */ | |
78 if ( stat(drive, stbuf) < 0 ) { | |
79 return(-1); | |
80 } | |
81 | |
82 /* If it does exist, verify that it's an available CD-ROM */ | |
83 is_cd = 0; | |
84 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { | |
85 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); | |
86 if ( cdfd >= 0 ) { | |
87 info.address_format = CD_MSF_FORMAT; | |
88 info.data_format = CD_CURRENT_POSITION; | |
89 info.data_len = 0; | |
90 info.data = NULL; | |
91 /* Under Linux, EIO occurs when a disk is not present. | |
92 This isn't 100% reliable, so we use the USE_MNTENT | |
93 code above instead. | |
94 */ | |
95 if ( (ioctl(cdfd, CDIOCREADSUBCHANNEL, &info) == 0) || | |
96 ERRNO_TRAYEMPTY(errno) ) { | |
97 is_cd = 1; | |
98 } | |
99 close(cdfd); | |
100 } | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
101 else if (ERRNO_TRAYEMPTY(errno)) |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
102 is_cd = 1; |
0 | 103 } |
104 return(is_cd); | |
105 } | |
106 | |
107 /* Add a CD-ROM drive to our list of valid drives */ | |
108 static void AddDrive(char *drive, struct stat *stbuf) | |
109 { | |
110 int i; | |
111 | |
112 if ( SDL_numcds < MAX_DRIVES ) { | |
113 /* Check to make sure it's not already in our list. | |
114 This can happen when we see a drive via symbolic link. | |
115 */ | |
116 for ( i=0; i<SDL_numcds; ++i ) { | |
117 if ( stbuf->st_rdev == SDL_cdmode[i] ) { | |
118 #ifdef DEBUG_CDROM | |
119 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); | |
120 #endif | |
121 return; | |
122 } | |
123 } | |
124 | |
125 /* Add this drive to our list */ | |
126 i = SDL_numcds; | |
127 SDL_cdlist[i] = (char *)malloc(strlen(drive)+1); | |
128 if ( SDL_cdlist[i] == NULL ) { | |
129 SDL_OutOfMemory(); | |
130 return; | |
131 } | |
132 strcpy(SDL_cdlist[i], drive); | |
133 SDL_cdmode[i] = stbuf->st_rdev; | |
134 ++SDL_numcds; | |
135 #ifdef DEBUG_CDROM | |
136 fprintf(stderr, "Added CD-ROM drive: %s\n", drive); | |
137 #endif | |
138 } | |
139 } | |
140 | |
141 int SDL_SYS_CDInit(void) | |
142 { | |
143 static char *checklist[] = { | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
144 #ifdef __OpenBSD__ |
25
3fbf86244fd2
Date: Wed, 9 May 2001 18:03:20 -0600
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
145 "?0 cd?c", "cdrom", NULL |
1026
0f3aa6ab3341
Select patches included from The NetBSD Package Collection (www.pkgsrc.org)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
146 #elif defined(__NetBSD__) |
0f3aa6ab3341
Select patches included from The NetBSD Package Collection (www.pkgsrc.org)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
147 "?0 cd?d", "?0 cd?c", "cdrom", NULL |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
148 #else |
0 | 149 "?0 cd?c", "?0 acd?c", "cdrom", NULL |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
150 #endif |
0 | 151 }; |
152 char *SDLcdrom; | |
153 int i, j, exists; | |
154 char drive[32]; | |
155 struct stat stbuf; | |
156 | |
157 /* Fill in our driver capabilities */ | |
158 SDL_CDcaps.Name = SDL_SYS_CDName; | |
159 SDL_CDcaps.Open = SDL_SYS_CDOpen; | |
160 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; | |
161 SDL_CDcaps.Status = SDL_SYS_CDStatus; | |
162 SDL_CDcaps.Play = SDL_SYS_CDPlay; | |
163 SDL_CDcaps.Pause = SDL_SYS_CDPause; | |
164 SDL_CDcaps.Resume = SDL_SYS_CDResume; | |
165 SDL_CDcaps.Stop = SDL_SYS_CDStop; | |
166 SDL_CDcaps.Eject = SDL_SYS_CDEject; | |
167 SDL_CDcaps.Close = SDL_SYS_CDClose; | |
168 | |
169 /* Look in the environment for our CD-ROM drive list */ | |
170 SDLcdrom = getenv("SDL_CDROM"); /* ':' separated list of devices */ | |
171 if ( SDLcdrom != NULL ) { | |
172 char *cdpath, *delim; | |
173 cdpath = malloc(strlen(SDLcdrom)+1); | |
174 if ( cdpath != NULL ) { | |
175 strcpy(cdpath, SDLcdrom); | |
176 SDLcdrom = cdpath; | |
177 do { | |
178 delim = strchr(SDLcdrom, ':'); | |
179 if ( delim ) { | |
180 *delim++ = '\0'; | |
181 } | |
182 if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { | |
183 AddDrive(SDLcdrom, &stbuf); | |
184 } | |
185 if ( delim ) { | |
186 SDLcdrom = delim; | |
187 } else { | |
188 SDLcdrom = NULL; | |
189 } | |
190 } while ( SDLcdrom ); | |
191 free(cdpath); | |
192 } | |
193 | |
194 /* If we found our drives, there's nothing left to do */ | |
195 if ( SDL_numcds > 0 ) { | |
196 return(0); | |
197 } | |
198 } | |
199 | |
200 /* Scan the system for CD-ROM drives */ | |
201 for ( i=0; checklist[i]; ++i ) { | |
202 if ( checklist[i][0] == '?' ) { | |
203 char *insert; | |
204 exists = 1; | |
205 for ( j=checklist[i][1]; exists; ++j ) { | |
206 sprintf(drive, "/dev/%s", &checklist[i][3]); | |
207 insert = strchr(drive, '?'); | |
208 if ( insert != NULL ) { | |
209 *insert = j; | |
210 } | |
211 switch (CheckDrive(drive, &stbuf)) { | |
212 /* Drive exists and is a CD-ROM */ | |
213 case 1: | |
214 AddDrive(drive, &stbuf); | |
215 break; | |
216 /* Drive exists, but isn't a CD-ROM */ | |
217 case 0: | |
218 break; | |
219 /* Drive doesn't exist */ | |
220 case -1: | |
221 exists = 0; | |
222 break; | |
223 } | |
224 } | |
225 } else { | |
226 sprintf(drive, "/dev/%s", checklist[i]); | |
227 if ( CheckDrive(drive, &stbuf) > 0 ) { | |
228 AddDrive(drive, &stbuf); | |
229 } | |
230 } | |
231 } | |
232 return(0); | |
233 } | |
234 | |
235 /* General ioctl() CD-ROM command function */ | |
236 static int SDL_SYS_CDioctl(int id, int command, void *arg) | |
237 { | |
238 int retval; | |
239 | |
240 retval = ioctl(id, command, arg); | |
241 if ( retval < 0 ) { | |
242 SDL_SetError("ioctl() error: %s", strerror(errno)); | |
243 } | |
244 return(retval); | |
245 } | |
246 | |
247 static const char *SDL_SYS_CDName(int drive) | |
248 { | |
249 return(SDL_cdlist[drive]); | |
250 } | |
251 | |
252 static int SDL_SYS_CDOpen(int drive) | |
253 { | |
254 return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0)); | |
255 } | |
256 | |
257 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) | |
258 { | |
259 struct ioc_toc_header toc; | |
260 int i, okay; | |
261 struct ioc_read_toc_entry entry; | |
262 struct cd_toc_entry data; | |
263 | |
264 okay = 0; | |
265 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCHEADER, &toc) == 0 ) { | |
266 cdrom->numtracks = toc.ending_track-toc.starting_track+1; | |
267 if ( cdrom->numtracks > SDL_MAX_TRACKS ) { | |
268 cdrom->numtracks = SDL_MAX_TRACKS; | |
269 } | |
270 /* Read all the track TOC entries */ | |
271 for ( i=0; i<=cdrom->numtracks; ++i ) { | |
272 if ( i == cdrom->numtracks ) { | |
273 cdrom->track[i].id = 0xAA; /* CDROM_LEADOUT */ | |
274 } else { | |
275 cdrom->track[i].id = toc.starting_track+i; | |
276 } | |
277 entry.starting_track = cdrom->track[i].id; | |
278 entry.address_format = CD_MSF_FORMAT; | |
279 entry.data_len = sizeof(data); | |
280 entry.data = &data; | |
281 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCENTRYS, | |
282 &entry) < 0 ) { | |
283 break; | |
284 } else { | |
285 cdrom->track[i].type = data.control; | |
286 cdrom->track[i].offset = MSF_TO_FRAMES( | |
287 data.addr.msf.minute, | |
288 data.addr.msf.second, | |
289 data.addr.msf.frame); | |
290 cdrom->track[i].length = 0; | |
291 if ( i > 0 ) { | |
292 cdrom->track[i-1].length = | |
293 cdrom->track[i].offset- | |
294 cdrom->track[i-1].offset; | |
295 } | |
296 } | |
297 } | |
298 if ( i == (cdrom->numtracks+1) ) { | |
299 okay = 1; | |
300 } | |
301 } | |
302 return(okay ? 0 : -1); | |
303 } | |
304 | |
305 /* Get CD-ROM status */ | |
306 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) | |
307 { | |
308 CDstatus status; | |
309 struct ioc_toc_header toc; | |
310 struct ioc_read_subchannel info; | |
311 struct cd_sub_channel_info data; | |
312 | |
313 info.address_format = CD_MSF_FORMAT; | |
314 info.data_format = CD_CURRENT_POSITION; | |
315 info.track = 0; | |
316 info.data_len = sizeof(data); | |
317 info.data = &data; | |
318 if ( ioctl(cdrom->id, CDIOCREADSUBCHANNEL, &info) < 0 ) { | |
319 if ( ERRNO_TRAYEMPTY(errno) ) { | |
320 status = CD_TRAYEMPTY; | |
321 } else { | |
322 status = CD_ERROR; | |
323 } | |
324 } else { | |
325 switch (data.header.audio_status) { | |
326 case CD_AS_AUDIO_INVALID: | |
327 case CD_AS_NO_STATUS: | |
328 /* Try to determine if there's a CD available */ | |
329 if (ioctl(cdrom->id,CDIOREADTOCHEADER,&toc)==0) | |
330 status = CD_STOPPED; | |
331 else | |
332 status = CD_TRAYEMPTY; | |
333 break; | |
334 case CD_AS_PLAY_COMPLETED: | |
335 status = CD_STOPPED; | |
336 break; | |
337 case CD_AS_PLAY_IN_PROGRESS: | |
338 status = CD_PLAYING; | |
339 break; | |
340 case CD_AS_PLAY_PAUSED: | |
341 status = CD_PAUSED; | |
342 break; | |
343 default: | |
344 status = CD_ERROR; | |
345 break; | |
346 } | |
347 } | |
348 if ( position ) { | |
349 if ( status == CD_PLAYING || (status == CD_PAUSED) ) { | |
350 *position = MSF_TO_FRAMES( | |
351 data.what.position.absaddr.msf.minute, | |
352 data.what.position.absaddr.msf.second, | |
353 data.what.position.absaddr.msf.frame); | |
354 } else { | |
355 *position = 0; | |
356 } | |
357 } | |
358 return(status); | |
359 } | |
360 | |
361 /* Start play */ | |
362 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) | |
363 { | |
364 struct ioc_play_msf playtime; | |
365 | |
366 FRAMES_TO_MSF(start, | |
367 &playtime.start_m, &playtime.start_s, &playtime.start_f); | |
368 FRAMES_TO_MSF(start+length, | |
369 &playtime.end_m, &playtime.end_s, &playtime.end_f); | |
370 #ifdef DEBUG_CDROM | |
371 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", | |
372 playtime.start_m, playtime.start_s, playtime.start_f, | |
373 playtime.end_m, playtime.end_s, playtime.end_f); | |
374 #endif | |
375 ioctl(cdrom->id, CDIOCSTART, 0); | |
376 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPLAYMSF, &playtime)); | |
377 } | |
378 | |
379 /* Pause play */ | |
380 static int SDL_SYS_CDPause(SDL_CD *cdrom) | |
381 { | |
382 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPAUSE, 0)); | |
383 } | |
384 | |
385 /* Resume play */ | |
386 static int SDL_SYS_CDResume(SDL_CD *cdrom) | |
387 { | |
388 return(SDL_SYS_CDioctl(cdrom->id, CDIOCRESUME, 0)); | |
389 } | |
390 | |
391 /* Stop play */ | |
392 static int SDL_SYS_CDStop(SDL_CD *cdrom) | |
393 { | |
394 return(SDL_SYS_CDioctl(cdrom->id, CDIOCSTOP, 0)); | |
395 } | |
396 | |
397 /* Eject the CD-ROM */ | |
398 static int SDL_SYS_CDEject(SDL_CD *cdrom) | |
399 { | |
400 return(SDL_SYS_CDioctl(cdrom->id, CDIOCEJECT, 0)); | |
401 } | |
402 | |
403 /* Close the CD-ROM handle */ | |
404 static void SDL_SYS_CDClose(SDL_CD *cdrom) | |
405 { | |
406 close(cdrom->id); | |
407 } | |
408 | |
409 void SDL_SYS_CDQuit(void) | |
410 { | |
411 int i; | |
412 | |
413 if ( SDL_numcds > 0 ) { | |
414 for ( i=0; i<SDL_numcds; ++i ) { | |
415 free(SDL_cdlist[i]); | |
416 } | |
417 SDL_numcds = 0; | |
418 } | |
419 } | |
420 |