Mercurial > sdl-ios-xcode
view src/cdrom/beos/SDL_syscdrom.cc @ 2872:762f0663c36a
Use the desktop format instead of an arbitrary one.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 16 Dec 2008 17:40:30 +0000 |
parents | 99210400e8b9 |
children |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2009 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" #ifdef SDL_CDROM_BEOS /* Functions for system-level CD-ROM audio control on BeOS (not completely implemented yet) */ #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <scsi.h> #include <Directory.h> #include <Entry.h> #include <Path.h> #include "SDL_cdrom.h" extern "C" { #include "../SDL_syscdrom.h" } /* Constants to help us get at the SCSI table-of-contents info */ #define CD_NUMTRACKS(toc) toc.toc_data[3] #define CD_TRACK(toc, track) (&toc.toc_data[6+(track)*8]) #define CD_TRACK_N(toc, track) CD_TRACK(toc, track)[0] #define CD_TRACK_M(toc, track) CD_TRACK(toc, track)[3] #define CD_TRACK_S(toc, track) CD_TRACK(toc, track)[4] #define CD_TRACK_F(toc, track) CD_TRACK(toc, track)[5] /* Constants to help us get at the SCSI position info */ #define POS_TRACK(pos) pos.position[6] #define POS_ABS_M(pos) pos.position[9] #define POS_ABS_S(pos) pos.position[10] #define POS_ABS_F(pos) pos.position[11] #define POS_REL_M(pos) pos.position[13] #define POS_REL_S(pos) pos.position[14] #define POS_REL_F(pos) pos.position[15] /* The maximum number of CD-ROM drives we'll detect */ #define MAX_DRIVES 16 /* A list of available CD-ROM drives */ static char *SDL_cdlist[MAX_DRIVES]; /* The system-dependent CD control functions */ static const char *SDL_SYS_CDName(int drive); static int SDL_SYS_CDOpen(int drive); static int SDL_SYS_CDGetTOC(SDL_CD * cdrom); static CDstatus SDL_SYS_CDStatus(SDL_CD * cdrom, int *position); static int SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length); static int SDL_SYS_CDPause(SDL_CD * cdrom); static int SDL_SYS_CDResume(SDL_CD * cdrom); static int SDL_SYS_CDStop(SDL_CD * cdrom); static int SDL_SYS_CDEject(SDL_CD * cdrom); static void SDL_SYS_CDClose(SDL_CD * cdrom); int try_dir(const char *directory); /* Check a drive to see if it is a CD-ROM */ static int CheckDrive(char *drive) { struct stat stbuf; int is_cd, cdfd; device_geometry info; /* If it doesn't exist, return -1 */ if (stat(drive, &stbuf) < 0) { return (-1); } /* If it does exist, verify that it's an available CD-ROM */ is_cd = 0; cdfd = open(drive, 0); if (cdfd >= 0) { if (ioctl(cdfd, B_GET_GEOMETRY, &info) == B_NO_ERROR) { if (info.device_type == B_CD) { is_cd = 1; } } close(cdfd); } else { /* This can happen when the drive is open .. (?) */ ; is_cd = 1; } return (is_cd); } /* Add a CD-ROM drive to our list of valid drives */ static void AddDrive(char *drive) { int i; size_t len; if (SDL_numcds < MAX_DRIVES) { /* Add this drive to our list */ i = SDL_numcds; len = SDL_strlen(drive) + 1; SDL_cdlist[i] = (char *) SDL_malloc(len); if (SDL_cdlist[i] == NULL) { SDL_OutOfMemory(); return; } SDL_strlcpy(SDL_cdlist[i], drive, len); ++SDL_numcds; #ifdef CDROM_DEBUG fprintf(stderr, "Added CD-ROM drive: %s\n", drive); #endif } } /* IDE bus scanning magic */ enum { IDE_GET_DEVICES_INFO = B_DEVICE_OP_CODES_END + 50, }; struct ide_ctrl_info { bool ide_0_present; bool ide_0_master_present; bool ide_0_slave_present; int ide_0_master_type; int ide_0_slave_type; bool ide_1_present; bool ide_1_master_present; bool ide_1_slave_present; int ide_1_master_type; int ide_1_slave_type; }; int SDL_SYS_CDInit(void) { char *SDLcdrom; int raw_fd; struct ide_ctrl_info info; /* Fill in our driver capabilities */ SDL_CDcaps.Name = SDL_SYS_CDName; SDL_CDcaps.Open = SDL_SYS_CDOpen; SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; SDL_CDcaps.Status = SDL_SYS_CDStatus; SDL_CDcaps.Play = SDL_SYS_CDPlay; SDL_CDcaps.Pause = SDL_SYS_CDPause; SDL_CDcaps.Resume = SDL_SYS_CDResume; SDL_CDcaps.Stop = SDL_SYS_CDStop; SDL_CDcaps.Eject = SDL_SYS_CDEject; SDL_CDcaps.Close = SDL_SYS_CDClose; /* Look in the environment for our CD-ROM drive list */ SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ if (SDLcdrom != NULL) { char *cdpath, *delim; size_t len = SDL_strlen(SDLcdrom) + 1; cdpath = SDL_stack_alloc(char, len); if (cdpath != NULL) { SDL_strlcpy(cdpath, SDLcdrom, len); SDLcdrom = cdpath; do { delim = SDL_strchr(SDLcdrom, ':'); if (delim) { *delim++ = '\0'; } if (CheckDrive(SDLcdrom) > 0) { AddDrive(SDLcdrom); } if (delim) { SDLcdrom = delim; } else { SDLcdrom = NULL; } } while (SDLcdrom); SDL_stack_free(cdpath); } /* If we found our drives, there's nothing left to do */ if (SDL_numcds > 0) { return (0); } } /* Scan the system for CD-ROM drives */ try_dir("/dev/disk"); return 0; } int try_dir(const char *directory) { BDirectory dir; dir.SetTo(directory); if (dir.InitCheck() != B_NO_ERROR) { return false; } dir.Rewind(); BEntry entry; while (dir.GetNextEntry(&entry) >= 0) { BPath path; const char *name; entry_ref e; if (entry.GetPath(&path) != B_NO_ERROR) continue; name = path.Path(); if (entry.GetRef(&e) != B_NO_ERROR) continue; if (entry.IsDirectory()) { if (SDL_strcmp(e.name, "floppy") == 0) continue; /* ignore floppy (it is not silent) */ int devfd = try_dir(name); if (devfd >= 0) return devfd; } else { int devfd; device_geometry g; if (SDL_strcmp(e.name, "raw") != 0) continue; /* ignore partitions */ devfd = open(name, O_RDONLY); if (devfd < 0) continue; if (ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) { if (g.device_type == B_CD) { AddDrive(strdup(name)); } } close(devfd); } } return B_ERROR; } /* General ioctl() CD-ROM command function */ static int SDL_SYS_CDioctl(int index, int command, void *arg) { int okay; int fd; okay = 0; fd = open(SDL_cdlist[index], 0); if (fd >= 0) { if (ioctl(fd, command, arg) == B_NO_ERROR) { okay = 1; } close(fd); } return (okay ? 0 : -1); } static const char * SDL_SYS_CDName(int drive) { return (SDL_cdlist[drive]); } static int SDL_SYS_CDOpen(int drive) { return (drive); } static int SDL_SYS_CDGetTOC(SDL_CD * cdrom) { int i; scsi_toc toc; if (SDL_SYS_CDioctl(cdrom->id, B_SCSI_GET_TOC, &toc) == 0) { cdrom->numtracks = CD_NUMTRACKS(toc); if (cdrom->numtracks > SDL_MAX_TRACKS) { cdrom->numtracks = SDL_MAX_TRACKS; } for (i = 0; i <= cdrom->numtracks; ++i) { cdrom->track[i].id = CD_TRACK_N(toc, i); /* FIXME: How do we tell on BeOS? */ cdrom->track[i].type = SDL_AUDIO_TRACK; cdrom->track[i].offset = MSF_TO_FRAMES(CD_TRACK_M(toc, i), CD_TRACK_S(toc, i), CD_TRACK_F(toc, i)); cdrom->track[i].length = 0; if (i > 0) { cdrom->track[i - 1].length = cdrom->track[i].offset - cdrom->track[i - 1].offset; } } return (0); } else { return (-1); } } /* Get CD-ROM status */ static CDstatus SDL_SYS_CDStatus(SDL_CD * cdrom, int *position) { CDstatus status; int fd; int cur_frame; scsi_position pos; fd = open(SDL_cdlist[cdrom->id], 0); cur_frame = 0; if (fd >= 0) { if (ioctl(fd, B_SCSI_GET_POSITION, &pos) == B_NO_ERROR) { cur_frame = MSF_TO_FRAMES(POS_ABS_M(pos), POS_ABS_S(pos), POS_ABS_F(pos)); } if (!pos.position[1] || (pos.position[1] >= 0x13) || ((pos.position[1] == 0x12) && (!pos.position[6]))) { status = CD_STOPPED; } else if (pos.position[1] == 0x11) { status = CD_PLAYING; } else { status = CD_PAUSED; } close(fd); } else { status = CD_TRAYEMPTY; } if (position) { *position = cur_frame; } return (status); } /* Start play */ static int SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length) { int okay; int fd; scsi_play_position pos; okay = 0; fd = open(SDL_cdlist[cdrom->id], 0); if (fd >= 0) { FRAMES_TO_MSF(start, &pos.start_m, &pos.start_s, &pos.start_f); FRAMES_TO_MSF(start + length, &pos.end_m, &pos.end_s, &pos.end_f); if (ioctl(fd, B_SCSI_PLAY_POSITION, &pos) == B_NO_ERROR) { okay = 1; } close(fd); } return (okay ? 0 : -1); } /* Pause play */ static int SDL_SYS_CDPause(SDL_CD * cdrom) { return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_PAUSE_AUDIO, 0)); } /* Resume play */ static int SDL_SYS_CDResume(SDL_CD * cdrom) { return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_RESUME_AUDIO, 0)); } /* Stop play */ static int SDL_SYS_CDStop(SDL_CD * cdrom) { return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_STOP_AUDIO, 0)); } /* Eject the CD-ROM */ static int SDL_SYS_CDEject(SDL_CD * cdrom) { return (SDL_SYS_CDioctl(cdrom->id, B_SCSI_EJECT, 0)); } /* Close the CD-ROM handle */ static void SDL_SYS_CDClose(SDL_CD * cdrom) { close(cdrom->id); } void SDL_SYS_CDQuit(void) { int i; if (SDL_numcds > 0) { for (i = 0; i < SDL_numcds; ++i) { SDL_free(SDL_cdlist[i]); } SDL_numcds = 0; } } #endif /* SDL_CDROM_BEOS */ /* vi: set ts=4 sw=4 expandtab: */