Mercurial > sdl-ios-xcode
annotate src/cdrom/linux/SDL_syscdrom.c @ 4170:092c0bc69155 SDL-1.2
Fixed bug #618
Description From Tim Angus 2008-08-30 12:23:56 (-) [reply]
As we all know SDL 1.2 doesn't handle dead keys well since one key press
potentially equals two (or more) characters. For example, on many layouts,
keying <backquote>,<space> results in <no character>,<backquote><space>. Since
the unicode member of the SDL_keysym struct only has room for one character,
only one can be returned.
On Linux, the first character is returned. On Windows however, unless the exact
number of characters generated by the keypress is 1, nothing is returned. The
following patch addresses this inconsistency.
Updated patch which includes a further fix to the handling of the numpad when
numlock is on. This further fix is courtesy Amanieu d'Antras.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 13 Apr 2009 08:42:09 +0000 |
parents | a1b03ba2fcd0 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
4159 | 3 Copyright (C) 1997-2009 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1062
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1062
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 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 | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1062
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1062
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1062
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1062
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
247
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
1635
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
24 #ifdef SDL_CDROM_LINUX |
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
25 |
0 | 26 /* Functions for system-level CD-ROM audio control */ |
27 | |
1341
d02b552e5304
Configure dynamically generates SDL_config.h
Sam Lantinga <slouken@libsdl.org>
parents:
1338
diff
changeset
|
28 #include <string.h> /* For strerror() */ |
0 | 29 #include <sys/types.h> |
30 #include <sys/stat.h> | |
31 #include <sys/ioctl.h> | |
32 #include <fcntl.h> | |
33 #include <errno.h> | |
34 #include <unistd.h> | |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
35 #ifdef __LINUX__ |
1062
3e637850c02b
Date: Tue, 22 Mar 2005 23:50:20 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
1051
diff
changeset
|
36 #ifdef HAVE_LINUX_VERSION_H |
998
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
37 /* linux 2.6.9 workaround */ |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
38 #include <linux/version.h> |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
39 #if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,9) |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
40 #include <asm/types.h> |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
41 #define __le64 __u64 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
42 #define __le32 __u32 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
43 #define __le16 __u16 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
44 #define __be64 __u64 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
45 #define __be32 __u32 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
46 #define __be16 __u16 |
0e6627072f7a
Date: Wed, 24 Nov 2004 01:25:48 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
47 #endif /* linux 2.6.9 workaround */ |
1062
3e637850c02b
Date: Tue, 22 Mar 2005 23:50:20 +0100
Sam Lantinga <slouken@libsdl.org>
parents:
1051
diff
changeset
|
48 #endif /* HAVE_LINUX_VERSION_H */ |
0 | 49 #include <linux/cdrom.h> |
50 #endif | |
51 #ifdef __SVR4 | |
52 #include <sys/cdio.h> | |
53 #endif | |
54 | |
55 /* Define this to use the alternative getmntent() code */ | |
56 #ifndef __SVR4 | |
57 #define USE_MNTENT | |
58 #endif | |
59 | |
60 #ifdef USE_MNTENT | |
61 #if defined(__USLC__) | |
62 #include <sys/mntent.h> | |
63 #else | |
64 #include <mntent.h> | |
65 #endif | |
66 | |
67 #ifndef _PATH_MNTTAB | |
68 #ifdef MNTTAB | |
69 #define _PATH_MNTTAB MNTTAB | |
70 #else | |
71 #define _PATH_MNTTAB "/etc/fstab" | |
72 #endif | |
73 #endif /* !_PATH_MNTTAB */ | |
74 | |
75 #ifndef _PATH_MOUNTED | |
76 #define _PATH_MOUNTED "/etc/mtab" | |
77 #endif /* !_PATH_MOUNTED */ | |
78 | |
79 #ifndef MNTTYPE_CDROM | |
80 #define MNTTYPE_CDROM "iso9660" | |
81 #endif | |
82 #ifndef MNTTYPE_SUPER | |
83 #define MNTTYPE_SUPER "supermount" | |
84 #endif | |
85 #endif /* USE_MNTENT */ | |
86 | |
87 #include "SDL_cdrom.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
88 #include "../SDL_syscdrom.h" |
0 | 89 |
90 | |
91 /* The maximum number of CD-ROM drives we'll detect */ | |
92 #define MAX_DRIVES 16 | |
93 | |
94 /* A list of available CD-ROM drives */ | |
95 static char *SDL_cdlist[MAX_DRIVES]; | |
96 static dev_t SDL_cdmode[MAX_DRIVES]; | |
97 | |
98 /* The system-dependent CD control functions */ | |
99 static const char *SDL_SYS_CDName(int drive); | |
100 static int SDL_SYS_CDOpen(int drive); | |
101 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); | |
102 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); | |
103 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); | |
104 static int SDL_SYS_CDPause(SDL_CD *cdrom); | |
105 static int SDL_SYS_CDResume(SDL_CD *cdrom); | |
106 static int SDL_SYS_CDStop(SDL_CD *cdrom); | |
107 static int SDL_SYS_CDEject(SDL_CD *cdrom); | |
108 static void SDL_SYS_CDClose(SDL_CD *cdrom); | |
109 | |
110 /* Some ioctl() errno values which occur when the tray is empty */ | |
396
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
111 #ifndef ENOMEDIUM |
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
112 #define ENOMEDIUM ENOENT |
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
113 #endif |
0 | 114 #define ERRNO_TRAYEMPTY(errno) \ |
396
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
115 ((errno == EIO) || (errno == ENOENT) || \ |
11d6eed68dba
Added check for ENOMEDIUM to the Linux CDROM code
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
116 (errno == EINVAL) || (errno == ENOMEDIUM)) |
0 | 117 |
118 /* Check a drive to see if it is a CD-ROM */ | |
119 static int CheckDrive(char *drive, char *mnttype, struct stat *stbuf) | |
120 { | |
121 int is_cd, cdfd; | |
122 struct cdrom_subchnl info; | |
123 | |
124 /* If it doesn't exist, return -1 */ | |
125 if ( stat(drive, stbuf) < 0 ) { | |
126 return(-1); | |
127 } | |
128 | |
129 /* If it does exist, verify that it's an available CD-ROM */ | |
130 is_cd = 0; | |
131 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { | |
1051
091350827e08
SDL_CDOpen() fails on Linux if data track on disc is mounted in the
Ryan C. Gordon <icculus@icculus.org>
parents:
998
diff
changeset
|
132 cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0); |
0 | 133 if ( cdfd >= 0 ) { |
134 info.cdsc_format = CDROM_MSF; | |
135 /* Under Linux, EIO occurs when a disk is not present. | |
136 */ | |
137 if ( (ioctl(cdfd, CDROMSUBCHNL, &info) == 0) || | |
138 ERRNO_TRAYEMPTY(errno) ) { | |
139 is_cd = 1; | |
140 } | |
141 close(cdfd); | |
142 } | |
143 #ifdef USE_MNTENT | |
144 /* Even if we can't read it, it might be mounted */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
145 else if ( mnttype && (SDL_strcmp(mnttype, MNTTYPE_CDROM) == 0) ) { |
0 | 146 is_cd = 1; |
147 } | |
148 #endif | |
149 } | |
150 return(is_cd); | |
151 } | |
152 | |
153 /* Add a CD-ROM drive to our list of valid drives */ | |
154 static void AddDrive(char *drive, struct stat *stbuf) | |
155 { | |
156 int i; | |
157 | |
158 if ( SDL_numcds < MAX_DRIVES ) { | |
159 /* Check to make sure it's not already in our list. | |
160 This can happen when we see a drive via symbolic link. | |
161 */ | |
162 for ( i=0; i<SDL_numcds; ++i ) { | |
163 if ( stbuf->st_rdev == SDL_cdmode[i] ) { | |
164 #ifdef DEBUG_CDROM | |
165 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); | |
166 #endif | |
167 return; | |
168 } | |
169 } | |
170 | |
171 /* Add this drive to our list */ | |
172 i = SDL_numcds; | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
173 SDL_cdlist[i] = SDL_strdup(drive); |
0 | 174 if ( SDL_cdlist[i] == NULL ) { |
175 SDL_OutOfMemory(); | |
176 return; | |
177 } | |
178 SDL_cdmode[i] = stbuf->st_rdev; | |
179 ++SDL_numcds; | |
180 #ifdef DEBUG_CDROM | |
181 fprintf(stderr, "Added CD-ROM drive: %s\n", drive); | |
182 #endif | |
183 } | |
184 } | |
185 | |
186 #ifdef USE_MNTENT | |
187 static void CheckMounts(const char *mtab) | |
188 { | |
189 FILE *mntfp; | |
190 struct mntent *mntent; | |
191 struct stat stbuf; | |
192 | |
193 mntfp = setmntent(mtab, "r"); | |
194 if ( mntfp != NULL ) { | |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
195 char *tmp; |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
196 char *mnt_type; |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
197 size_t mnt_type_len; |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
198 char *mnt_dev; |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
199 size_t mnt_dev_len; |
0 | 200 |
201 while ( (mntent=getmntent(mntfp)) != NULL ) { | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
202 mnt_type_len = SDL_strlen(mntent->mnt_type) + 1; |
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
203 mnt_type = SDL_stack_alloc(char, mnt_type_len); |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
204 if (mnt_type == NULL) |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
205 continue; /* maybe you'll get lucky next time. */ |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
206 |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
207 mnt_dev_len = SDL_strlen(mntent->mnt_fsname) + 1; |
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
208 mnt_dev = SDL_stack_alloc(char, mnt_dev_len); |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
209 if (mnt_dev == NULL) { |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
210 SDL_stack_free(mnt_type); |
139
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
211 continue; |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
212 } |
ef23a1bf1244
Fixed potential buffer overflow in Linux CD code (thanks Ryan!)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
213 |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
214 SDL_strlcpy(mnt_type, mntent->mnt_type, mnt_type_len); |
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
215 SDL_strlcpy(mnt_dev, mntent->mnt_fsname, mnt_dev_len); |
0 | 216 |
217 /* Handle "supermount" filesystem mounts */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
218 if ( SDL_strcmp(mnt_type, MNTTYPE_SUPER) == 0 ) { |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
219 tmp = SDL_strstr(mntent->mnt_opts, "fs="); |
0 | 220 if ( tmp ) { |
3853
c6d3c5549886
Use correct function to free allocated mem
Patrice Mandin <patmandin@gmail.com>
parents:
1635
diff
changeset
|
221 SDL_stack_free(mnt_type); |
1341
d02b552e5304
Configure dynamically generates SDL_config.h
Sam Lantinga <slouken@libsdl.org>
parents:
1338
diff
changeset
|
222 mnt_type = SDL_strdup(tmp + SDL_strlen("fs=")); |
247
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
223 if ( mnt_type ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
224 tmp = SDL_strchr(mnt_type, ','); |
247
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
225 if ( tmp ) { |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
226 *tmp = '\0'; |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
227 } |
0 | 228 } |
229 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
230 tmp = SDL_strstr(mntent->mnt_opts, "dev="); |
0 | 231 if ( tmp ) { |
3853
c6d3c5549886
Use correct function to free allocated mem
Patrice Mandin <patmandin@gmail.com>
parents:
1635
diff
changeset
|
232 SDL_stack_free(mnt_dev); |
1341
d02b552e5304
Configure dynamically generates SDL_config.h
Sam Lantinga <slouken@libsdl.org>
parents:
1338
diff
changeset
|
233 mnt_dev = SDL_strdup(tmp + SDL_strlen("dev=")); |
247
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
234 if ( mnt_dev ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
235 tmp = SDL_strchr(mnt_dev, ','); |
247
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
236 if ( tmp ) { |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
237 *tmp = '\0'; |
b0f09f86378d
Fix crash with Linux supermount fstab entries (thanks Erno!)
Sam Lantinga <slouken@libsdl.org>
parents:
139
diff
changeset
|
238 } |
0 | 239 } |
240 } | |
241 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
242 if ( SDL_strcmp(mnt_type, MNTTYPE_CDROM) == 0 ) { |
0 | 243 #ifdef DEBUG_CDROM |
244 fprintf(stderr, "Checking mount path from %s: %s mounted on %s of %s\n", | |
245 mtab, mnt_dev, mntent->mnt_dir, mnt_type); | |
246 #endif | |
247 if (CheckDrive(mnt_dev, mnt_type, &stbuf) > 0) { | |
248 AddDrive(mnt_dev, &stbuf); | |
249 } | |
250 } | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
251 SDL_stack_free(mnt_dev); |
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
252 SDL_stack_free(mnt_type); |
0 | 253 } |
254 endmntent(mntfp); | |
255 } | |
256 } | |
257 #endif /* USE_MNTENT */ | |
258 | |
259 int SDL_SYS_CDInit(void) | |
260 { | |
261 /* checklist: /dev/cdrom, /dev/hd?, /dev/scd? /dev/sr? */ | |
262 static char *checklist[] = { | |
263 "cdrom", "?a hd?", "?0 scd?", "?0 sr?", NULL | |
264 }; | |
265 char *SDLcdrom; | |
266 int i, j, exists; | |
267 char drive[32]; | |
268 struct stat stbuf; | |
269 | |
270 /* Fill in our driver capabilities */ | |
271 SDL_CDcaps.Name = SDL_SYS_CDName; | |
272 SDL_CDcaps.Open = SDL_SYS_CDOpen; | |
273 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; | |
274 SDL_CDcaps.Status = SDL_SYS_CDStatus; | |
275 SDL_CDcaps.Play = SDL_SYS_CDPlay; | |
276 SDL_CDcaps.Pause = SDL_SYS_CDPause; | |
277 SDL_CDcaps.Resume = SDL_SYS_CDResume; | |
278 SDL_CDcaps.Stop = SDL_SYS_CDStop; | |
279 SDL_CDcaps.Eject = SDL_SYS_CDEject; | |
280 SDL_CDcaps.Close = SDL_SYS_CDClose; | |
281 | |
282 /* Look in the environment for our CD-ROM drive list */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
283 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ |
0 | 284 if ( SDLcdrom != NULL ) { |
285 char *cdpath, *delim; | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
286 size_t len = SDL_strlen(SDLcdrom)+1; |
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
287 cdpath = SDL_stack_alloc(char, len); |
0 | 288 if ( cdpath != NULL ) { |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
289 SDL_strlcpy(cdpath, SDLcdrom, len); |
0 | 290 SDLcdrom = cdpath; |
291 do { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
292 delim = SDL_strchr(SDLcdrom, ':'); |
0 | 293 if ( delim ) { |
294 *delim++ = '\0'; | |
295 } | |
296 #ifdef DEBUG_CDROM | |
297 fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom); | |
298 #endif | |
299 if ( CheckDrive(SDLcdrom, NULL, &stbuf) > 0 ) { | |
300 AddDrive(SDLcdrom, &stbuf); | |
301 } | |
302 if ( delim ) { | |
303 SDLcdrom = delim; | |
304 } else { | |
305 SDLcdrom = NULL; | |
306 } | |
307 } while ( SDLcdrom ); | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
308 SDL_stack_free(cdpath); |
0 | 309 } |
310 | |
311 /* If we found our drives, there's nothing left to do */ | |
312 if ( SDL_numcds > 0 ) { | |
313 return(0); | |
314 } | |
315 } | |
316 | |
317 #ifdef USE_MNTENT | |
318 /* Check /dev/cdrom first :-) */ | |
319 if (CheckDrive("/dev/cdrom", NULL, &stbuf) > 0) { | |
320 AddDrive("/dev/cdrom", &stbuf); | |
321 } | |
322 | |
323 /* Now check the currently mounted CD drives */ | |
324 CheckMounts(_PATH_MOUNTED); | |
325 | |
326 /* Finally check possible mountable drives in /etc/fstab */ | |
327 CheckMounts(_PATH_MNTTAB); | |
328 | |
329 /* If we found our drives, there's nothing left to do */ | |
330 if ( SDL_numcds > 0 ) { | |
331 return(0); | |
332 } | |
333 #endif /* USE_MNTENT */ | |
334 | |
335 /* Scan the system for CD-ROM drives. | |
336 Not always 100% reliable, so use the USE_MNTENT code above first. | |
337 */ | |
338 for ( i=0; checklist[i]; ++i ) { | |
339 if ( checklist[i][0] == '?' ) { | |
340 char *insert; | |
341 exists = 1; | |
342 for ( j=checklist[i][1]; exists; ++j ) { | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
343 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]); |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
344 insert = SDL_strchr(drive, '?'); |
0 | 345 if ( insert != NULL ) { |
346 *insert = j; | |
347 } | |
348 #ifdef DEBUG_CDROM | |
349 fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive); | |
350 #endif | |
351 switch (CheckDrive(drive, NULL, &stbuf)) { | |
352 /* Drive exists and is a CD-ROM */ | |
353 case 1: | |
354 AddDrive(drive, &stbuf); | |
355 break; | |
356 /* Drive exists, but isn't a CD-ROM */ | |
357 case 0: | |
358 break; | |
359 /* Drive doesn't exist */ | |
360 case -1: | |
361 exists = 0; | |
362 break; | |
363 } | |
364 } | |
365 } else { | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
366 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); |
0 | 367 #ifdef DEBUG_CDROM |
368 fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive); | |
369 #endif | |
370 if ( CheckDrive(drive, NULL, &stbuf) > 0 ) { | |
371 AddDrive(drive, &stbuf); | |
372 } | |
373 } | |
374 } | |
375 return(0); | |
376 } | |
377 | |
378 /* General ioctl() CD-ROM command function */ | |
379 static int SDL_SYS_CDioctl(int id, int command, void *arg) | |
380 { | |
381 int retval; | |
382 | |
383 retval = ioctl(id, command, arg); | |
384 if ( retval < 0 ) { | |
385 SDL_SetError("ioctl() error: %s", strerror(errno)); | |
386 } | |
387 return(retval); | |
388 } | |
389 | |
390 static const char *SDL_SYS_CDName(int drive) | |
391 { | |
392 return(SDL_cdlist[drive]); | |
393 } | |
394 | |
395 static int SDL_SYS_CDOpen(int drive) | |
396 { | |
1051
091350827e08
SDL_CDOpen() fails on Linux if data track on disc is mounted in the
Ryan C. Gordon <icculus@icculus.org>
parents:
998
diff
changeset
|
397 return(open(SDL_cdlist[drive], (O_RDONLY|O_NONBLOCK), 0)); |
0 | 398 } |
399 | |
400 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) | |
401 { | |
402 struct cdrom_tochdr toc; | |
403 int i, okay; | |
404 struct cdrom_tocentry entry; | |
405 | |
406 okay = 0; | |
407 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc) == 0 ) { | |
408 cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1; | |
409 if ( cdrom->numtracks > SDL_MAX_TRACKS ) { | |
410 cdrom->numtracks = SDL_MAX_TRACKS; | |
411 } | |
412 /* Read all the track TOC entries */ | |
413 for ( i=0; i<=cdrom->numtracks; ++i ) { | |
414 if ( i == cdrom->numtracks ) { | |
415 cdrom->track[i].id = CDROM_LEADOUT; | |
416 } else { | |
417 cdrom->track[i].id = toc.cdth_trk0+i; | |
418 } | |
419 entry.cdte_track = cdrom->track[i].id; | |
420 entry.cdte_format = CDROM_MSF; | |
421 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, | |
422 &entry) < 0 ) { | |
423 break; | |
424 } else { | |
425 if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) { | |
426 cdrom->track[i].type = SDL_DATA_TRACK; | |
427 } else { | |
428 cdrom->track[i].type = SDL_AUDIO_TRACK; | |
429 } | |
430 cdrom->track[i].offset = MSF_TO_FRAMES( | |
431 entry.cdte_addr.msf.minute, | |
432 entry.cdte_addr.msf.second, | |
433 entry.cdte_addr.msf.frame); | |
434 cdrom->track[i].length = 0; | |
435 if ( i > 0 ) { | |
436 cdrom->track[i-1].length = | |
437 cdrom->track[i].offset- | |
438 cdrom->track[i-1].offset; | |
439 } | |
440 } | |
441 } | |
442 if ( i == (cdrom->numtracks+1) ) { | |
443 okay = 1; | |
444 } | |
445 } | |
446 return(okay ? 0 : -1); | |
447 } | |
448 | |
449 /* Get CD-ROM status */ | |
450 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) | |
451 { | |
452 CDstatus status; | |
453 struct cdrom_tochdr toc; | |
454 struct cdrom_subchnl info; | |
455 | |
456 info.cdsc_format = CDROM_MSF; | |
457 if ( ioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) { | |
458 if ( ERRNO_TRAYEMPTY(errno) ) { | |
459 status = CD_TRAYEMPTY; | |
460 } else { | |
461 status = CD_ERROR; | |
462 } | |
463 } else { | |
464 switch (info.cdsc_audiostatus) { | |
465 case CDROM_AUDIO_INVALID: | |
466 case CDROM_AUDIO_NO_STATUS: | |
467 /* Try to determine if there's a CD available */ | |
468 if (ioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) | |
469 status = CD_STOPPED; | |
470 else | |
471 status = CD_TRAYEMPTY; | |
472 break; | |
473 case CDROM_AUDIO_COMPLETED: | |
474 status = CD_STOPPED; | |
475 break; | |
476 case CDROM_AUDIO_PLAY: | |
477 status = CD_PLAYING; | |
478 break; | |
479 case CDROM_AUDIO_PAUSED: | |
480 /* Workaround buggy CD-ROM drive */ | |
481 if ( info.cdsc_trk == CDROM_LEADOUT ) { | |
482 status = CD_STOPPED; | |
483 } else { | |
484 status = CD_PAUSED; | |
485 } | |
486 break; | |
487 default: | |
488 status = CD_ERROR; | |
489 break; | |
490 } | |
491 } | |
492 if ( position ) { | |
493 if ( status == CD_PLAYING || (status == CD_PAUSED) ) { | |
494 *position = MSF_TO_FRAMES( | |
495 info.cdsc_absaddr.msf.minute, | |
496 info.cdsc_absaddr.msf.second, | |
497 info.cdsc_absaddr.msf.frame); | |
498 } else { | |
499 *position = 0; | |
500 } | |
501 } | |
502 return(status); | |
503 } | |
504 | |
505 /* Start play */ | |
506 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) | |
507 { | |
508 struct cdrom_msf playtime; | |
509 | |
510 FRAMES_TO_MSF(start, | |
511 &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0); | |
512 FRAMES_TO_MSF(start+length, | |
513 &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1); | |
514 #ifdef DEBUG_CDROM | |
515 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", | |
516 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, | |
517 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1); | |
518 #endif | |
519 return(SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime)); | |
520 } | |
521 | |
522 /* Pause play */ | |
523 static int SDL_SYS_CDPause(SDL_CD *cdrom) | |
524 { | |
525 return(SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0)); | |
526 } | |
527 | |
528 /* Resume play */ | |
529 static int SDL_SYS_CDResume(SDL_CD *cdrom) | |
530 { | |
531 return(SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0)); | |
532 } | |
533 | |
534 /* Stop play */ | |
535 static int SDL_SYS_CDStop(SDL_CD *cdrom) | |
536 { | |
537 return(SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0)); | |
538 } | |
539 | |
540 /* Eject the CD-ROM */ | |
541 static int SDL_SYS_CDEject(SDL_CD *cdrom) | |
542 { | |
543 return(SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0)); | |
544 } | |
545 | |
546 /* Close the CD-ROM handle */ | |
547 static void SDL_SYS_CDClose(SDL_CD *cdrom) | |
548 { | |
549 close(cdrom->id); | |
550 } | |
551 | |
552 void SDL_SYS_CDQuit(void) | |
553 { | |
554 int i; | |
555 | |
556 if ( SDL_numcds > 0 ) { | |
557 for ( i=0; i<SDL_numcds; ++i ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
558 SDL_free(SDL_cdlist[i]); |
0 | 559 } |
560 SDL_numcds = 0; | |
561 } | |
562 } | |
563 | |
1635
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
564 #endif /* SDL_CDROM_LINUX */ |