Home | History | Annotate | Download | only in mint
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2004 Sam Lantinga
      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
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 #ifdef SDL_CDROM_MINT
     25 
     26 /*
     27 	Atari MetaDOS CD-ROM functions
     28 
     29 	Patrice Mandin
     30 */
     31 
     32 #include <errno.h>
     33 
     34 #include <cdromio.h>
     35 #include <metados.h>
     36 
     37 #include "SDL_cdrom.h"
     38 #include "../SDL_syscdrom.h"
     39 
     40 /* Some ioctl() errno values which occur when the tray is empty */
     41 #ifndef ENOMEDIUM
     42 #define ENOMEDIUM ENOENT
     43 #endif
     44 #define ERRNO_TRAYEMPTY(errno)	\
     45 	((errno == EIO)    || (errno == ENOENT) || \
     46 	 (errno == EINVAL) || (errno == ENOMEDIUM))
     47 
     48 /* The maximum number of CD-ROM drives we'll detect */
     49 #define MAX_DRIVES	32
     50 
     51 typedef struct {
     52 	unsigned char device[3];	/* Physical device letter + ':' + '\0' */
     53 	metaopen_t	metaopen;		/* Infos on opened drive */
     54 } metados_drive_t;
     55 
     56 static metados_drive_t metados_drives[MAX_DRIVES];
     57 
     58 /* The system-dependent CD control functions */
     59 static const char *SDL_SYS_CDName(int drive);
     60 static int SDL_SYS_CDOpen(int drive);
     61 static void SDL_SYS_CDClose(SDL_CD *cdrom);
     62 static int SDL_SYS_CDioctl(int id, int command, void *arg);
     63 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
     64 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
     65 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
     66 static int SDL_SYS_CDPause(SDL_CD *cdrom);
     67 static int SDL_SYS_CDResume(SDL_CD *cdrom);
     68 static int SDL_SYS_CDStop(SDL_CD *cdrom);
     69 static int SDL_SYS_CDEject(SDL_CD *cdrom);
     70 
     71 int SDL_SYS_CDInit(void)
     72 {
     73 	metainit_t	metainit={0,0,0,0};
     74 	metaopen_t	metaopen;
     75 	int i, handle;
     76 	struct cdrom_subchnl info;
     77 
     78 	Metainit(&metainit);
     79 	if (metainit.version == NULL) {
     80 #ifdef DEBUG_CDROM
     81 		fprintf(stderr, "MetaDOS not installed\n");
     82 #endif
     83 		return -1;
     84 	}
     85 
     86 	if (metainit.drives_map == 0) {
     87 #ifdef DEBUG_CDROM
     88 		fprintf(stderr, "No MetaDOS devices present\n");
     89 #endif
     90 		return -1;
     91 	}
     92 
     93 	SDL_numcds = 0;
     94 
     95 	for (i='A'; i<='Z'; i++) {
     96 		metados_drives[SDL_numcds].device[0] = 0;
     97 		metados_drives[SDL_numcds].device[1] = ':';
     98 		metados_drives[SDL_numcds].device[2] = 0;
     99 
    100 		if (metainit.drives_map & (1<<(i-'A'))) {
    101 			handle = Metaopen(i, &metaopen);
    102 			if (handle == 0) {
    103 
    104 				info.cdsc_format = CDROM_MSF;
    105 				if ( (Metaioctl(i, METADOS_IOCTL_MAGIC, CDROMSUBCHNL, &info) == 0) || ERRNO_TRAYEMPTY(errno) ) {
    106 					metados_drives[SDL_numcds].device[0] = i;
    107 					++SDL_numcds;
    108 				}
    109 
    110 				Metaclose(i);
    111 			}
    112 		}
    113 	}
    114 
    115 	/* Fill in our driver capabilities */
    116 	SDL_CDcaps.Name = SDL_SYS_CDName;
    117 	SDL_CDcaps.Open = SDL_SYS_CDOpen;
    118 	SDL_CDcaps.Close = SDL_SYS_CDClose;
    119 
    120 	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
    121 	SDL_CDcaps.Status = SDL_SYS_CDStatus;
    122 	SDL_CDcaps.Play = SDL_SYS_CDPlay;
    123 	SDL_CDcaps.Pause = SDL_SYS_CDPause;
    124 	SDL_CDcaps.Resume = SDL_SYS_CDResume;
    125 	SDL_CDcaps.Stop = SDL_SYS_CDStop;
    126 	SDL_CDcaps.Eject = SDL_SYS_CDEject;
    127 
    128 	return 0;
    129 }
    130 
    131 void SDL_SYS_CDQuit(void)
    132 {
    133 	SDL_numcds = 0;
    134 }
    135 
    136 static const char *SDL_SYS_CDName(int drive)
    137 {
    138 	return(metados_drives[drive].device);
    139 }
    140 
    141 static int SDL_SYS_CDOpen(int drive)
    142 {
    143 	int handle;
    144 
    145 	handle = Metaopen(metados_drives[drive].device[0], &(metados_drives[drive].metaopen));
    146 	if (handle == 0) {
    147 		return drive;
    148 	}
    149 
    150 	return -1;
    151 }
    152 
    153 static void SDL_SYS_CDClose(SDL_CD *cdrom)
    154 {
    155 	Metaclose(metados_drives[cdrom->id].device[0]);
    156 }
    157 
    158 static int SDL_SYS_CDioctl(int id, int command, void *arg)
    159 {
    160 	int retval;
    161 
    162 	retval = Metaioctl(metados_drives[id].device[0], METADOS_IOCTL_MAGIC, command, arg);
    163 	if ( retval < 0 ) {
    164 		SDL_SetError("ioctl() error: %s", strerror(errno));
    165 	}
    166 	return(retval);
    167 }
    168 
    169 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
    170 {
    171 	int i,okay;
    172 	struct cdrom_tochdr toc;
    173 	struct cdrom_tocentry entry;
    174 
    175 	/* Use standard ioctl() */
    176 	if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)<0) {
    177 		return -1;
    178 	}
    179 
    180 	cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1;
    181 	if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
    182 		cdrom->numtracks = SDL_MAX_TRACKS;
    183 	}
    184 
    185 	/* Read all the track TOC entries */
    186 	okay=1;
    187 	for ( i=0; i<=cdrom->numtracks; ++i ) {
    188 		if ( i == cdrom->numtracks ) {
    189 			cdrom->track[i].id = CDROM_LEADOUT;
    190 		} else {
    191 			cdrom->track[i].id = toc.cdth_trk0+i;
    192 		}
    193 		entry.cdte_track = cdrom->track[i].id;
    194 		entry.cdte_format = CDROM_MSF;
    195 		if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, &entry) < 0 ) {
    196 			okay=0;
    197 			break;
    198 		} else {
    199 			if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) {
    200 				cdrom->track[i].type = SDL_DATA_TRACK;
    201 			} else {
    202 				cdrom->track[i].type = SDL_AUDIO_TRACK;
    203 			}
    204 			cdrom->track[i].offset = MSF_TO_FRAMES(
    205 				entry.cdte_addr.msf.minute,
    206 				entry.cdte_addr.msf.second,
    207 				entry.cdte_addr.msf.frame);
    208 				cdrom->track[i].length = 0;
    209 			if ( i > 0 ) {
    210 				cdrom->track[i-1].length = cdrom->track[i].offset-cdrom->track[i-1].offset;
    211 			}
    212 		}
    213 	}
    214 
    215 	return(okay ? 0 : -1);
    216 }
    217 
    218 /* Get CD-ROM status */
    219 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
    220 {
    221 	CDstatus status;
    222 	struct cdrom_tochdr toc;
    223 	struct cdrom_subchnl info;
    224 
    225 	info.cdsc_format = CDROM_MSF;
    226 	if ( SDL_SYS_CDioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) {
    227 		if ( ERRNO_TRAYEMPTY(errno) ) {
    228 			status = CD_TRAYEMPTY;
    229 		} else {
    230 			status = CD_ERROR;
    231 		}
    232 	} else {
    233 		switch (info.cdsc_audiostatus) {
    234 			case CDROM_AUDIO_INVALID:
    235 			case CDROM_AUDIO_NO_STATUS:
    236 				/* Try to determine if there's a CD available */
    237 				if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) {
    238 					status = CD_STOPPED;
    239 				} else {
    240 					status = CD_TRAYEMPTY;
    241 				}
    242 				break;
    243 			case CDROM_AUDIO_COMPLETED:
    244 				status = CD_STOPPED;
    245 				break;
    246 			case CDROM_AUDIO_PLAY:
    247 				status = CD_PLAYING;
    248 				break;
    249 			case CDROM_AUDIO_PAUSED:
    250 				/* Workaround buggy CD-ROM drive */
    251 				if ( info.cdsc_trk == CDROM_LEADOUT ) {
    252 					status = CD_STOPPED;
    253 				} else {
    254 					status = CD_PAUSED;
    255 				}
    256 				break;
    257 			default:
    258 				status = CD_ERROR;
    259 				break;
    260 		}
    261 	}
    262 	if ( position ) {
    263 		if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
    264 			*position = MSF_TO_FRAMES(
    265 					info.cdsc_absaddr.msf.minute,
    266 					info.cdsc_absaddr.msf.second,
    267 					info.cdsc_absaddr.msf.frame);
    268 		} else {
    269 			*position = 0;
    270 		}
    271 	}
    272 	return(status);
    273 }
    274 
    275 /* Start play */
    276 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
    277 {
    278 	struct cdrom_msf playtime;
    279 
    280 	FRAMES_TO_MSF(start,
    281 	   &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0);
    282 	FRAMES_TO_MSF(start+length,
    283 	   &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1);
    284 #ifdef DEBUG_CDROM
    285   fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
    286 	playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
    287 	playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
    288 #endif
    289 
    290 	return SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime);
    291 }
    292 
    293 /* Pause play */
    294 static int SDL_SYS_CDPause(SDL_CD *cdrom)
    295 {
    296 	return SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0);
    297 }
    298 
    299 /* Resume play */
    300 static int SDL_SYS_CDResume(SDL_CD *cdrom)
    301 {
    302 	return SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0);
    303 }
    304 
    305 /* Stop play */
    306 static int SDL_SYS_CDStop(SDL_CD *cdrom)
    307 {
    308 	return SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0);
    309 }
    310 
    311 /* Eject the CD-ROM */
    312 static int SDL_SYS_CDEject(SDL_CD *cdrom)
    313 {
    314 	return SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0);
    315 }
    316 
    317 #endif /* SDL_CDROM_MINT */
    318