⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_syscdrom.c

📁 SDL库 在进行视频显示程序spcaview安装时必须的库文件
💻 C
字号:
/*    SDL - Simple DirectMedia Layer    Copyright (C) 1997-2006 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_QNX/* Functions for system-level CD-ROM audio control */#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <fcntl.h>#include <errno.h>#include <unistd.h>#include <sys/cdrom.h>#include <sys/dcmd_cam.h>#include "SDL_timer.h"#include "SDL_cdrom.h"#include "../SDL_syscdrom.h"/* The maximum number of CD-ROM drives we'll detect */#define MAX_DRIVES 16#define QNX_CD_OPENMODE O_RDONLY | O_EXCL/* A list of available CD-ROM drives */static char *SDL_cdlist[MAX_DRIVES];static dev_t SDL_cdmode[MAX_DRIVES];static int   SDL_cdopen[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);/* Check a drive to see if it is a CD-ROM */static int CheckDrive(char *drive, struct stat *stbuf){    int is_cd, cdfd;    cam_devinfo_t dinfo;    int devctlret=0;    int atapi;    int removable;    int cdb10;    /* 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, QNX_CD_OPENMODE);        if ( cdfd >= 0 )        {            devctlret=devctl(cdfd, DCMD_CAM_DEVINFO, &dinfo, sizeof(cam_devinfo_t), NULL);            if (devctlret==EOK)            {               atapi=dinfo.flags & DEV_ATAPI;               removable=dinfo.flags & DEV_REMOVABLE;               cdb10=dinfo.flags & DEV_CDB_10; /* I'm not sure about that flag */               /* in the near future need to add more checks for splitting cdroms from other devices */               if ((atapi)&&(removable))               {                   is_cd = 1;               }            }            close(cdfd);        }    }    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])            {                return;            }        }        /* Add this drive to our list */        i = SDL_numcds;        SDL_cdlist[i] = SDL_strdup(drive);        if (SDL_cdlist[i] == NULL)        {            SDL_OutOfMemory();            return;        }        SDL_cdmode[i] = stbuf->st_rdev;        ++SDL_numcds;    }}int SDL_SYS_CDInit(void){    /* checklist: /dev/cdrom, /dev/cd?, /dev/scd? */    static char *checklist[]={"cdrom", "?0 cd?", "?1 cd?", "?0 scd?", NULL};    char *SDLcdrom;    int i, j, exists;    char drive[32];    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;    /* clearing device open status */    for (i=0; i<MAX_DRIVES; i++)    {       SDL_cdopen[i]=0;    }    /* 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, &stbuf) > 0)                {                    AddDrive(SDLcdrom, &stbuf);                }                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 */    for ( i=0; checklist[i]; ++i )    {        if (checklist[i][0] == '?')        {            char* insert;            exists = 1;            for ( j=checklist[i][1]; exists; ++j )            {                SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]);                insert = SDL_strchr(drive, '?');                if (insert != NULL)                {                    *insert = j;                }                switch (CheckDrive(drive, &stbuf))                {                    /* Drive exists and is a CD-ROM */                    case 1:                             AddDrive(drive, &stbuf);                             break;                    /* Drive exists, but isn't a CD-ROM */                    case 0:                             break;                    /* Drive doesn't exist */                    case -1:                             exists = 0;                             break;                }            }        }        else        {            SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);            if (CheckDrive(drive, &stbuf) > 0)            {                AddDrive(drive, &stbuf);            }        }    }    return(0);}static const char *SDL_SYS_CDName(int drive){    return(SDL_cdlist[drive]);}static int SDL_SYS_CDOpen(int drive){    int handle;    handle=open(SDL_cdlist[drive], QNX_CD_OPENMODE);    if (handle>0)    {        SDL_cdopen[drive]=handle;    }    return (handle);}static int SDL_SYS_CDGetTOC(SDL_CD *cdrom){    cdrom_read_toc_t toc;    int i, okay;    okay = 0;    if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), NULL) == 0)    {        cdrom->numtracks = toc.last_track - toc.first_track + 1;        if (cdrom->numtracks > SDL_MAX_TRACKS)        {            cdrom->numtracks = SDL_MAX_TRACKS;        }        /* Read all the track TOC entries */        for (i=0; i<=cdrom->numtracks; ++i)        {            if (i == cdrom->numtracks)            {                cdrom->track[i].id = CDROM_LEADOUT;            }            else            {                cdrom->track[i].id = toc.first_track+i;            }            cdrom->track[i].type = toc.toc_entry[i].control_adr & 0x0F;            cdrom->track[i].offset = toc.toc_entry[i].addr.lba;            cdrom->track[i].length = 0;            if (i > 0)            {                 cdrom->track[i-1].length = cdrom->track[i].offset-cdrom->track[i-1].offset;            }        }        if (i == (cdrom->numtracks+1))        {            okay = 1;        }    }    return (okay ? 0 : -1);}/* Get CD-ROM status */static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position){    CDstatus status;    cdrom_read_toc_t toc;    cdrom_subch_data_t info;    cam_devinfo_t dinfo;    int devctlret=0;    int drive=-1;    int i;    int eagaincnt=0;    /* check media presence before read subchannel call, some cdroms can lockups */    /* if no media, while calling read subchannel functions.                     */    devctlret=devctl(cdrom->id, DCMD_CAM_DEVINFO, &dinfo, sizeof(cam_devinfo_t), NULL);    if (devctlret==EOK)    {        if ((dinfo.flags & DEV_NO_MEDIA)!=0)        {            status = CD_TRAYEMPTY;            if (position)            {                *position = 0;            }            return (status);        }    }    /* if media exists, then do other stuff */    SDL_memset(&info, 0x00, sizeof(info));    info.subch_command.data_format = CDROM_SUBCH_CURRENT_POSITION;    do {        devctlret=devctl(cdrom->id, DCMD_CAM_CDROMSUBCHNL, &info, sizeof(info), NULL);        if (devctlret==EIO)        {            /* big workaround for media change, handle is unusable after that,               that bug was found in QNX 6.2, 6.2.1 is not released yet.    */            for (i=0; i<MAX_DRIVES; i++)            {                if (SDL_cdopen[i]==cdrom->id)                {                    drive=i;                    break;                }            }            if (drive==-1)            {               /* that cannot happen, but ... */               break;            }            close(cdrom->id);            cdrom->id=open(SDL_cdlist[drive], QNX_CD_OPENMODE);            devctlret=EAGAIN;        }        if (devctlret==EAGAIN)        {            eagaincnt++;        }        if (eagaincnt==2)        {            /* workaround for broken cdroms, which can return always EAGAIN when its not ready, */            /* that mean errornous media or just no media avail                                 */            devctlret=ENXIO;            break;        }    } while ((devctlret==EAGAIN)||(devctlret==ESTALE));    if (devctlret != 0)    {        if (devctlret==ENXIO)        {            status = CD_TRAYEMPTY;        }        else        {            status = CD_ERROR;        }    }    else    {        switch (info.current_position.header.audio_status)        {            case CDROM_AUDIO_INVALID:            case CDROM_AUDIO_NO_STATUS:                 /* Try to determine if there's a CD available */                 if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), NULL)==0)                     status = CD_STOPPED;                 else                     status = CD_TRAYEMPTY;                 break;            case CDROM_AUDIO_COMPLETED:                 status = CD_STOPPED;                 break;            case CDROM_AUDIO_PLAY:                 status = CD_PLAYING;                 break;            case CDROM_AUDIO_PAUSED:                 /* Workaround buggy CD-ROM drive */                 if (info.current_position.data_format == CDROM_LEADOUT)                 {                     status = CD_STOPPED;                 }                 else                 {                     status = CD_PAUSED;                 }                 break;            default:                 status = CD_ERROR;                 break;        }    }    if (position)    {       if (status==CD_PLAYING || (status==CD_PAUSED))       {           *position = MSF_TO_FRAMES(info.current_position.addr.msf.minute,                                     info.current_position.addr.msf.second,                                     info.current_position.addr.msf.frame);       }       else       {           *position = 0;       }    }    return (status);}/* Start play */static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length){    cdrom_playmsf_t playtime;    FRAMES_TO_MSF(start, &playtime.start_minute, &playtime.start_second, &playtime.start_frame);    FRAMES_TO_MSF(start+length, &playtime.end_minute, &playtime.end_second, &playtime.end_frame);    if (devctl(cdrom->id, DCMD_CAM_CDROMPLAYMSF, &playtime, sizeof(playtime), NULL) != 0)    {       return -1;    }    else    {       return 0;    }}/* Pause play */static int SDL_SYS_CDPause(SDL_CD *cdrom){    if (devctl(cdrom->id, DCMD_CAM_CDROMPAUSE, NULL, 0, NULL)!=0)    {       return -1;    }    else    {       return 0;    }}/* Resume play */static int SDL_SYS_CDResume(SDL_CD *cdrom){    if (devctl(cdrom->id, DCMD_CAM_CDROMRESUME, NULL, 0, NULL)!=0)    {       return -1;    }    else    {       return 0;    }}/* Stop play */static int SDL_SYS_CDStop(SDL_CD *cdrom){    if (devctl(cdrom->id, DCMD_CAM_CDROMSTOP, NULL, 0, NULL)!=0)    {       return -1;    }    else    {       return 0;    }}/* Eject the CD-ROM */static int SDL_SYS_CDEject(SDL_CD *cdrom){    if (devctl(cdrom->id, DCMD_CAM_EJECT_MEDIA, NULL, 0, NULL)!=0)    {       return -1;    }    else    {       return 0;    }}/* Close the CD-ROM handle */static void SDL_SYS_CDClose(SDL_CD *cdrom){    int i;    for (i=0; i<MAX_DRIVES; i++)    {       if (SDL_cdopen[i]==cdrom->id)       {           SDL_cdopen[i]=0;           break;       }    }    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_QNX */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -