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

流媒体/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.cc,v 1.2 2002/04/22 21:38:02 wmay Exp $";
  21. #endif
  22. /* Functions for system-level CD-ROM audio control on BeOS
  23.    (not completely implemented yet)
  24.  */
  25. #include <sys/types.h>
  26. #include <stdlib.h>
  27. #include <sys/stat.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <unistd.h>
  31. #include <scsi.h>
  32. #include <Directory.h>
  33. #include <Entry.h>
  34. #include <Path.h>
  35. #include "SDL_error.h"
  36. #include "SDL_cdrom.h"
  37. extern "C" {
  38. #include "SDL_syscdrom.h"
  39. }
  40. /* Constants to help us get at the SCSI table-of-contents info */
  41. #define CD_NUMTRACKS(toc) toc.toc_data[3]
  42. #define CD_TRACK(toc, track) (&toc.toc_data[6+(track)*8])
  43. #define CD_TRACK_N(toc, track) CD_TRACK(toc, track)[0]
  44. #define CD_TRACK_M(toc, track) CD_TRACK(toc, track)[3]
  45. #define CD_TRACK_S(toc, track) CD_TRACK(toc, track)[4]
  46. #define CD_TRACK_F(toc, track) CD_TRACK(toc, track)[5]
  47. /* Constants to help us get at the SCSI position info */
  48. #define POS_TRACK(pos) pos.position[6]
  49. #define POS_ABS_M(pos) pos.position[9]
  50. #define POS_ABS_S(pos) pos.position[10]
  51. #define POS_ABS_F(pos) pos.position[11]
  52. #define POS_REL_M(pos) pos.position[13]
  53. #define POS_REL_S(pos) pos.position[14]
  54. #define POS_REL_F(pos) pos.position[15]
  55. /* The maximum number of CD-ROM drives we'll detect */
  56. #define MAX_DRIVES 16
  57. /* A list of available CD-ROM drives */
  58. static char *SDL_cdlist[MAX_DRIVES];
  59. /* The system-dependent CD control functions */
  60. static const char *SDL_SYS_CDName(int drive);
  61. static int SDL_SYS_CDOpen(int drive);
  62. static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
  63. static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
  64. static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
  65. static int SDL_SYS_CDPause(SDL_CD *cdrom);
  66. static int SDL_SYS_CDResume(SDL_CD *cdrom);
  67. static int SDL_SYS_CDStop(SDL_CD *cdrom);
  68. static int SDL_SYS_CDEject(SDL_CD *cdrom);
  69. static void SDL_SYS_CDClose(SDL_CD *cdrom);
  70. int try_dir(const char *directory);
  71. /* Check a drive to see if it is a CD-ROM */
  72. static int CheckDrive(char *drive)
  73. {
  74. struct stat stbuf;
  75. int is_cd, cdfd;
  76. device_geometry info;
  77. /* If it doesn't exist, return -1 */
  78. if ( stat(drive, &stbuf) < 0 ) {
  79. return(-1);
  80. }
  81. /* If it does exist, verify that it's an available CD-ROM */
  82. is_cd = 0;
  83. cdfd = open(drive, 0);
  84. if ( cdfd >= 0 ) {
  85. if ( ioctl(cdfd, B_GET_GEOMETRY, &info) == B_NO_ERROR ) {
  86. if ( info.device_type == B_CD ) {
  87. is_cd = 1;
  88. }
  89. }
  90. close(cdfd);
  91. } else {
  92. /* This can happen when the drive is open .. (?) */;
  93. is_cd = 1;
  94. }
  95. return(is_cd);
  96. }
  97. /* Add a CD-ROM drive to our list of valid drives */
  98. static void AddDrive(char *drive)
  99. {
  100. int i;
  101. if ( SDL_numcds < MAX_DRIVES ) {
  102. /* Add this drive to our list */
  103. i = SDL_numcds;
  104. SDL_cdlist[i] = (char *)malloc(strlen(drive)+1);
  105. if ( SDL_cdlist[i] == NULL ) {
  106. SDL_OutOfMemory();
  107. return;
  108. }
  109. strcpy(SDL_cdlist[i], drive);
  110. ++SDL_numcds;
  111. #ifdef CDROM_DEBUG
  112.   fprintf(stderr, "Added CD-ROM drive: %sn", drive);
  113. #endif
  114. }
  115. }
  116. /* IDE bus scanning magic */
  117. enum {
  118. IDE_GET_DEVICES_INFO = B_DEVICE_OP_CODES_END + 50,
  119. };
  120. struct ide_ctrl_info {
  121. bool ide_0_present;
  122. bool ide_0_master_present;
  123. bool ide_0_slave_present;
  124. int ide_0_master_type;
  125. int ide_0_slave_type;
  126. bool ide_1_present;
  127. bool ide_1_master_present;
  128. bool ide_1_slave_present;
  129. int ide_1_master_type;
  130. int ide_1_slave_type;
  131. };
  132. int  SDL_SYS_CDInit(void)
  133. {
  134. char *SDLcdrom;
  135. int raw_fd;
  136. struct ide_ctrl_info info;
  137. /* Fill in our driver capabilities */
  138. SDL_CDcaps.Name = SDL_SYS_CDName;
  139. SDL_CDcaps.Open = SDL_SYS_CDOpen;
  140. SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
  141. SDL_CDcaps.Status = SDL_SYS_CDStatus;
  142. SDL_CDcaps.Play = SDL_SYS_CDPlay;
  143. SDL_CDcaps.Pause = SDL_SYS_CDPause;
  144. SDL_CDcaps.Resume = SDL_SYS_CDResume;
  145. SDL_CDcaps.Stop = SDL_SYS_CDStop;
  146. SDL_CDcaps.Eject = SDL_SYS_CDEject;
  147. SDL_CDcaps.Close = SDL_SYS_CDClose;
  148. /* Look in the environment for our CD-ROM drive list */
  149. SDLcdrom = getenv("SDL_CDROM"); /* ':' separated list of devices */
  150. if ( SDLcdrom != NULL ) {
  151. char *cdpath, *delim;
  152. cdpath = (char *)malloc(strlen(SDLcdrom)+1);
  153. if ( cdpath != NULL ) {
  154. strcpy(cdpath, SDLcdrom);
  155. SDLcdrom = cdpath;
  156. do {
  157. delim = strchr(SDLcdrom, ':');
  158. if ( delim ) {
  159. *delim++ = '';
  160. }
  161. if ( CheckDrive(SDLcdrom) > 0 ) {
  162. AddDrive(SDLcdrom);
  163. }
  164. if ( delim ) {
  165. SDLcdrom = delim;
  166. } else {
  167. SDLcdrom = NULL;
  168. }
  169. } while ( SDLcdrom );
  170. free(cdpath);
  171. }
  172. /* If we found our drives, there's nothing left to do */
  173. if ( SDL_numcds > 0 ) {
  174. return(0);
  175. }
  176. }
  177. /* Scan the system for CD-ROM drives */
  178. try_dir("/dev/disk");
  179. return 0;
  180. }
  181. int try_dir(const char *directory)
  182. BDirectory dir; 
  183. dir.SetTo(directory); 
  184. if(dir.InitCheck() != B_NO_ERROR) { 
  185. return false; 
  186. dir.Rewind(); 
  187. BEntry entry; 
  188. while(dir.GetNextEntry(&entry) >= 0) { 
  189. BPath path; 
  190. const char *name; 
  191. entry_ref e; 
  192. if(entry.GetPath(&path) != B_NO_ERROR) 
  193. continue; 
  194. name = path.Path(); 
  195. if(entry.GetRef(&e) != B_NO_ERROR) 
  196. continue; 
  197. if(entry.IsDirectory()) { 
  198. if(strcmp(e.name, "floppy") == 0) 
  199. continue; /* ignore floppy (it is not silent)  */
  200. int devfd = try_dir(name);
  201. if(devfd >= 0)
  202. return devfd;
  203. else { 
  204. int devfd; 
  205. device_geometry g; 
  206. if(strcmp(e.name, "raw") != 0) 
  207. continue; /* ignore partitions */
  208. devfd = open(name, O_RDONLY); 
  209. if(devfd < 0) 
  210. continue; 
  211. if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) {
  212. if(g.device_type == B_CD)
  213. {
  214. AddDrive(strdup(name));
  215. }
  216. }
  217. close(devfd);
  218. }
  219. return B_ERROR;
  220. }
  221. /* General ioctl() CD-ROM command function */
  222. static int SDL_SYS_CDioctl(int index, int command, void *arg)
  223. {
  224. int okay;
  225. int fd;
  226. okay = 0;
  227. fd = open(SDL_cdlist[index], 0);
  228. if ( fd >= 0 ) {
  229. if ( ioctl(fd, command, arg) == B_NO_ERROR ) {
  230. okay = 1;
  231. }
  232. close(fd);
  233. }
  234. return(okay ? 0 : -1);
  235. }
  236. static const char *SDL_SYS_CDName(int drive)
  237. {
  238. return(SDL_cdlist[drive]);
  239. static int SDL_SYS_CDOpen(int drive)
  240. {
  241. return(drive);
  242. }
  243. static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
  244. {
  245. int i;
  246. scsi_toc toc;
  247. if ( SDL_SYS_CDioctl(cdrom->id, B_SCSI_GET_TOC, &toc) == 0 ) {
  248. cdrom->numtracks = CD_NUMTRACKS(toc);
  249. if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
  250. cdrom->numtracks = SDL_MAX_TRACKS;
  251. }
  252. for ( i=0; i<=cdrom->numtracks; ++i ) {
  253. cdrom->track[i].id = CD_TRACK_N(toc, i);
  254. /* FIXME:  How do we tell on BeOS? */
  255. cdrom->track[i].type = SDL_AUDIO_TRACK;
  256. cdrom->track[i].offset = MSF_TO_FRAMES(
  257. CD_TRACK_M(toc, i),
  258. CD_TRACK_S(toc, i),
  259. CD_TRACK_F(toc, i));
  260. cdrom->track[i].length = 0;
  261. if ( i > 0 ) {
  262. cdrom->track[i-1].length =
  263. cdrom->track[i].offset-
  264. cdrom->track[i-1].offset;
  265. }
  266. }
  267. return(0);
  268. } else {
  269. return(-1);
  270. }
  271. }
  272. /* Get CD-ROM status */
  273. static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
  274. {
  275. CDstatus status;
  276. int fd;
  277. int cur_frame;
  278. scsi_position pos;
  279. fd = open(SDL_cdlist[cdrom->id], 0);
  280. cur_frame = 0;
  281. if ( fd >= 0 ) {
  282. if ( ioctl(fd, B_SCSI_GET_POSITION, &pos) == B_NO_ERROR ) {
  283. cur_frame = MSF_TO_FRAMES(
  284. POS_ABS_M(pos), POS_ABS_S(pos), POS_ABS_F(pos));
  285. }
  286. if ( ! pos.position[1] || (pos.position[1] >= 0x13) ||
  287. ((pos.position[1] == 0x12) && (!pos.position[6])) ) {
  288. status = CD_STOPPED;
  289. } else
  290. if ( pos.position[1] == 0x11 ) {
  291. status = CD_PLAYING;
  292. } else {
  293. status = CD_PAUSED;
  294. }
  295. close(fd);
  296. } else {
  297. status = CD_TRAYEMPTY;
  298. }
  299. if ( position ) {
  300. *position = cur_frame;
  301. }
  302. return(status);
  303. }
  304. /* Start play */
  305. static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
  306. {
  307. int okay;
  308. int fd;
  309. scsi_play_position pos;
  310. okay = 0;
  311. fd = open(SDL_cdlist[cdrom->id], 0);
  312. if ( fd >= 0 ) {
  313. FRAMES_TO_MSF(start, &pos.start_m, &pos.start_s, &pos.start_f);
  314. FRAMES_TO_MSF(start+length, &pos.end_m, &pos.end_s, &pos.end_f);
  315. if ( ioctl(fd, B_SCSI_PLAY_POSITION, &pos) == B_NO_ERROR ) {
  316. okay = 1;
  317. }
  318. close(fd);
  319. }
  320. return(okay ? 0 : -1);
  321. }
  322. /* Pause play */
  323. static int SDL_SYS_CDPause(SDL_CD *cdrom)
  324. {
  325. return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_PAUSE_AUDIO, 0));
  326. }
  327. /* Resume play */
  328. static int SDL_SYS_CDResume(SDL_CD *cdrom)
  329. {
  330. return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_RESUME_AUDIO, 0));
  331. }
  332. /* Stop play */
  333. static int SDL_SYS_CDStop(SDL_CD *cdrom)
  334. {
  335. return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_STOP_AUDIO, 0));
  336. }
  337. /* Eject the CD-ROM */
  338. static int SDL_SYS_CDEject(SDL_CD *cdrom)
  339. {
  340. return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_EJECT, 0));
  341. }
  342. /* Close the CD-ROM handle */
  343. static void SDL_SYS_CDClose(SDL_CD *cdrom)
  344. {
  345. close(cdrom->id);
  346. }
  347. void SDL_SYS_CDQuit(void)
  348. {
  349. int i;
  350. if ( SDL_numcds > 0 ) {
  351. for ( i=0; i<SDL_numcds; ++i ) {
  352. free(SDL_cdlist[i]);
  353. }
  354. SDL_numcds = 0;
  355. }
  356. }