1 /* $NetBSD: pkgsrc/audio/xcdplayer/files/cdrom_freebsd.c,v 1.6 2005/12/11 20:48:46 joerg 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
17 static int c;
18
19 # include <stdio.h>
20 # include <sys/file.h>
21 # include <sys/types.h>
22 # include <sys/param.h>
23 # include <sys/stat.h>
24 # include <string.h>
25 # include <sys/time.h>
26
27 #include <sys/ioctl.h>
28 #include <sys/disklabel.h>
29 #include <sys/cdio.h>
30
31 # include "debug.h"
32 # include "cdrom_freebsd.h"
33 # include "app.h"
34
35 #ifdef __NetBSD__
36 static char cdrom[] = "/dev/rcd0d";
37 static char cdrom1[] = "/dev/rmcd0d";
38 #else
39 static char cdrom[] = "/dev/cd0c";
40 static char cdrom1[] = "/dev/mcd0c";
41 #endif
42
43 cdrom_info cdi;
44 char info_filename[256];
45 FILE *disc_info = NULL;
46
47 static int cdrom_fd = -1;
48
49 extern AppData app_data;
50
get_stored_info()51 get_stored_info()
52 {
53 int i,n;
54 char line[100];
55 char *title;
56
57 if(disc_info) {
58 fclose(disc_info);
59 disc_info = NULL;
60 }
61
62 if ( cdi.maxtrack == 0) {
63 return(0);
64 }
65 for (i = 0, n = 0; i < cdi.maxtrack; i++)
66 n = n + ((i+1) * cdi.times[i]);
67 n = n / cdi.maxtrack;
68
69 disc_title = NULL;
70 if (app_data.cdInfoDir != NULL)
71 sprintf(info_filename, "%s/cd.%d", app_data.cdInfoDir, n);
72 else
73 sprintf(info_filename, "cd.%d", n);
74
75 if ((disc_info = fopen(info_filename, "r")) != NULL)
76 {
77 fgets(line, 100, disc_info);
78 title = strchr(line, ':');
79 if (title != NULL)
80 {
81 *(strchr(title, '\n')) = '\0';
82 disc_title = strdup(title + 1);
83 }
84 fgets(line, 100, disc_info);
85 sscanf(line, "Program: %s", program_str);
86 }
87 else {
88 disc_title = strdup(NOTITLESTR);
89 program_str[0] = 0;
90 }
91 if (disc_title == NULL) {
92 disc_title = strdup(NOTITLESTR);
93 }
94 }
95
96 int
cdrom_open()97 cdrom_open() {
98 int n;
99 extern void update_title();
100
101 if (cdrom_fd != -1)
102 return(cdi.curtrack);
103
104 if (app_data.device != NULL) {
105 if ((cdrom_fd = open(app_data.device, O_RDONLY)) == -1) {
106 perror(app_data.device);
107 return(-1);
108 }
109 } else {
110 if ( (cdrom_fd = open(cdrom, O_RDONLY)) == -1
111 && (cdrom_fd = open(cdrom1, O_RDONLY)) == -1
112 ) {
113 perror("open: ");
114 return(-1);
115 }
116 }
117
118 if (cdrom_get_times() == -1) {
119 cdrom_close();
120 return(-1);
121 }
122
123 if ((n = cdrom_get_curtrack()) == -1)
124 return(-1);
125
126 get_stored_info();
127
128 update_title();
129
130 if (cdi.state & CDROM_STATE_PLAY)
131 cdi.curtrack = n;
132
133 if (cdi.state & CDROM_STATE_SHUFFLE)
134 shuffle_setup();
135
136 return(cdi.curtrack);
137 }
138
139 void
cdrom_close()140 cdrom_close() {
141 if (cdrom_fd == -1)
142 return;
143
144 if (cdi.times != NULL) {
145 free((char *) cdi.times);
146 free((char *) cdi.addrs);
147 cdi.times = NULL;
148 cdi.addrs = NULL;
149 }
150
151 (void) close(cdrom_fd);
152 cdrom_fd = -1;
153 }
154
155
156 int
cdrom_start()157 cdrom_start() {
158 if (cdrom_fd == -1)
159 return(-1);
160
161 if (ioctl(cdrom_fd, CDIOCSTART) == -1) {
162 perror("ioctl(cdromstart)");
163 return(-1);
164 }
165
166 return(0);
167 }
168
169 int
cdrom_stop()170 cdrom_stop() {
171 if (cdrom_fd == -1)
172 return(-1);
173
174 if (ioctl(cdrom_fd, CDIOCSTOP) == -1) {
175 perror("ioctl(cdromstop)");
176 return(-1);
177 }
178
179 return(0);
180 }
181
182 int
cdrom_eject()183 cdrom_eject() {
184 if (cdrom_fd == -1)
185 return(-1);
186
187 if (ioctl(cdrom_fd, CDIOCALLOW) == -1) {
188 perror("ioctl(cdromallow)");
189 return(-1);
190 }
191
192 if (ioctl(cdrom_fd, CDIOCEJECT) == -1) {
193 perror("ioctl(cdromeject)");
194 return(-1);
195 }
196
197 return(0);
198 }
199
200 int
cdrom_pause()201 cdrom_pause() {
202 if (cdrom_fd == -1)
203 return(-1);
204
205 if (ioctl(cdrom_fd, CDIOCPAUSE) == -1) {
206 perror("ioctl(cdrompause)");
207 return(-1);
208 }
209
210 return(0);
211 }
212
213 int
cdrom_resume()214 cdrom_resume() {
215 if (cdrom_fd == -1)
216 return(-1);
217
218 if (ioctl(cdrom_fd, CDIOCRESUME) == -1) {
219 perror("ioctl(cdromresume)");
220 return(-1);
221 }
222
223 return(0);
224 }
225
226 int
cdrom_volume(left_vol,right_vol)227 cdrom_volume(left_vol, right_vol)
228 int left_vol;
229 int right_vol;
230 {
231 struct ioc_vol vol;
232
233 if (cdrom_fd == -1)
234 return(-1);
235
236 vol.vol[0] = left_vol;
237 vol.vol[1] = right_vol;
238 vol.vol[2] = 0;
239 vol.vol[3] = 0;
240
241 if (ioctl(cdrom_fd, CDIOCSETVOL, &vol) == -1) {
242 perror("ioctl(cdromvolctrl)");
243 return(-1);
244 }
245
246 return(0);
247 }
248
249 int
cdrom_get_times()250 cdrom_get_times() {
251 struct ioc_toc_header tochdr;
252 extern unsigned short *ushort_malloc();
253 extern struct msf *msf_malloc();
254 unsigned long trk, trk_total, otime;
255 struct msf msf;
256
257 if (cdrom_read_tochdr(&tochdr) == -1)
258 return(-1);
259
260 cdi.mintrack = tochdr.starting_track;
261 cdi.maxtrack = tochdr.ending_track;
262
263 if (cdi.times != NULL)
264 {
265 free((char *) cdi.times);
266 free((char *) cdi.addrs);
267 cdi.times = NULL;
268 cdi.addrs = NULL;
269 }
270
271 cdi.times = ushort_malloc(cdi.maxtrack - cdi.mintrack + 1);
272 cdi.addrs = msf_malloc(cdi.maxtrack - cdi.mintrack + 2);
273
274 otime = 0;
275
276 for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
277 if (cdrom_get_msf(trk, &msf, &trk_total) == -1)
278 return(-1);
279
280 /* record start address for each track (track 1 starts at 0)*/
281 cdi.addrs[trk - cdi.mintrack] = msf;
282
283 trk_total -= otime;
284
285 /* use start time of next track as length of previous */
286 if (otime != 0)
287 {
288 cdi.times[trk - cdi.mintrack - 1] = trk_total;
289 }
290
291 otime += trk_total;
292
293 }
294
295 /* find start of leadout to get length of last track */
296 if (cdrom_get_msf(CDROM_LEADOUT, &msf, &trk_total) == -1)
297 return(-1);
298
299 /* recode leadout start address */
300 cdi.addrs[trk - cdi.mintrack] = msf;
301 trk_total -= otime;
302 otime += trk_total;
303
304 cdi.times[trk - cdi.mintrack - 1] = trk_total;
305 return(0);
306 }
307
308 int
cdrom_get_curtrack()309 cdrom_get_curtrack() {
310 struct cd_sub_channel_info data;
311
312 if (cdrom_read_subchannel(&data) == -1)
313 return(-1);
314
315 switch (data.header.audio_status) {
316 case CD_AS_AUDIO_INVALID:
317 return(-1);
318
319 /* playing track subchnl.cdsc_trk */
320 case CD_AS_PLAY_IN_PROGRESS:
321 return((int) data.what.position.track_number);
322
323 /* paused on track subchnl.cdsc_trk */
324 case CD_AS_PLAY_PAUSED:
325 return((int) data.what.position.track_number);
326
327 /* punt */
328 case CD_AS_PLAY_COMPLETED:
329 return(0);
330
331 case CD_AS_PLAY_ERROR:
332 return(-1);
333
334 /* punt */
335 case CD_AS_NO_STATUS:
336 debug_printf(1, "cdrom_get_curtrack: no status\n");
337 return(0);
338 }
339
340 /* bad value in cdsc_audiostatus */
341 return(-1);
342 }
343
344 int
cdrom_get_msf(track,msf,length)345 cdrom_get_msf(track, msf, length)
346 unsigned long track;
347 struct msf *msf;
348 unsigned long *length;
349 {
350 struct cd_toc_entry data;
351
352 if (cdrom_read_tocentry(track, &data, sizeof(data)) == -1)
353 return(-1);
354
355 msf->minute = data.addr.msf.minute;
356 msf->second = data.addr.msf.second;
357 msf->frame = data.addr.msf.frame;
358 *length = (((unsigned int) msf->minute) * 60) + (unsigned int) msf->second;
359 return(0);
360 }
361
362 int
cdrom_get_curmsf(msf)363 cdrom_get_curmsf(msf)
364 struct msf *msf;
365 {
366 struct cd_sub_channel_info data;
367
368 if (cdrom_read_subchannel(&data) == -1)
369 return(-1);
370
371 msf->minute = data.what.position.absaddr.msf.minute;
372 msf->second = data.what.position.absaddr.msf.second;
373 msf->frame = data.what.position.absaddr.msf.frame;
374 return (0);
375 }
376
377 int
cdrom_play_track(start_track,end_track)378 cdrom_play_track(start_track, end_track)
379 unsigned char start_track;
380 unsigned char end_track;
381 {
382 struct ioc_play_track ti;
383 struct ioc_play_msf play_addr;
384 char *addr;
385
386 if (cdrom_fd == -1)
387 return(-1);
388
389 play_addr.start_m = cdi.addrs[start_track - cdi.mintrack].minute;
390 play_addr.start_s = cdi.addrs[start_track - cdi.mintrack].second;
391 play_addr.start_f = cdi.addrs[start_track - cdi.mintrack].frame;
392 play_addr.end_m = cdi.addrs[end_track - cdi.mintrack + 1].minute;
393 play_addr.end_s = cdi.addrs[end_track - cdi.mintrack + 1].second;
394 play_addr.end_f = cdi.addrs[end_track - cdi.mintrack + 1].frame - 1;
395
396 if(play_addr.end_f >= 75) {
397 play_addr.end_f = 74;
398 play_addr.end_s--;
399 }
400 if(play_addr.end_s >= 60) {
401 play_addr.end_s = 59;
402 play_addr.end_m--;
403 }
404 addr = (char *)&play_addr;
405 if (ioctl(cdrom_fd, CDIOCPLAYMSF, &play_addr) == -1) {
406 perror("ioctl(cdromplaymsftrk)");
407 return(-1);
408 }
409
410 return(0);
411 }
412
413 int
cdrom_play_msf(start_msf,end_msf)414 cdrom_play_msf(start_msf, end_msf)
415 struct msf *start_msf;
416 struct msf *end_msf;
417 {
418 struct ioc_play_msf play_addr;
419
420 if (cdrom_fd == -1)
421 return(-1);
422
423 play_addr.start_m = start_msf->minute;
424 play_addr.start_s = start_msf->second;
425 play_addr.start_f = start_msf->frame;
426 play_addr.end_m = end_msf->minute;
427 play_addr.end_s = end_msf->second;
428 play_addr.end_f = end_msf->frame;
429
430 if (ioctl(cdrom_fd, CDIOCPLAYMSF, &play_addr) == -1) {
431 perror("ioctl(cdromplaymsf)");
432 return(-1);
433 }
434
435 return(0);
436 }
437
438
439 int
cdrom_read_subchannel(data)440 cdrom_read_subchannel(data)
441 struct cd_sub_channel_info *data;
442 {
443 struct ioc_read_subchannel subchnl;
444
445 if (cdrom_fd == -1)
446 return(-1);
447
448 subchnl.address_format = CD_MSF_FORMAT;
449 subchnl.data_format = CD_CURRENT_POSITION;
450 subchnl.data_len = /* sizeof(struct cd_sub_channel_info)*/ 16;
451 subchnl.track = 0;
452 subchnl.data = data;
453
454 if (ioctl(cdrom_fd, CDIOCREADSUBCHANNEL, (char *) &subchnl) == -1) {
455 fprintf(stderr, "ioctl(cdromsubchnl): ");
456 perror(cdrom);
457 return(-1);
458 }
459
460 return(0);
461 }
462
463 int
cdrom_read_track(track,data)464 cdrom_read_track(track, data)
465 unsigned int track;
466 struct cd_sub_channel_info *data;
467 {
468 struct ioc_read_subchannel subchnl;
469
470 if (cdrom_fd == -1)
471 return(-1);
472
473 subchnl.address_format = CD_MSF_FORMAT;
474 subchnl.data_format = CD_TRACK_INFO;
475 subchnl.data_len = /* sizeof(struct cd_sub_channel_info)*/ 24;
476 subchnl.track = track;
477 subchnl.data = data;
478
479 if (ioctl(cdrom_fd, CDIOCREADSUBCHANNEL, (char *) &subchnl) == -1) {
480 fprintf(stderr, "ioctl(cdromsubchnltrk): ");
481 perror(cdrom);
482 return(-1);
483 }
484
485 return(0);
486 }
487
488 int
cdrom_read_tocentry(track,data,size)489 cdrom_read_tocentry(track, data, size)
490 unsigned int track;
491 struct cd_toc_entry *data;
492 int size;
493 {
494 struct ioc_read_toc_entry tocentry;
495
496 if (cdrom_fd == -1)
497 return(-1);
498
499 tocentry.starting_track = (unsigned char)track;
500 tocentry.address_format = CD_MSF_FORMAT;
501 tocentry.data_len = /* sizeof(struct cd_toc_entry)*/ size;
502 tocentry.data = data;
503
504 if (ioctl(cdrom_fd, CDIOREADTOCENTRYS, (char *) &tocentry) == -1) {
505 perror("ioctl(cdromreadtocentry)");
506 return(-1);
507 }
508
509 return(0);
510 }
511
512 int
cdrom_read_tochdr(tochdr)513 cdrom_read_tochdr(tochdr)
514 struct ioc_toc_header *tochdr;
515 {
516 if (cdrom_fd == -1)
517 return(-1);
518
519 if (ioctl(cdrom_fd, CDIOREADTOCHEADER, (char *) tochdr) == -1) {
520 perror("ioctl(cdromreadtochdr): ");
521 return(-1);
522 }
523
524 return(0);
525 }
526
527 int
cdrom_status()528 cdrom_status() {
529 struct cd_sub_channel_info data;
530
531 if (cdrom_read_subchannel(&data) == -1)
532 return(-1);
533
534 switch (data.header.audio_status) {
535 case CD_AS_AUDIO_INVALID:
536 return(CDROM_INVALID);
537
538 case CD_AS_PLAY_IN_PROGRESS:
539 return(CDROM_PLAYING);
540
541 case CD_AS_PLAY_PAUSED:
542 return(CDROM_PAUSED);
543
544 case CD_AS_PLAY_COMPLETED:
545 return(CDROM_COMPLETED);
546
547 case CD_AS_PLAY_ERROR:
548 return(CDROM_ERROR);
549
550 case CD_AS_NO_STATUS:
551 return(CDROM_NO_STATUS);
552 }
553
554 return(-1);
555 }
556
557 unsigned short *
ushort_malloc(n)558 ushort_malloc(n)
559 int n;
560 {
561 extern char *calloc();
562 unsigned short *ptr;
563
564 ptr = (unsigned short *) calloc(n, sizeof(unsigned short));
565 if (ptr == NULL) {
566 perror("calloc");
567 exit(1);
568 }
569
570 return(ptr);
571 }
572
573 struct msf *
msf_malloc(n)574 msf_malloc(n)
575 int n;
576 {
577 extern char *calloc();
578 struct msf *ptr;
579
580 ptr = (struct msf *) calloc(n, sizeof(struct msf));
581 if (ptr == NULL) {
582 perror("calloc");
583 exit(1);
584 }
585
586 return(ptr);
587 }
588
589 int
cdrom_disp_cdi()590 cdrom_disp_cdi() {
591 int trk;
592
593 fprintf(stderr,"CDI structure:\n");
594 fprintf(stderr,"\tcurtrack: %d\n",cdi.curtrack);
595 fprintf(stderr,"\tmin: %d max: %d total: %d\n",
596 cdi.mintrack, cdi.maxtrack, cdi.ntracks);
597 fprintf(stderr,"\tdur: %d state: %2x\n",cdi.duration, cdi.state);
598 fprintf(stderr,"\tcurrand: %d lastprog: %d\n",
599 cdi.currand, cdi.lastprog);
600 fprintf(stderr,"\n\tTracklist:\n");
601 if (cdi.maxtrack != cdi.mintrack) {
602 for (trk=0; trk<=cdi.maxtrack-cdi.mintrack+1; trk++) {
603 fprintf(stderr,"\t%3d: %d %02d:%02d %d\n",trk,cdi.times[trk],
604 cdi.addrs[trk].minute,cdi.addrs[trk].second,
605 cdi.addrs[trk].frame);
606 }
607 }
608 }
609