📄 sdl_syscdrom.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_OS2/* Functions for system-level CD-ROM audio control */#define INCL_MCIOS2#include <os2.h>#include <os2me.h>#include "SDL_cdrom.h"#include "../SDL_syscdrom.h"/* Size of MCI result buffer (in bytes) */#define MCI_CMDRETBUFSIZE 128/* 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);/* MCI Timing Functions */#define MCI_MMTIMEPERSECOND 3000#define FRAMESFROMMM(mmtime) (((mmtime)*CD_FPS)/MCI_MMTIMEPERSECOND)/* Ready for MCI CDAudio Devices */int SDL_SYS_CDInit(void){int i; /* generig counter */MCI_SYSINFO_PARMS msp; /* Structure to MCI SysInfo parameters */CHAR SysInfoRet[MCI_CMDRETBUFSIZE]; /* Buffer for MCI Command result *//* 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;/* Get the number of CD ROMs in the System *//* Clean SysInfo structure */SDL_memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS));/* Prepare structure to Ask Numer of Audio CDs */msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);SDL_numcds = atoi(SysInfoRet);if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number *//* Get and Add their system name to the SDL_cdlist */msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */for (i=0; i<SDL_numcds; i++) { msp.ulNumber = i+1; mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_NAME | MCI_WAIT,&msp, 0); SDL_cdlist[i] = SDL_strdup(SysInfoRet); if ( SDL_cdlist[i] == NULL ) { SDL_OutOfMemory(); return(-1); } }return(0);}/* Return CDAudio System Dependent Device Name - Ready for MCI*/static const char *SDL_SYS_CDName(int drive){return(SDL_cdlist[drive]);}/* Open CDAudio Device - Ready for MCI */static int SDL_SYS_CDOpen(int drive){MCI_OPEN_PARMS mop;MCI_SET_PARMS msp;MCI_GENERIC_PARMS mgp;/* Open the device */mop.hwndCallback = (HWND)NULL; // Nonemop.usDeviceID = (USHORT)NULL; // Will be returned.mop.pszDeviceType = (PSZ)SDL_cdlist[drive]; // CDAudio Deviceif (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR);/* Set time format */msp.hwndCallback = (HWND)NULL; // Nonemsp.ulTimeFormat = MCI_FORMAT_MSF; // Minute : Second : Frame structuremsp.ulSpeedFormat = (ULONG)NULL; // No changemsp.ulAudio = (ULONG)NULL; // No Channelmsp.ulLevel = (ULONG)NULL; // No Volumemsp.ulOver = (ULONG)NULL; // No Delaymsp.ulItem = (ULONG)NULL; // No itemmsp.ulValue = (ULONG)NULL; // No value for item flagif (LOUSHORT(mciSendCommand(mop.usDeviceID,MCI_SET,MCI_WAIT | MCI_SET_TIME_FORMAT,&msp, 0)) == MCIERR_SUCCESS) return (mop.usDeviceID);/* Error setting time format? - Close opened device */mgp.hwndCallback = (HWND)NULL; // NonemciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0);return(CD_ERROR);}/* Get CD Table Of Contents - Ready for MCI */static int SDL_SYS_CDGetTOC(SDL_CD *cdrom){MCI_TOC_PARMS mtp;MCI_STATUS_PARMS msp;MCI_TOC_REC * mtr;INT i;/* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0;/* Get Number of Tracks */msp.hwndCallback = (HWND)NULL; /* None */msp.ulReturn = (ULONG)NULL; /* We want this information */msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS;msp.ulValue = (ULONG)NULL; /* No additional information */if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);cdrom->numtracks = msp.ulReturn;if ( cdrom->numtracks > SDL_MAX_TRACKS ) { cdrom->numtracks = SDL_MAX_TRACKS; }/* Alocate space for TOC data */mtr = (MCI_TOC_REC *)SDL_malloc(cdrom->numtracks*sizeof(MCI_TOC_REC));if ( mtr == NULL ) { SDL_OutOfMemory(); return(-1); }/* Get TOC from CD */mtp.pBuf = mtr;mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC);if (LOUSHORT(mciSendCommand(cdrom->id,MCI_GETTOC,MCI_WAIT,&mtp, 0)) != MCIERR_SUCCESS) { SDL_OutOfMemory(); SDL_free(mtr); return(CD_ERROR); }/* Fill SDL Tracks Structure */for (i=0; i<cdrom->numtracks; i++) { /* Set Track ID */ cdrom->track[i].id = (mtr+i)->TrackNum; /* Set Track Type */ msp.hwndCallback = (HWND)NULL; /* None */ msp.ulReturn = (ULONG)NULL; /* We want this information */ msp.ulItem = MCI_CD_STATUS_TRACK_TYPE; msp.ulValue = (ULONG)((mtr+i)->TrackNum); /* Track Number? */ if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_TRACK | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) { SDL_free(mtr); return (CD_ERROR); } if (msp.ulReturn==MCI_CD_TRACK_AUDIO) cdrom->track[i].type = SDL_AUDIO_TRACK; else cdrom->track[i].type = SDL_DATA_TRACK; /* Set Track Length - values from MCI are in MMTIMEs - 3000 MMTIME = 1 second */ cdrom->track[i].length = FRAMESFROMMM((mtr+i)->ulEndAddr - (mtr+i)->ulStartAddr); /* Set Track Offset */ cdrom->track[i].offset = FRAMESFROMMM((mtr+i)->ulStartAddr); }SDL_free(mtr);return(0);}/* Get CD-ROM status - Ready for MCI */static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position){CDstatus status;MCI_STATUS_PARMS msp;/* Get Status from MCI */msp.hwndCallback = (HWND)NULL; /* None */msp.ulReturn = (ULONG)NULL; /* We want this information */msp.ulItem = MCI_STATUS_MODE;msp.ulValue = (ULONG)NULL; /* No additional information */if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR;else { switch(msp.ulReturn) { case MCI_MODE_NOT_READY: status = CD_TRAYEMPTY; break; case MCI_MODE_PAUSE: status = CD_PAUSED; break; case MCI_MODE_PLAY: status = CD_PLAYING; break; case MCI_MODE_STOP: status = CD_STOPPED; break; /* These cases should not occour */ case MCI_MODE_RECORD: case MCI_MODE_SEEK: default: status = CD_ERROR; break; } }/* Determine position */if (position != NULL) /* The SDL $&$&%# CDROM call sends NULL pointer here! */ { if ((status == CD_PLAYING) || (status == CD_PAUSED)) { /* Get Position */ msp.hwndCallback = (HWND)NULL; /* None */ msp.ulReturn = (ULONG)NULL; /* We want this information */ msp.ulItem = MCI_STATUS_POSITION; msp.ulValue = (ULONG)NULL; /* No additiona info */ if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return (CD_ERROR); /* Convert from MSF (format selected in the Open process) to Frames (format that will be returned) */ *position = MSF_TO_FRAMES(MSF_MINUTE(msp.ulReturn),MSF_SECOND(msp.ulReturn),MSF_FRAME(msp.ulReturn)); } else *position = 0; }return(status);}/* Start play - Ready for MCI */static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length){MCI_GENERIC_PARMS mgp;MCI_STATUS_PARMS msp;MCI_PLAY_PARMS mpp;ULONG min,sec,frm;/* Start MSF */FRAMES_TO_MSF(start, &min, &sec, &frm);MSF_MINUTE(mpp.ulFrom) = min;MSF_SECOND(mpp.ulFrom) = sec;MSF_FRAME(mpp.ulFrom) = frm;/* End MSF */FRAMES_TO_MSF(start+length, &min, &sec, &frm);MSF_MINUTE(mpp.ulTo) = min;MSF_SECOND(mpp.ulTo) = sec;MSF_FRAME(mpp.ulTo) = frm;#ifdef DEBUG_CDROM fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);#endif/* Verifies if it is paused first... and if it is, unpause before stopping it. */msp.hwndCallback = (HWND)NULL; /* None */msp.ulReturn = (ULONG)NULL; /* We want this information */msp.ulItem = MCI_STATUS_MODE;msp.ulValue = (ULONG)NULL; /* No additional information */if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS) { if (msp.ulReturn == MCI_MODE_PAUSE) { mgp.hwndCallback = (HWND)NULL; // None mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0); } }/* Now play it. */mpp.hwndCallback = (HWND)NULL; // We do not want the info. tempif (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0;return (CD_ERROR);}/* Pause play - Ready for MCI */static int SDL_SYS_CDPause(SDL_CD *cdrom){MCI_GENERIC_PARMS mgp;mgp.hwndCallback = (HWND)NULL; // Noneif (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;return(CD_ERROR);}/* Resume play - Ready for MCI */static int SDL_SYS_CDResume(SDL_CD *cdrom){MCI_GENERIC_PARMS mgp;mgp.hwndCallback = (HWND)NULL; // Noneif (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;return(CD_ERROR);}/* Stop play - Ready for MCI */static int SDL_SYS_CDStop(SDL_CD *cdrom){MCI_GENERIC_PARMS mgp;MCI_STATUS_PARMS msp;/* Verifies if it is paused first... and if it is, unpause before stopping it. */msp.hwndCallback = (HWND)NULL; /* None */msp.ulReturn = (ULONG)NULL; /* We want this information */msp.ulItem = MCI_STATUS_MODE;msp.ulValue = (ULONG)NULL; /* No additional information */if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS) { if (msp.ulReturn == MCI_MODE_PAUSE) { mgp.hwndCallback = (HWND)NULL; // None mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0); } }/* Now stops the media */mgp.hwndCallback = (HWND)NULL; // Noneif (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;return(CD_ERROR);}/* Eject the CD-ROM - Ready for MCI */static int SDL_SYS_CDEject(SDL_CD *cdrom){MCI_SET_PARMS msp;msp.hwndCallback = (HWND)NULL; // Nonemsp.ulTimeFormat = (ULONG)NULL; // No changemsp.ulSpeedFormat = (ULONG)NULL; // No changemsp.ulAudio = (ULONG)NULL; // No Channelmsp.ulLevel = (ULONG)NULL; // No Volumemsp.ulOver = (ULONG)NULL; // No Delaymsp.ulItem = (ULONG)NULL; // No itemmsp.ulValue = (ULONG)NULL; // No value for item flagif (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0;return(CD_ERROR);}/* Close the CD-ROM handle - Ready for MCI */static void SDL_SYS_CDClose(SDL_CD *cdrom){MCI_GENERIC_PARMS mgp;mgp.hwndCallback = (HWND)NULL; // NonemciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0);}/* Finalize CDROM Subsystem - Ready for MCI */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_OS2 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -