SDL_syscdrom.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:16k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_syscdrom.c,v 1.4 2002/04/22 21:38:02 wmay Exp $";
  21. #endif
  22. /* MacOS functions for system-level CD-ROM audio control */
  23. #include <Devices.h>
  24. #include <Files.h>
  25. #include <LowMem.h> /* Use entry table macros, not functions in InterfaceLib  */
  26. #include "SDL_cdrom.h"
  27. #include "SDL_syscdrom.h"
  28. #include "SDL_syscdrom_c.h"
  29. /* Added by Matt Slot */
  30. #if !defined(LMGetUnitTableEntryCount)
  31.   #define LMGetUnitTableEntryCount()   *(short *)0x01D2
  32. #endif
  33. /* The maximum number of CD-ROM drives we'll detect */
  34. #define MAX_DRIVES 26
  35. /* A list of available CD-ROM drives */
  36. static long SDL_cdversion = 0;
  37. static struct {
  38. short dRefNum;
  39. short driveNum;
  40. long frames;
  41. char name[256];
  42. Boolean hasAudio;
  43. } SDL_cdlist[MAX_DRIVES];
  44. static StringPtr gDriverName = "p.AppleCD";
  45. /* The system-dependent CD control functions */
  46. static const char *SDL_SYS_CDName(int drive);
  47. static int SDL_SYS_CDOpen(int drive);
  48. static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
  49. static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
  50. static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
  51. static int SDL_SYS_CDPause(SDL_CD *cdrom);
  52. static int SDL_SYS_CDResume(SDL_CD *cdrom);
  53. static int SDL_SYS_CDStop(SDL_CD *cdrom);
  54. static int SDL_SYS_CDEject(SDL_CD *cdrom);
  55. static void SDL_SYS_CDClose(SDL_CD *cdrom);
  56. static short SDL_SYS_ShortToBCD(short value)
  57. {
  58. return((value % 10) + (value / 10) * 0x10); /* Convert value to BCD */
  59. }
  60. static short SDL_SYS_BCDToShort(short value)
  61. {
  62. return((value % 0x10) + (value / 0x10) * 10); /* Convert value from BCD */
  63. }
  64. int  SDL_SYS_CDInit(void)
  65. {
  66. SInt16 dRefNum = 0;
  67. SInt16 first, last;
  68. SDL_numcds = 0;
  69. /* Check that the software is available */
  70. if (Gestalt(kGestaltAudioCDSelector, &SDL_cdversion) || 
  71. !SDL_cdversion) return(0);
  72. /* Fill in our driver capabilities */
  73. SDL_CDcaps.Name = SDL_SYS_CDName;
  74. SDL_CDcaps.Open = SDL_SYS_CDOpen;
  75. SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
  76. SDL_CDcaps.Status = SDL_SYS_CDStatus;
  77. SDL_CDcaps.Play = SDL_SYS_CDPlay;
  78. SDL_CDcaps.Pause = SDL_SYS_CDPause;
  79. SDL_CDcaps.Resume = SDL_SYS_CDResume;
  80. SDL_CDcaps.Stop = SDL_SYS_CDStop;
  81. SDL_CDcaps.Eject = SDL_SYS_CDEject;
  82. SDL_CDcaps.Close = SDL_SYS_CDClose;
  83. /* Walk the list, count each AudioCD driver, and save the refnums */
  84. first = -1;
  85. last = 0 - LMGetUnitTableEntryCount();
  86. for(dRefNum = first; dRefNum >= last; dRefNum--) {
  87. Str255 driverName;
  88. StringPtr namePtr;
  89. DCtlHandle deviceEntry;
  90. deviceEntry = GetDCtlEntry(dRefNum);
  91. if (! deviceEntry) continue;
  92. /* Is this an .AppleCD ? */
  93. namePtr = (*deviceEntry)->dCtlFlags & (1L << dRAMBased) ?
  94. ((StringPtr) ((DCtlPtr) deviceEntry)->dCtlDriver + 18) :
  95. ((StringPtr) (*deviceEntry)->dCtlDriver + 18);
  96. BlockMoveData(namePtr, driverName, namePtr[0]+1);
  97. if (driverName[0] > gDriverName[0]) driverName[0] = gDriverName[0];
  98. if (! EqualString(driverName, gDriverName, false, false)) continue;
  99. /* Record the basic info for each drive */
  100. SDL_cdlist[SDL_numcds].dRefNum = dRefNum;
  101. BlockMoveData(namePtr + 1, SDL_cdlist[SDL_numcds].name, namePtr[0]);
  102. SDL_cdlist[SDL_numcds].name[namePtr[0]] = 0;
  103. SDL_cdlist[SDL_numcds].hasAudio = false;
  104. SDL_numcds++;
  105. }
  106. return(0);
  107. }
  108. static const char *SDL_SYS_CDName(int drive)
  109. {
  110. return(SDL_cdlist[drive].name);
  111. }
  112. static int get_drivenum(int drive)
  113. {
  114. QHdr *driveQ = GetDrvQHdr();
  115. DrvQEl *driveElem;
  116. /* Update the drive number */
  117. SDL_cdlist[drive].driveNum = 0;
  118. if ( driveQ->qTail ) {
  119. driveQ->qTail->qLink = 0;
  120. }
  121. for ( driveElem=(DrvQEl *)driveQ->qHead; driveElem;
  122.       driveElem = (DrvQEl *)driveElem->qLink ) {
  123. if ( driveElem->dQRefNum == SDL_cdlist[drive].dRefNum ) {
  124. SDL_cdlist[drive].driveNum = driveElem->dQDrive;
  125. break;
  126. }
  127. }
  128. return(SDL_cdlist[drive].driveNum);
  129. }
  130. static int SDL_SYS_CDOpen(int drive)
  131. {
  132. return(drive);
  133. }
  134. static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
  135. {
  136. CDCntrlParam cdpb;
  137. CDTrackData tracks[SDL_MAX_TRACKS];
  138. long i, leadout;
  139. /* Get the number of tracks on the CD by examining the TOC */
  140. memset(&cdpb, 0, sizeof(cdpb));
  141. cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
  142. cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
  143. cdpb.csCode = kReadTOC;
  144. cdpb.csParam.words[0] = kGetTrackRange;
  145. if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
  146. SDL_SetError("PBControlSync() failed");
  147. return(-1);
  148. }
  149. cdrom->numtracks = 
  150. SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - 
  151. SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1;
  152. if ( cdrom->numtracks > SDL_MAX_TRACKS )
  153. cdrom->numtracks = SDL_MAX_TRACKS;
  154. cdrom->status = CD_STOPPED;
  155. cdrom->cur_track = 0; /* Apparently these are set elsewhere */
  156. cdrom->cur_frame = 0; /* Apparently these are set elsewhere */
  157. /* Get the lead out area of the CD by examining the TOC */
  158. memset(&cdpb, 0, sizeof(cdpb));
  159. cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
  160. cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
  161. cdpb.csCode = kReadTOC;
  162. cdpb.csParam.words[0] = kGetLeadOutArea;
  163. if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
  164. SDL_SetError("PBControlSync() failed");
  165. return(-1);
  166. }
  167. leadout = MSF_TO_FRAMES(
  168. SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]),
  169. SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]),
  170. SDL_SYS_BCDToShort(cdpb.csParam.bytes[2]));
  171. /* Get an array of track locations by examining the TOC */
  172. memset(tracks, 0, sizeof(tracks));
  173. memset(&cdpb, 0, sizeof(cdpb));
  174. cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
  175. cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
  176. cdpb.csCode = kReadTOC;
  177. cdpb.csParam.words[0] = kGetTrackEntries; /* Type of Query */
  178. * ((long *) (cdpb.csParam.words+1)) = (long) tracks;
  179. cdpb.csParam.words[3] = cdrom->numtracks * sizeof(tracks[0]);
  180. * ((char *) (cdpb.csParam.words+4)) = 1; /* First track */
  181. if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
  182. SDL_SetError("PBControlSync() failed");
  183. return(-1);
  184. }
  185. /* Read all the track TOC entries */
  186. SDL_cdlist[cdrom->id].hasAudio = false;
  187. for ( i=0; i<cdrom->numtracks; ++i ) 
  188. {
  189. cdrom->track[i].id = i+1;
  190. if (tracks[i].entry.control & kDataTrackMask)
  191. cdrom->track[i].type = SDL_DATA_TRACK;
  192. else
  193. {
  194. cdrom->track[i].type = SDL_AUDIO_TRACK;
  195. SDL_cdlist[SDL_numcds].hasAudio = true;
  196. }
  197. cdrom->track[i].offset = MSF_TO_FRAMES(
  198. SDL_SYS_BCDToShort(tracks[i].entry.min),
  199. SDL_SYS_BCDToShort(tracks[i].entry.min),
  200. SDL_SYS_BCDToShort(tracks[i].entry.frame));
  201. cdrom->track[i].length = MSF_TO_FRAMES(
  202. SDL_SYS_BCDToShort(tracks[i+1].entry.min),
  203. SDL_SYS_BCDToShort(tracks[i+1].entry.min),
  204. SDL_SYS_BCDToShort(tracks[i+1].entry.frame)) -
  205. cdrom->track[i].offset;
  206. }
  207. /* Apparently SDL wants a fake last entry */
  208. cdrom->track[i].offset = leadout;
  209. cdrom->track[i].length = 0;
  210. return(0);
  211. }
  212. /* Get CD-ROM status */
  213. static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
  214. {
  215. CDCntrlParam cdpb;
  216. CDstatus status = CD_ERROR;
  217. Boolean spinning = false;
  218. if (position) *position = 0;
  219. /* Get the number of tracks on the CD by examining the TOC */
  220. if ( ! get_drivenum(cdrom->id) ) {
  221. return(CD_TRAYEMPTY);
  222. }
  223. memset(&cdpb, 0, sizeof(cdpb));
  224. cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
  225. cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
  226. cdpb.csCode = kReadTOC;
  227. cdpb.csParam.words[0] = kGetTrackRange;
  228. if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
  229. SDL_SetError("PBControlSync() failed");
  230. return(CD_ERROR);
  231. }
  232. cdrom->numtracks = 
  233. SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - 
  234. SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1;
  235. if ( cdrom->numtracks > SDL_MAX_TRACKS )
  236. cdrom->numtracks = SDL_MAX_TRACKS;
  237. cdrom->cur_track = 0; /* Apparently these are set elsewhere */
  238. cdrom->cur_frame = 0; /* Apparently these are set elsewhere */
  239. if (1 || SDL_cdlist[cdrom->id].hasAudio) {
  240. /* Get the current playback status */
  241. memset(&cdpb, 0, sizeof(cdpb));
  242. cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
  243. cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
  244. cdpb.csCode = kAudioStatus;
  245. if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
  246. SDL_SetError("PBControlSync() failed");
  247. return(-1);
  248. }
  249. switch(cdpb.csParam.cd.status) {
  250. case kStatusPlaying:
  251. status = CD_PLAYING;
  252. spinning = true;
  253. break;
  254. case kStatusPaused:
  255. status = CD_PAUSED;
  256. spinning = true;
  257. break;
  258. case kStatusMuted:
  259. status = CD_PLAYING; /* What should I do here? */
  260. spinning = true;
  261. break;
  262. case kStatusDone:
  263. status = CD_STOPPED;
  264. spinning = true;
  265. break;
  266. case kStatusStopped:
  267. status = CD_STOPPED;
  268. spinning = false;
  269. break;
  270. case kStatusError:
  271. default:
  272. status = CD_ERROR;
  273. spinning = false;
  274. break;
  275. }
  276. if (spinning && position) *position = MSF_TO_FRAMES(
  277. SDL_SYS_BCDToShort(cdpb.csParam.cd.minute),
  278. SDL_SYS_BCDToShort(cdpb.csParam.cd.second),
  279. SDL_SYS_BCDToShort(cdpb.csParam.cd.frame));
  280. }
  281. else
  282. status = CD_ERROR; /* What should I do here? */
  283. return(status);
  284. }
  285. /* Start play */
  286. static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
  287. {
  288. CDCntrlParam cdpb;
  289. /* Pause the current audio playback to avoid audible artifacts */
  290. if ( SDL_SYS_CDPause(cdrom) < 0 ) {
  291. return(-1);
  292. }
  293. /* Specify the AudioCD playback mode */
  294. memset(&cdpb, 0, sizeof(cdpb));
  295. cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
  296. cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
  297. cdpb.csCode = kSetPlayMode;
  298. cdpb.csParam.bytes[0] = false; /* Repeat? */
  299. cdpb.csParam.bytes[1] = kPlayModeSequential; /* Play mode */
  300. /* ゥナTreat as soft error, NEC Drive doesnt support this call ゥ