cdrom_freebsd.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. /* $OpenBSD: cdrom_freebsd.c,v 1.3 2010/05/17 08:31:11 espie Exp $ */
  2. /*
  3. * Copyright (C) 1990 Regents of the University of California.
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and
  6. * its documentation for any purpose is hereby granted without fee,
  7. * provided that the above copyright notice appear in all copies and that
  8. * both that copyright notice and this permission notice appear in
  9. * supporting documentation, and that the name of the University of
  10. * California not be used in advertising or publicity pertaining to
  11. * distribution of the software without specific, written prior
  12. * permission. the University of California makes no representations
  13. * about the suitability of this software for any purpose. It is provided
  14. * "as is" without express or implied warranty.
  15. */
  16. static int c;
  17. # include <stdio.h>
  18. # include <stdlib.h>
  19. # include <sys/file.h>
  20. # include <sys/types.h>
  21. # include <sys/param.h>
  22. # include <sys/stat.h>
  23. # include <string.h>
  24. # include <sys/buf.h>
  25. # include <sys/time.h>
  26. #include <sys/ioctl.h>
  27. #include <sys/disklabel.h>
  28. #include <sys/cdio.h>
  29. # include "debug.h"
  30. # include "cdrom_freebsd.h"
  31. # include "app.h"
  32. extern char *device;
  33. static char cdrom[] = "/dev/rcd0c";
  34. static char cdrom1[] = "/dev/rmcd0c";
  35. cdrom_info cdi;
  36. char info_filename[256];
  37. FILE *disc_info = NULL;
  38. static int cdrom_fd = -1;
  39. extern AppData app_data;
  40. get_stored_info()
  41. {
  42. int i,n;
  43. char line[100];
  44. char *title;
  45. if(disc_info) {
  46. fclose(disc_info);
  47. disc_info = NULL;
  48. }
  49. if ( cdi.maxtrack == 0) {
  50. return(0);
  51. }
  52. for (i = 0, n = 0; i < cdi.maxtrack; i++)
  53. n = n + ((i+1) * cdi.times[i]);
  54. n = n / cdi.maxtrack;
  55. disc_title = NULL;
  56. if (app_data.cdInfoDir != NULL)
  57. sprintf(info_filename, "%s/cd.%d", app_data.cdInfoDir, n);
  58. else
  59. sprintf(info_filename, "cd.%d", n);
  60. if ((disc_info = fopen(info_filename, "r")) != NULL)
  61. {
  62. fgets(line, 100, disc_info);
  63. title = strchr(line, ':');
  64. if (title != NULL)
  65. {
  66. *(strchr(title, '\n')) = '\0';
  67. disc_title = strdup(title + 1);
  68. }
  69. fgets(line, 100, disc_info);
  70. sscanf(line, "Program: %s", program_str);
  71. }
  72. else {
  73. disc_title = strdup(NOTITLESTR);
  74. program_str[0] = 0;
  75. }
  76. if (disc_title == NULL) {
  77. disc_title = strdup(NOTITLESTR);
  78. }
  79. }
  80. int
  81. cdrom_open() {
  82. int n;
  83. extern void update_title();
  84. if (cdrom_fd != -1)
  85. return(cdi.curtrack);
  86. if (app_data.device != NULL) {
  87. if ((cdrom_fd = open(app_data.device, O_RDONLY)) == -1) {
  88. perror(app_data.device);
  89. return(-1);
  90. }
  91. } else {
  92. if ( (cdrom_fd = open(cdrom, O_RDONLY)) == -1
  93. && (cdrom_fd = open(cdrom1, O_RDONLY)) == -1
  94. ) {
  95. perror("open: ");
  96. return(-1);
  97. }
  98. }
  99. if (cdrom_get_times() == -1) {
  100. cdrom_close();
  101. return(-1);
  102. }
  103. if ((n = cdrom_get_curtrack()) == -1)
  104. return(-1);
  105. get_stored_info();
  106. update_title();
  107. if (cdi.state & CDROM_STATE_PLAY)
  108. cdi.curtrack = n;
  109. if (cdi.state & CDROM_STATE_SHUFFLE)
  110. shuffle_setup();
  111. return(cdi.curtrack);
  112. }
  113. void
  114. cdrom_close() {
  115. if (cdrom_fd == -1)
  116. return;
  117. if (cdi.times != NULL) {
  118. free((char *) cdi.times);
  119. free((char *) cdi.addrs);
  120. cdi.times = NULL;
  121. cdi.addrs = NULL;
  122. }
  123. (void) close(cdrom_fd);
  124. cdrom_fd = -1;
  125. }
  126. int
  127. cdrom_start() {
  128. if (cdrom_fd == -1)
  129. return(-1);
  130. if (ioctl(cdrom_fd, CDIOCSTART) == -1) {
  131. perror("ioctl(cdromstart)");
  132. return(-1);
  133. }
  134. return(0);
  135. }
  136. int
  137. cdrom_stop() {
  138. if (cdrom_fd == -1)
  139. return(-1);
  140. if (ioctl(cdrom_fd, CDIOCSTOP) == -1) {
  141. perror("ioctl(cdromstop)");
  142. return(-1);
  143. }
  144. return(0);
  145. }
  146. int
  147. cdrom_eject() {
  148. if (cdrom_fd == -1)
  149. return(-1);
  150. if (ioctl(cdrom_fd, CDIOCALLOW) == -1) {
  151. perror("ioctl(cdromallow)");
  152. return(-1);
  153. }
  154. if (ioctl(cdrom_fd, CDIOCEJECT) == -1) {
  155. perror("ioctl(cdromeject)");
  156. return(-1);
  157. }
  158. return(0);
  159. }
  160. int
  161. cdrom_pause() {
  162. if (cdrom_fd == -1)
  163. return(-1);
  164. if (ioctl(cdrom_fd, CDIOCPAUSE) == -1) {
  165. perror("ioctl(cdrompause)");
  166. return(-1);
  167. }
  168. return(0);
  169. }
  170. int
  171. cdrom_resume() {
  172. if (cdrom_fd == -1)
  173. return(-1);
  174. if (ioctl(cdrom_fd, CDIOCRESUME) == -1) {
  175. perror("ioctl(cdromresume)");
  176. return(-1);
  177. }
  178. return(0);
  179. }
  180. int
  181. cdrom_volume(left_vol, right_vol)
  182. int left_vol;
  183. int right_vol;
  184. {
  185. struct ioc_vol vol;
  186. if (cdrom_fd == -1)
  187. return(-1);
  188. vol.vol[0] = left_vol;
  189. vol.vol[1] = right_vol;
  190. vol.vol[2] = 0;
  191. vol.vol[3] = 0;
  192. if (ioctl(cdrom_fd, CDIOCSETVOL, &vol) == -1) {
  193. perror("ioctl(cdromvolctrl)");
  194. return(-1);
  195. }
  196. return(0);
  197. }
  198. int
  199. cdrom_get_times() {
  200. struct ioc_toc_header tochdr;
  201. extern unsigned short *ushort_malloc();
  202. extern struct msf *msf_malloc();
  203. unsigned long trk, trk_total, otime;
  204. struct msf msf;
  205. if (cdrom_read_tochdr(&tochdr) == -1)
  206. return(-1);
  207. cdi.mintrack = tochdr.starting_track;
  208. cdi.maxtrack = tochdr.ending_track;
  209. if (cdi.times != NULL)
  210. {
  211. free((char *) cdi.times);
  212. free((char *) cdi.addrs);
  213. cdi.times = NULL;
  214. cdi.addrs = NULL;
  215. }
  216. cdi.times = ushort_malloc(cdi.maxtrack - cdi.mintrack + 1);
  217. cdi.addrs = msf_malloc(cdi.maxtrack - cdi.mintrack + 2);
  218. otime = 0;
  219. for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
  220. if (cdrom_get_msf(trk, &msf, &trk_total) == -1)
  221. return(-1);
  222. /* record start address for each track (track 1 starts at 0)*/
  223. cdi.addrs[trk - cdi.mintrack] = msf;
  224. trk_total -= otime;
  225. /* use start time of next track as length of previous */
  226. if (otime != 0)
  227. {
  228. cdi.times[trk - cdi.mintrack - 1] = trk_total;
  229. }
  230. otime += trk_total;
  231. }
  232. /* find start of leadout to get length of last track */
  233. if (cdrom_get_msf(CDROM_LEADOUT, &msf, &trk_total) == -1)
  234. return(-1);
  235. /* recode leadout start address */
  236. cdi.addrs[trk - cdi.mintrack] = msf;
  237. trk_total -= otime;
  238. otime += trk_total;
  239. cdi.times[trk - cdi.mintrack - 1] = trk_total;
  240. return(0);
  241. }
  242. int
  243. cdrom_get_curtrack() {
  244. struct cd_sub_channel_info data;
  245. if (cdrom_read_subchannel(&data) == -1)
  246. return(-1);
  247. switch (data.header.audio_status) {
  248. case CD_AS_AUDIO_INVALID:
  249. return(-1);
  250. /* playing track subchnl.cdsc_trk */
  251. case CD_AS_PLAY_IN_PROGRESS:
  252. return((int) data.what.position.track_number);
  253. /* paused on track subchnl.cdsc_trk */
  254. case CD_AS_PLAY_PAUSED:
  255. return((int) data.what.position.track_number);
  256. /* punt */
  257. case CD_AS_PLAY_COMPLETED:
  258. return(0);
  259. case CD_AS_PLAY_ERROR:
  260. return(-1);
  261. /* punt */
  262. case CD_AS_NO_STATUS:
  263. debug_printf(1, "cdrom_get_curtrack: no status\n");
  264. return(0);
  265. }
  266. /* bad value in cdsc_audiostatus */
  267. return(-1);
  268. }
  269. int
  270. cdrom_get_msf(track, msf, length)
  271. unsigned long track;
  272. struct msf *msf;
  273. unsigned long *length;
  274. {
  275. struct cd_toc_entry data;
  276. if (cdrom_read_tocentry(track, &data, sizeof(data)) == -1)
  277. return(-1);
  278. msf->minute = data.addr.msf.minute;
  279. msf->second = data.addr.msf.second;
  280. msf->frame = data.addr.msf.frame;
  281. *length = (((unsigned int) msf->minute) * 60) + (unsigned int) msf->second;
  282. return(0);
  283. }
  284. int
  285. cdrom_get_curmsf(msf)
  286. struct msf *msf;
  287. {
  288. struct cd_sub_channel_info data;
  289. if (cdrom_read_subchannel(&data) == -1)
  290. return(-1);
  291. msf->minute = data.what.position.absaddr.msf.minute;
  292. msf->second = data.what.position.absaddr.msf.second;
  293. msf->frame = data.what.position.absaddr.msf.frame;
  294. return (0);
  295. }
  296. int
  297. cdrom_play_track(start_track, end_track)
  298. unsigned char start_track;
  299. unsigned char end_track;
  300. {
  301. struct ioc_play_track ti;
  302. struct ioc_play_msf play_addr;
  303. char *addr;
  304. if (cdrom_fd == -1)
  305. return(-1);
  306. play_addr.start_m = cdi.addrs[start_track - cdi.mintrack].minute;
  307. play_addr.start_s = cdi.addrs[start_track - cdi.mintrack].second;
  308. play_addr.start_f = cdi.addrs[start_track - cdi.mintrack].frame;
  309. play_addr.end_m = cdi.addrs[end_track - cdi.mintrack + 1].minute;
  310. play_addr.end_s = cdi.addrs[end_track - cdi.mintrack + 1].second;
  311. play_addr.end_f = cdi.addrs[end_track - cdi.mintrack + 1].frame - 1;
  312. if(play_addr.end_f >= 75) {
  313. play_addr.end_f = 74;
  314. play_addr.end_s--;
  315. }
  316. if(play_addr.end_s >= 60) {
  317. play_addr.end_s = 59;
  318. play_addr.end_m--;
  319. }
  320. addr = (char *)&play_addr;
  321. if (ioctl(cdrom_fd, CDIOCPLAYMSF, &play_addr) == -1) {
  322. perror("ioctl(cdromplaymsftrk)");
  323. return(-1);
  324. }
  325. return(0);
  326. }
  327. int
  328. cdrom_play_msf(start_msf, end_msf)
  329. struct msf *start_msf;
  330. struct msf *end_msf;
  331. {
  332. struct ioc_play_msf play_addr;
  333. if (cdrom_fd == -1)
  334. return(-1);
  335. play_addr.start_m = start_msf->minute;
  336. play_addr.start_s = start_msf->second;
  337. play_addr.start_f = start_msf->frame;
  338. play_addr.end_m = end_msf->minute;
  339. play_addr.end_s = end_msf->second;
  340. play_addr.end_f = end_msf->frame;
  341. if (ioctl(cdrom_fd, CDIOCPLAYMSF, &play_addr) == -1) {
  342. perror("ioctl(cdromplaymsf)");
  343. return(-1);
  344. }
  345. return(0);
  346. }
  347. int
  348. cdrom_read_subchannel(data)
  349. struct cd_sub_channel_info *data;
  350. {
  351. struct ioc_read_subchannel subchnl;
  352. if (cdrom_fd == -1)
  353. return(-1);
  354. subchnl.address_format = CD_MSF_FORMAT;
  355. subchnl.data_format = CD_CURRENT_POSITION;
  356. subchnl.data_len = /* sizeof(struct cd_sub_channel_info)*/ 16;
  357. subchnl.track = 0;
  358. subchnl.data = data;
  359. if (ioctl(cdrom_fd, CDIOCREADSUBCHANNEL, (char *) &subchnl) == -1) {
  360. fprintf(stderr, "ioctl(cdromsubchnl): ");
  361. perror(cdrom);
  362. return(-1);
  363. }
  364. return(0);
  365. }
  366. int
  367. cdrom_read_track(track, data)
  368. unsigned int track;
  369. struct cd_sub_channel_info *data;
  370. {
  371. struct ioc_read_subchannel subchnl;
  372. if (cdrom_fd == -1)
  373. return(-1);
  374. subchnl.address_format = CD_MSF_FORMAT;
  375. subchnl.data_format = CD_TRACK_INFO;
  376. subchnl.data_len = /* sizeof(struct cd_sub_channel_info)*/ 24;
  377. subchnl.track = track;
  378. subchnl.data = data;
  379. if (ioctl(cdrom_fd, CDIOCREADSUBCHANNEL, (char *) &subchnl) == -1) {
  380. fprintf(stderr, "ioctl(cdromsubchnltrk): ");
  381. perror(cdrom);
  382. return(-1);
  383. }
  384. return(0);
  385. }
  386. int
  387. cdrom_read_tocentry(track, data, size)
  388. unsigned int track;
  389. struct cd_toc_entry *data;
  390. int size;
  391. {
  392. struct ioc_read_toc_entry tocentry;
  393. if (cdrom_fd == -1)
  394. return(-1);
  395. tocentry.starting_track = (unsigned char)track;
  396. tocentry.address_format = CD_MSF_FORMAT;
  397. tocentry.data_len = /* sizeof(struct cd_toc_entry)*/ size;
  398. tocentry.data = data;
  399. if (ioctl(cdrom_fd, CDIOREADTOCENTRYS, (char *) &tocentry) == -1) {
  400. perror("ioctl(cdromreadtocentry)");
  401. return(-1);
  402. }
  403. return(0);
  404. }
  405. int
  406. cdrom_read_tochdr(tochdr)
  407. struct ioc_toc_header *tochdr;
  408. {
  409. if (cdrom_fd == -1)
  410. return(-1);
  411. if (ioctl(cdrom_fd, CDIOREADTOCHEADER, (char *) tochdr) == -1) {
  412. perror("ioctl(cdromreadtochdr): ");
  413. return(-1);
  414. }
  415. return(0);
  416. }
  417. int
  418. cdrom_status() {
  419. struct cd_sub_channel_info data;
  420. if (cdrom_read_subchannel(&data) == -1)
  421. return(-1);
  422. switch (data.header.audio_status) {
  423. case CD_AS_AUDIO_INVALID:
  424. return(CDROM_INVALID);
  425. case CD_AS_PLAY_IN_PROGRESS:
  426. return(CDROM_PLAYING);
  427. case CD_AS_PLAY_PAUSED:
  428. return(CDROM_PAUSED);
  429. case CD_AS_PLAY_COMPLETED:
  430. return(CDROM_COMPLETED);
  431. case CD_AS_PLAY_ERROR:
  432. return(CDROM_ERROR);
  433. case CD_AS_NO_STATUS:
  434. return(CDROM_NO_STATUS);
  435. }
  436. return(-1);
  437. }
  438. unsigned short *
  439. ushort_malloc(n)
  440. int n;
  441. {
  442. unsigned short *ptr;
  443. ptr = (unsigned short *) calloc(n, sizeof(unsigned short));
  444. if (ptr == NULL) {
  445. perror("calloc");
  446. exit(1);
  447. }
  448. return(ptr);
  449. }
  450. struct msf *
  451. msf_malloc(n)
  452. int n;
  453. {
  454. struct msf *ptr;
  455. ptr = (struct msf *) calloc(n, sizeof(struct msf));
  456. if (ptr == NULL) {
  457. perror("calloc");
  458. exit(1);
  459. }
  460. return(ptr);
  461. }
  462. int
  463. cdrom_disp_cdi() {
  464. int trk;
  465. fprintf(stderr,"CDI structure:\n");
  466. fprintf(stderr,"\tcurtrack: %d\n",cdi.curtrack);
  467. fprintf(stderr,"\tmin: %d max: %d total: %d\n",
  468. cdi.mintrack, cdi.maxtrack, cdi.ntracks);
  469. fprintf(stderr,"\tdur: %d state: %2x\n",cdi.duration, cdi.state);
  470. fprintf(stderr,"\tcurrand: %d lastprog: %d\n",
  471. cdi.currand, cdi.lastprog);
  472. fprintf(stderr,"\n\tTracklist:\n");
  473. if (cdi.maxtrack != cdi.mintrack) {
  474. for (trk=0; trk<=cdi.maxtrack-cdi.mintrack+1; trk++) {
  475. fprintf(stderr,"\t%3d: %d %02d:%02d %d\n",trk,cdi.times[trk],
  476. cdi.addrs[trk].minute,cdi.addrs[trk].second,
  477. cdi.addrs[trk].frame);
  478. }
  479. }
  480. }