📄 sdl_syscdrom.c
字号:
/*
AIX audio module for SDL (Simple DirectMedia Layer)
Copyright (C) 2000 Carsten Griwodz
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Carsten Griwodz
griff@kom.tu-darmstadt.de
based on linux/SDL_syscdrom.c by Sam Lantinga
*/
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id: SDL_syscdrom.c,v 1.2 2002/04/22 21:38:02 wmay Exp $";
#endif
/* Functions for system-level CD-ROM audio control */
#define DEBUG_CDROM 1
#include <sys/types.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/devinfo.h>
#include <sys/mntctl.h>
#include <sys/statfs.h>
#include <sys/vmount.h>
#include <fstab.h>
#include <sys/scdisk.h>
#include "SDL_error.h"
#include "SDL_cdrom.h"
#include "SDL_syscdrom.h"
/* 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];
static dev_t SDL_cdmode[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);
static int SDL_SYS_CDioctl(int id, int command, void *arg);
/* Check a drive to see if it is a CD-ROM */
static int CheckDrive(char *drive, struct stat *stbuf)
{
int is_cd;
int cdfd;
int ret;
struct devinfo 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;
if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) {
cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
if ( cdfd >= 0 ) {
ret = SDL_SYS_CDioctl( cdfd, IOCINFO, &info );
if ( ret < 0 ) {
/* Some kind of error */
is_cd = 0;
} else {
if ( info.devtype == DD_CDROM ) {
is_cd = 1;
} else {
is_cd = 0;
}
}
close(cdfd);
}
#ifdef DEBUG_CDROM
else
{
fprintf(stderr, "Could not open drive %s (%s)\n", drive, strerror(errno));
}
#endif
}
return is_cd;
}
/* Add a CD-ROM drive to our list of valid drives */
static void AddDrive(char *drive, struct stat *stbuf)
{
int i;
if ( SDL_numcds < MAX_DRIVES ) {
/* Check to make sure it's not already in our list.
This can happen when we see a drive via symbolic link.
*/
for ( i=0; i<SDL_numcds; ++i ) {
if ( stbuf->st_rdev == SDL_cdmode[i] ) {
#ifdef DEBUG_CDROM
fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
#endif
return;
}
}
/* Add this drive to our list */
i = SDL_numcds;
SDL_cdlist[i] = (char *)malloc(strlen(drive)+1);
if ( SDL_cdlist[i] == NULL ) {
SDL_OutOfMemory();
return;
}
strcpy(SDL_cdlist[i], drive);
SDL_cdmode[i] = stbuf->st_rdev;
++SDL_numcds;
#ifdef DEBUG_CDROM
fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
#endif
}
}
static void CheckMounts()
{
char* buffer;
int bufsz;
struct vmount* ptr;
int ret;
buffer = (char*)malloc(10);
bufsz = 10;
if ( buffer==NULL )
{
fprintf(stderr, "Could not allocate 10 bytes in aix/SDL_syscdrom.c:CheckMounts\n" );
exit ( -10 );
}
do
{
/* mntctrl() returns an array of all mounted filesystems */
ret = mntctl ( MCTL_QUERY, bufsz, buffer );
if ( ret == 0 )
{
/* Buffer was too small, realloc. */
bufsz = *(int*)buffer; /* Required size is in first word. */
/* (whatever a word is in AIX 4.3.3) */
/* int seems to be OK in 32bit mode. */
free(buffer);
buffer = (char*)malloc(bufsz);
if ( buffer==NULL )
{
fprintf(stderr,
"Could not allocate %d bytes in aix/SDL_syscdrom.c:CheckMounts\n",
bufsz );
exit ( -10 );
}
}
else if ( ret < 0 )
{
#ifdef DEBUG_CDROM
fprintf(stderr, "Error reading vmount structures\n");
#endif
return;
}
}
while ( ret == 0 );
#ifdef DEBUG_CDROM
fprintf ( stderr, "Read %d vmount structures\n",ret );
#endif
ptr = (struct vmount*)buffer;
do
{
switch(ptr->vmt_gfstype)
{
case MNT_CDROM :
{
struct stat stbuf;
char* text;
text = (char*)ptr + ptr->vmt_data[VMT_OBJECT].vmt_off;
#ifdef DEBUG_CDROM
fprintf(stderr, "Checking mount path: %s mounted on %s\n",
text, (char*)ptr + ptr->vmt_data[VMT_STUB].vmt_off );
#endif
if ( CheckDrive( text, &stbuf) > 0)
{
AddDrive( text, &stbuf);
}
}
break;
default :
break;
}
ptr = (struct vmount*)((char*)ptr + ptr->vmt_length);
ret--;
}
while ( ret > 0 );
free ( buffer );
}
static int CheckNonmounts()
{
#ifdef _THREAD_SAFE
AFILE_t fsFile = NULL;
int passNo = 0;
int ret;
struct fstab entry;
struct stat stbuf;
ret = setfsent_r( &fsFile, &passNo );
if ( ret != 0 ) return -1;
do
{
ret = getfsent_r ( &entry, &fsFile, &passNo );
if ( ret == 0 ) {
char* l = strrchr(entry.fs_spec,'/');
if ( l != NULL ) {
if ( !strncmp("cd",++l,2) ) {
#ifdef DEBUG_CDROM
fprintf(stderr,
"Found unmounted CD ROM drive with device name %s\n",
entry.fs_spec);
#endif
if ( CheckDrive( entry.fs_spec, &stbuf) > 0)
{
AddDrive( entry.fs_spec, &stbuf);
}
}
}
}
}
while ( ret == 0 );
ret = endfsent_r ( &fsFile );
if ( ret != 0 ) return -1;
return 0;
#else
struct fstab* entry;
struct stat stbuf;
setfsent();
do
{
entry = getfsent();
if ( entry != NULL ) {
char* l = strrchr(entry->fs_spec,'/');
if ( l != NULL ) {
if ( !strncmp("cd",++l,2) ) {
#ifdef DEBUG_CDROM
fprintf(stderr,"Found unmounted CD ROM drive with device name %s", entry->fs_spec);
#endif
if ( CheckDrive( entry->fs_spec, &stbuf) > 0)
{
AddDrive( entry->fs_spec, &stbuf);
}
}
}
}
}
while ( entry != NULL );
endfsent();
#endif
}
int SDL_SYS_CDInit(void)
{
char *SDLcdrom;
struct stat stbuf;
/* 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 = getenv("SDL_CDROM"); /* ':' separated list of devices */
if ( SDLcdrom != NULL ) {
char *cdpath, *delim;
cdpath = malloc(strlen(SDLcdrom)+1);
if ( cdpath != NULL ) {
strcpy(cdpath, SDLcdrom);
SDLcdrom = cdpath;
do {
delim = strchr(SDLcdrom, ':');
if ( delim ) {
*delim++ = '\0';
}
#ifdef DEBUG_CDROM
fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom);
#endif
if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
AddDrive(SDLcdrom, &stbuf);
}
if ( delim ) {
SDLcdrom = delim;
} else {
SDLcdrom = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -