1 /*
2  * Copyright (C) 1990 Regents of the University of California.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee,
6  * provided that the above copyright notice appear in all copies and that
7  * both that copyright notice and this permission notice appear in
8  * supporting documentation, and that the name of the University of
9  * California not be used in advertising or publicity pertaining to
10  * distribution of the software without specific, written prior
11  * permission.  the University of California makes no representations
12  * about the suitability of this software for any purpose.  It is provided
13  * "as is" without express or implied warranty.
14  */
15 
16 static int c;
17 
18 # if defined(sgi)
19 # include <stdio.h>
20 
21 # include <sys/file.h>
22 # include <sys/types.h>
23 # include <sys/param.h>
24 # include <sys/stat.h>
25 
26 # include <mntent.h>
27 # include <string.h>
28 # include <signal.h>
29 
30 # include <sys/buf.h>
31 
32 # include <sys/time.h>
33 
34 /* We need shared memory for the counter display if using scsi_audio */
35 #include <sys/ipc.h>
36 #include <sys/shm.h>
37 int		shmid;
38 key_t		shmkey;
39 
40 
41 # include "debug.h"
42 # include "cdrom_sgi.h"
43 
44 extern char	*device;
45 # if defined(notdef)
46 extern void	cdrom_print_toc();
47 # endif /* defined(notdef) */
48 
49 void		cdrom_audio_close();
50 void		cdrom_callback();
51 void		cdrom_kill_child();
52 int		cdrom_child_setup();
53 void		cdrom_child_pause();
54 void		cdrom_child_died();
55 void		cdrom_child_quit();
56 
57 #define INIT_READ	200	/* Maximum number we can play */
58 #define ONE_SECOND	75	/* One second of data */
59 
60 cdrom_info		cdi;
61 struct _cdrom_shmem	*cdrom_shmem;
62 char			info_filename[256];
63 FILE			*disc_info = NULL;
64 
65 CDPLAYER	*cdrom_fd = NULL;
66 ALport		audio_fd = NULL;
67 long		audio_param[6];
68 CDFRAME		*cd_audio_buff = NULL;
69 CDPARSER	*cd_parser = NULL;
70 int		cdrom_audio_opened = 0;
71 
get_stored_info()72 get_stored_info()
73 {
74 	int i,n;
75 	char	line[100];
76 	char	*title;
77 
78 	if ( cdi.maxtrack == 0) {
79 		return(0);
80 	}
81 	for (i = 0, n = 0; i < cdi.maxtrack; i++)
82 	    n = n + ((i+1) * cdi.times[i]);
83 	n = n / cdi.maxtrack;
84 
85 	disc_title = NULL;
86 	if (cdInfoDir != NULL)
87 	    sprintf(info_filename, "%s/cd.%d", cdInfoDir, n);
88 	else
89 	    sprintf(info_filename, "cd.%d", n);
90 
91 	if ((disc_info = fopen(info_filename, "r")) != NULL)
92 	{
93 	    fgets(line, 100, disc_info);
94 	    title = strchr(line, ':');
95 	    if (title != NULL)
96 	    {
97 	    	*(strchr(title, '\n')) = '\0';
98 	        disc_title = strdup(title + 1);
99 	    }
100 	    fgets(line, 100, disc_info);
101 	    sscanf(line, "Program: %s", program_str);
102 	}
103 	if (disc_title == NULL) {
104 		disc_title = NOTITLESTR;
105 	}
106 }
107 
108 int
cdrom_open()109 cdrom_open() {
110 	int		n;
111 	CDSTATUS	cdrom_stat;
112 	extern void update_title();
113 
114 	if (cdrom_fd != NULL) {
115 		return(cdi.curtrack);
116 	}
117 
118 	if (device != NULL) {
119 		fprintf(stderr,"Device: %s\n",device);
120 		if ((cdrom_fd = CDopen(device, "r")) == NULL) {
121 			fprintf(stderr, "open cdrom: %s",device);
122 			perror("CDopen");
123 			return(-1);
124 		}
125 	} else {
126 		if ((cdrom_fd = CDopen(0, "r")) == NULL) {
127 			fprintf(stderr, "open cdrom: ");
128 			perror("CDopen");
129 			return(-1);
130 		}
131 	}
132 
133 	if (cdrom_get_times() == -1) {
134 		cdrom_close();
135 		return(-1);
136 	}
137 
138 	if ((n = cdrom_get_curtrack()) == -1)
139 		return(-1);
140 
141 	get_stored_info();
142 
143 	update_title();
144 
145 	if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
146 		fprintf(stderr, "CDgetstatus(cdrom_stat): ");
147 		perror("CDgetstatus");
148 		return(-1);
149 	}
150 	if ((cdrom_stat.state == CD_PLAYING) ||
151 	    (cdrom_stat.state == CD_PAUSED)) {
152 		cdi.scsi_audio = 0;
153 	} else {
154 		cdi.scsi_audio = cdrom_audio_avail();
155 	}
156 
157 	if (cdi.scsi_audio) {
158 		if (cd_audio_buff == (CDFRAME *) NULL) {
159 			if ((cd_audio_buff =
160 			     (CDFRAME *) malloc(INIT_READ * CDDA_BLOCKSIZE)) == NULL) {
161 				fprintf(stderr,"cdrom_open: cannot allocate cd digital data buffer!\n");
162 				perror("cdrom_open");
163 				cdi.scsi_audio = 0;
164 			}
165 		}
166 		if (cd_parser == NULL) {
167 			if ((cd_parser = CDcreateparser()) == NULL) {
168 				fprintf(stderr,"cdrom_open: CDcreateparser failed!\n");
169 				perror("cdrom_open");
170 				cdi.scsi_audio = 0;
171 			}
172 			CDresetparser(cd_parser);
173 			CDsetcallback(cd_parser, cd_audio, cdrom_callback, 0);
174 			CDsetcallback(cd_parser, cd_pnum, cdrom_callback, 0);
175 			CDsetcallback(cd_parser, cd_atime, cdrom_callback, 0);
176 			CDsetcallback(cd_parser, cd_catalog, cdrom_callback, 0);
177 		}
178 #if 0
179 		/* Get the catalog number, if one exists */
180 		CDseektrack(cdrom_fd,1);
181 		cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
182 		cdrom_play_frames(1);
183 #endif
184 	}
185 
186 	if (cdi.state & CDROM_STATE_PLAY)
187 		cdi.curtrack = n;
188 
189 	if (cdi.state & CDROM_STATE_SHUFFLE)
190 		shuffle_setup();
191 
192 	return(cdi.curtrack);
193 }
194 
195 void
cdrom_close()196 cdrom_close() {
197 	if (cdrom_fd == NULL)
198 		return;
199 
200 	if (cdi.scsi_audio) {
201 		cdrom_kill_child();
202 		cdrom_audio_close();
203 	}
204 	if (cdi.times != NULL) {
205 		free((char *) cdi.times);
206 		free((char *) cdi.addrs);
207 		cdi.times = NULL;
208 		cdi.addrs = NULL;
209 	}
210 
211 	(void) CDclose(cdrom_fd);
212 	cdrom_fd = NULL;
213 }
214 
215 int
cdrom_audio_open()216 cdrom_audio_open() {
217 	ALconfig	aconfig;
218 
219 	aconfig = ALnewconfig();
220 
221 	/* Attempt to create the largest buffer we can */
222 	ALsetqueuesize (aconfig, SAMPLES_PER_FRAME * INIT_READ);
223 
224 	/* Make sure we are 16bit stereo */
225 	ALsetwidth(aconfig, AL_SAMPLE_16);
226 	ALsetchannels(aconfig, AL_STEREO);
227 
228 	if ((audio_fd = ALopenport("XCplayer", "w", aconfig)) == NULL) {
229 		ALfreeconfig(aconfig);
230 		return(-1);	/* No error, just return -1 */
231 	}
232 
233 	ALfreeconfig(aconfig);
234 
235 	audio_param[0] = AL_OUTPUT_RATE;
236 	audio_param[1] = AL_RATE_44100;
237 	ALsetparams(AL_DEFAULT_DEVICE, audio_param, 2);
238 
239 	shmkey = IPC_PRIVATE;
240 	if ((shmid = shmget(shmkey, sizeof(struct _cdrom_shmem),
241 			    (SHM_R | SHM_W | IPC_CREAT | IPC_EXCL) )) < 0) {
242 		perror("shmget");
243 		return(-1);
244 	}
245 	cdrom_shmem = shmat(shmid, NULL, SHM_RND);
246 }
247 
248 void
cdrom_audio_close()249 cdrom_audio_close() {
250 	if (audio_fd == NULL)
251 		return;
252 
253 	(void) ALcloseport(audio_fd);
254 	shmdt(cdrom_shmem);
255 	shmctl(shmid,IPC_RMID);
256 	audio_fd = NULL;
257 	cdrom_audio_opened = 0;
258 }
259 
260 void
cdrom_callback(arg,type,data)261 cdrom_callback(arg, type, data)
262 	int		arg;
263 	CDDATATYPES	type;
264 	void		*data;
265 {
266 	struct cdtimecode	*timecode_info;
267 	CDPROGNUM		*pnum_info;
268 	char *			catalog_num;
269 	int			otime, time;
270 	int			i;
271 
272 	switch (type) {
273 	case cd_audio:
274 		ALwritesamps(audio_fd, data, SAMPLES_PER_FRAME);
275 		break;
276 	case cd_pnum:
277 		pnum_info = data;
278 
279 		if (pnum_info->value <=
280 		    cdrom_shmem->cdrom_audio_cdi.end_track) {
281 			cdrom_shmem->cdrom_audio_cdi.curtrack = pnum_info->value;
282 		} else {
283 			cdrom_shmem->cdrom_audio_cdi.curtrack = 0;
284 			cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
285 		}
286 		break;
287 	case cd_atime:
288 		timecode_info = data;
289 
290 		otime = (cdrom_shmem->cdrom_audio_msf.minute * 60) +
291 			cdrom_shmem->cdrom_audio_msf.second;
292 		time = (((timecode_info->mhi * 10) +
293 			 timecode_info->mlo) * 60) +
294 				 (timecode_info->shi * 10) +
295 					 timecode_info->slo;
296 
297 		if ((otime > (time + 2)) || (otime < time - 2)) {
298 			if (CDseek(cdrom_fd,
299 				   cdrom_shmem->cdrom_audio_msf.minute,
300 				   cdrom_shmem->cdrom_audio_msf.second,
301 				   cdrom_shmem->cdrom_audio_msf.frame) < 0) {
302 				perror("CDseek");
303 			}
304 			cdrom_shmem->cdrom_audio_cdi.state = CD_ABORT;
305 			return;
306 		}
307 
308 		cdrom_shmem->cdrom_audio_msf.minute =
309 			(timecode_info->mhi * 10) + timecode_info->mlo;
310 		cdrom_shmem->cdrom_audio_msf.second =
311 			(timecode_info->shi * 10) + timecode_info->slo;
312 		cdrom_shmem->cdrom_audio_msf.frame =
313 			(timecode_info->fhi * 10) + timecode_info->flo;
314 
315 		break;
316 	case cd_catalog:
317 		catalog_num = data;
318 #if 0
319 		fprintf(stderr,"Catalog #: ");
320 		for (i=0; i<13; i++) {
321 			fprintf(stderr,"%d",*(catalog_num+i));
322 		}
323 		fprintf(stderr,"\n");
324 #endif
325 	default:
326 		return;
327 	}
328 }
329 
330 int
cdrom_start()331 cdrom_start() {
332 	return(0);
333 }
334 
335 int
cdrom_stop()336 cdrom_stop() {
337 	if (cdi.scsi_audio && cdrom_audio_opened) {
338 		cdrom_kill_child();
339 		cdrom_shmem->cdrom_audio_cdi.curtrack = cdi.curtrack;
340 		cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
341 	}
342 	if (! CDstop(cdrom_fd)) {
343 		perror("CDstop");
344 		return(-1);
345 	}
346 
347 	return(0);
348 }
349 
350 int
cdrom_eject()351 cdrom_eject() {
352 	if (cdi.scsi_audio && cdrom_audio_opened) {
353 		cdrom_kill_child();
354 		cdrom_shmem->cdrom_audio_cdi.state = CD_NODISC;
355 	}
356 	if (! CDeject(cdrom_fd)) {
357 		perror("ioctl(cdromeject)");
358 		return(-1);
359 	}
360 	cdrom_close();
361 
362 	return(0);
363 }
364 
365 int
cdrom_pause()366 cdrom_pause() {
367 	int track;
368 
369 	if (cdi.scsi_audio && cdrom_audio_opened) {
370 		cdrom_shmem->cdrom_audio_cdi.state = CD_PAUSED;
371 		return(0);
372 	}
373 	if (! cdrom_paused(&track)) {
374 		if (! CDtogglepause(cdrom_fd)) {
375 			perror("CDtogglepause");
376 			return(-1);
377 		}
378 	}
379 
380 	return(0);
381 }
382 
383 int
cdrom_resume()384 cdrom_resume() {
385 	int track;
386 
387 	if (cdi.scsi_audio && cdrom_audio_opened) {
388 		cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
389 		return(0);
390 	}
391 	if (! cdrom_playing(&track)) {
392 		if (! CDtogglepause(cdrom_fd)) {
393 			perror("CDtogglepause");
394 			return(-1);
395 		}
396 	}
397 
398 	return(0);
399 }
400 
401 int
cdrom_toggle_audio()402 cdrom_toggle_audio()
403 {
404 	if (cdi.scsi_audio) {
405 		cdrom_kill_child();
406 		cdi.scsi_audio = 0;
407 		return;
408 	}
409 	cdi.scsi_audio = 1;
410 }
411 
412 int
cdrom_volume(left_vol,right_vol)413 cdrom_volume(left_vol, right_vol)
414 	int			left_vol;
415 	int			right_vol;
416 {
417 	CDVOLUME	cd_vol;
418 
419 	if (cdi.scsi_audio) {
420 		audio_param[0] = AL_LEFT_SPEAKER_GAIN;
421 		audio_param[1] = left_vol;
422 		audio_param[2] = AL_RIGHT_SPEAKER_GAIN;
423 		audio_param[3] = right_vol;
424 
425 		ALsetparams (AL_DEFAULT_DEVICE, audio_param, 4);
426 	} else {
427 #if 0
428 		/* I would love to use this, but it isn't documented */
429 		cd_vol.chan0 = (unsigned char)left_vol;
430 		cd_vol.chan1 = (unsigned char)right_vol;
431 		CDsetvolume(cdrom_fd, &cd_vol);
432 #endif
433 		return(-1);
434 	}
435 
436 	return(0);
437 }
438 
439 int
cdrom_get_volume()440 cdrom_get_volume()
441 {
442 	int vol;
443 	CDVOLUME	cd_vol;
444 
445 	audio_param[0] = AL_LEFT_SPEAKER_GAIN;
446 	audio_param[2] = AL_RIGHT_SPEAKER_GAIN;
447 	if (cdi.scsi_audio) {
448 		ALgetparams (AL_DEFAULT_DEVICE, audio_param, 4);
449 
450 		/* Return the average of left and right channels */
451 		vol=(audio_param[1] + audio_param[3]) / 2;
452 	} else {
453 #if 0
454 		/* I would love to use this, but it isn't documented */
455 		CDgetvolume(cdrom_fd, &cd_vol);
456 		fprintf(stderr,"%d %d %d %d\n",cd_vol.chan0,cd_vol.chan1,
457 			cd_vol.chan2,cd_vol.chan3);
458 		vol=(cd_vol.chan0 + cd_vol.chan1) / 2;
459 #endif
460 		vol = -1;
461 	}
462 
463 	return(vol);
464 }
465 
466 int
cdrom_get_times()467 cdrom_get_times() {
468 	CDSTATUS	        tochdr;
469 	extern unsigned short	*ushort_malloc();
470 	extern struct msf	*msf_malloc();
471 	unsigned long		trk, trk_total, otime;
472 	struct msf		msf;
473 
474 	if (cdrom_read_tochdr(&tochdr) == -1) {
475 		cdi.mintrack = 0;
476 		cdi.maxtrack = 0;
477 		return(-1);
478 #if 0
479 		return(0);
480 #endif
481 	}
482 
483 	cdi.mintrack = tochdr.first;
484 	cdi.maxtrack = tochdr.last;
485 
486 	if (cdi.times != NULL)
487 	{
488 		free((char *) cdi.times);
489 		free((char *) cdi.addrs);
490 		cdi.times = NULL;
491 		cdi.addrs = NULL;
492 	}
493 
494 	cdi.times = ushort_malloc(cdi.maxtrack - cdi.mintrack + 1);
495 	cdi.addrs = msf_malloc(cdi.maxtrack - cdi.mintrack + 2);
496 
497 	otime = 0;
498 
499 	for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
500 		if (cdrom_get_msf(trk, &msf, &trk_total) == -1)
501 			return(-1);
502 
503 		/* record start address for each track (track 1 starts at 0)*/
504 		cdi.addrs[trk - cdi.mintrack] = msf;
505 
506 		trk_total -= otime;
507 
508 		/* use start time of next track as length of previous */
509 		if (otime != 0)
510 		{
511 			cdi.times[trk - cdi.mintrack - 1] = trk_total;
512 		}
513 
514 		otime += trk_total;
515 
516 	}
517 
518 	/* find start of  leadout to get length of last track */
519 	if (cdrom_get_msf(CDROM_LEADOUT, &msf, &trk_total) == -1)
520 		return(-1);
521 
522 	/* recode leadout start address */
523 	cdi.addrs[trk - cdi.mintrack] = msf;
524 	trk_total -= otime;
525 	otime += trk_total;
526 
527 	cdi.times[trk - cdi.mintrack - 1] = trk_total;
528 
529 	return(0);
530 }
531 
532 # if defined(notdef)
533 static void
cdrom_print_toc()534 cdrom_print_toc() {
535 	unsigned long		trk, trk_total;
536 
537 	for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
538 		trk_total = cdi.times[trk - cdi.mintrack];
539 		debug_printf(1, "%02u:%02u\n", trk_total/60, trk_total%60);
540 	}
541 }
542 # endif /* defined(notdef) */
543 
544 int
cdrom_get_curtrack()545 cdrom_get_curtrack() {
546 	CDSTATUS cdrom_stat;
547 
548 	if (cdi.scsi_audio && cdrom_audio_opened &&
549 	    ((cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING) ||
550 	     (cdrom_shmem->cdrom_audio_cdi.state == CD_PAUSED))) {
551 		if (((cdrom_shmem->cdrom_audio_msf.minute * 60) +
552 		     cdrom_shmem->cdrom_audio_msf.second) >
553 		    ((cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack].minute * 60) +
554 		     cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack].second)) {
555 			cdrom_shmem->cdrom_audio_cdi.curtrack++;
556 		}
557 		if (((cdrom_shmem->cdrom_audio_msf.minute * 60) +
558 		     cdrom_shmem->cdrom_audio_msf.second) <
559 		    ((cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack-1].minute * 60) +
560 		     cdi.addrs[cdrom_shmem->cdrom_audio_cdi.curtrack-1].second)) {
561 			cdrom_shmem->cdrom_audio_cdi.curtrack--;
562 		}
563 		return(cdrom_shmem->cdrom_audio_cdi.curtrack);
564 	}
565 	if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
566 		fprintf(stderr, "CDgetstatus(cdrom_stat): ");
567 		perror("CDgetstatus");
568 		return(-1);
569 	}
570 
571 	switch (cdrom_stat.state) {
572 	case CD_ERROR:
573 		return(-1);
574 
575 	case CD_NODISC:
576 		debug_printf(1, "cdrom_get_curtrack: no disc\n");
577 		return(0);
578 
579 		/* playing track cdrom_stat.track */
580 	case CD_PLAYING:
581 		return((int) cdrom_stat.track);
582 
583 		/* paused on track cdrom_stat.track */
584 	case CD_PAUSED:
585 		return((int) cdrom_stat.track);
586 
587 		/* punt */
588 	case CD_READY:
589 		return(0);
590 
591 		/* punt */
592 	case CD_STILL:
593 		return(0);
594 
595 #if 0
596 	case CD_NOSTATUS:
597 		debug_printf(1, "cdrom_get_curtrack: no status\n");
598 		return(0);
599 #endif
600 	}
601 
602 	/* bad value in cdrom_stat */
603 	return(-1);
604 }
605 
606 int
cdrom_get_msf(track,msf,length)607 cdrom_get_msf(track, msf, length)
608 	unsigned long		track;
609 	struct msf		*msf;
610 	unsigned long		*length;
611 {
612 	struct cdrom_tocentry	tocentry;
613 
614 	if (cdrom_read_tocentry(track, &tocentry) == -1)
615 		return(-1);
616 
617 	msf->minute = tocentry.cdte_addr.msf.minute;
618 	msf->second = tocentry.cdte_addr.msf.second;
619 	msf->frame = tocentry.cdte_addr.msf.frame;
620 
621 	*length = ((int) tocentry.cdte_addr.msf.minute * 60) +
622 		(int) tocentry.cdte_addr.msf.second;
623 
624 	return(0);
625 }
626 
627 int
cdrom_get_curmsf(msf)628 cdrom_get_curmsf(msf)
629 	struct msf *msf;
630 {
631 	int 		num_frames;
632 	CDSTATUS 	cdrom_stat;
633 
634 	if (cdi.scsi_audio && cdrom_audio_opened) {
635 		msf->minute = cdrom_shmem->cdrom_audio_msf.minute;
636 		msf->second = cdrom_shmem->cdrom_audio_msf.second;
637 		msf->frame = cdrom_shmem->cdrom_audio_msf.frame;
638 		if (msf->minute < 0) {
639 			msf->minute = 0;
640 			msf->second = 0;
641 			msf->frame = 0;
642 		}
643 		return(0);
644 	}
645 	if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
646 		fprintf(stderr, "CDgetstatus(cdrom_stat): ");
647 		perror("CDgetstatus");
648 		return(-1);
649 	}
650 	msf->minute = cdrom_stat.abs_min;
651 	msf->second = cdrom_stat.abs_sec;
652 	msf->frame = cdrom_stat.abs_frame;
653 
654 	return (0);
655 }
656 
657 int
cdrom_play_track(start_track,end_track)658 cdrom_play_track(start_track, end_track)
659 	unsigned char		start_track;
660 	unsigned char		end_track;
661 {
662 	int 		track;
663 	struct msf 	msf;
664 
665 	track = start_track;
666 
667 	if ( cdi.scsi_audio && cdrom_audio_opened ) {
668 		cdrom_shmem->cdrom_audio_cdi.start_track = start_track;
669 		cdrom_shmem->cdrom_audio_cdi.end_track = end_track;
670 
671 		cdrom_shmem->cdrom_audio_cdi.state = CD_ABORT;
672 		if (CDseektrack(cdrom_fd, track) < 0) {
673 			perror("CDseektrack");
674 			return(-1);
675 		}
676 		msf = cdi.addrs[track - cdi.mintrack];
677 		cdrom_shmem->cdrom_audio_msf.minute = msf.minute;
678 		cdrom_shmem->cdrom_audio_msf.second = msf.second;
679 		cdrom_shmem->cdrom_audio_msf.frame = msf.frame;
680 		cdi.curtrack = track;
681 		cdrom_shmem->cdrom_audio_cdi.curtrack = track;
682 		cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
683 		if (cdrom_shmem->cdrom_audio_cdi.child_pid != 0) {
684 			return(0);
685 		}
686 		signal(SIGCLD, cdrom_child_died);
687 		if ((cdrom_shmem->cdrom_audio_cdi.child_pid = fork()) == 0) {
688 			cdrom_child_setup();
689 			while (1) {
690 				cdrom_play_frames(ONE_SECOND);
691 			}
692 		}
693 	} else {
694 		if (! CDplaytrack(cdrom_fd, track, 1)) {
695 			perror("CDplaytrack");
696 			return(-1);
697 		}
698 	}
699 
700 	return(0);
701 }
702 
703 int
cdrom_play_msf(start_msf,end_msf)704 cdrom_play_msf(start_msf, end_msf)
705 	struct msf	*start_msf;
706 	struct msf	*end_msf;
707 {
708 	int num_frames;
709 	int i;
710 
711 	/* Fix negative seconds */
712 	if (start_msf->second < 0) {
713 		start_msf->second += 60;
714 		start_msf->minute--;
715 	}
716 
717 	if ( cdi.scsi_audio && cdrom_audio_opened ) {
718 		cdrom_shmem->cdrom_audio_msf.minute = start_msf->minute;
719 		cdrom_shmem->cdrom_audio_msf.second = start_msf->second;
720 		cdrom_shmem->cdrom_audio_msf.frame = start_msf->frame;
721 		if (CDseek(cdrom_fd, start_msf->minute,
722 				start_msf->second,
723 				start_msf->frame) < 0) {
724 			perror("CDseek");
725 			return(-1);
726 		}
727 		cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
728 		cdrom_shmem->cdrom_audio_cdi.curtrack = cdi.curtrack;
729 		if (cdrom_shmem->cdrom_audio_cdi.child_pid != 0) {
730 			return(0);
731 		}
732 		signal(SIGCLD, cdrom_child_died);
733 		if ((cdrom_shmem->cdrom_audio_cdi.child_pid = fork()) == 0) {
734 			cdrom_child_setup();
735 			while (1) {
736 				cdrom_play_frames(ONE_SECOND);
737 			}
738 		}
739 
740 	} else {
741 		if (! CDplayabs(cdrom_fd, start_msf->minute,
742 				start_msf->second,
743 				start_msf->frame, 1)) {
744 			perror("CDplayabs");
745 			return(-1);
746 		}
747 
748 		return(0);
749 	}
750 }
751 
752 int
cdrom_read_tocentry(track,tocentry)753 cdrom_read_tocentry(track, tocentry)
754 	unsigned int		track;
755 	struct cdrom_tocentry 	*tocentry;
756 {
757 	CDSTATUS cdrom_stat;
758 	CDTRACKINFO cdrom_track;
759 
760 	tocentry->cdte_track = track;
761 	tocentry->cdte_format = CDROM_MSF;
762 
763 	if (cdrom_status() == CD_NODISC) {
764 		tocentry->cdte_addr.msf.minute = 0;
765 		tocentry->cdte_addr.msf.second = 0;
766 		tocentry->cdte_addr.msf.frame = 0;
767 		return(0);
768 	}
769 
770 	if (track == CDROM_LEADOUT) {
771 		if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
772 			fprintf(stderr, "CDgetstatus(cdrom_read_tocentry): ");
773 			perror("CDgetstatus");
774 			return(-1);
775 		}
776 		tocentry->cdte_addr.msf.minute = cdrom_stat.total_min;
777 		tocentry->cdte_addr.msf.second = cdrom_stat.total_sec;
778 		tocentry->cdte_addr.msf.frame = cdrom_stat.total_frame;
779 	} else {
780 		if (! CDgettrackinfo(cdrom_fd, track,
781 				     (CDTRACKINFO *) &cdrom_track)) {
782 			fprintf(stderr, "CDgettrackinfo(cdrom_read_tocentry): ");
783 			perror("CDgetstatus");
784 			return(-1);
785 		}
786 		tocentry->cdte_addr.msf.minute = cdrom_track.start_min;
787 		tocentry->cdte_addr.msf.second = cdrom_track.start_sec;
788 		tocentry->cdte_addr.msf.frame = cdrom_track.start_frame;
789 	}
790 	return(0);
791 }
792 
793 int
cdrom_read_tochdr(tochdr)794 cdrom_read_tochdr(tochdr)
795 	CDSTATUS *tochdr;
796 {
797 	if (cdrom_status() == CD_NODISC)
798 		return(-1);
799 
800 	if (! CDgetstatus(cdrom_fd, tochdr)) {
801 		fprintf(stderr, "CDgetstatus(cdrom_read_tochdr): ");
802 		perror("CDgetstatus");
803 		return(-1);
804 	}
805 
806 	return(0);
807 }
808 
809 int
cdrom_status()810 cdrom_status() {
811 	CDSTATUS cdrom_stat;
812 
813 	if (cdrom_fd == NULL) {
814 		return(-1);
815 	}
816 
817 	if (cdi.scsi_audio && cdrom_audio_opened &&
818 	    (cdrom_shmem->cdrom_audio_cdi.child_pid != 0)) {
819 		return(cdrom_shmem->cdrom_audio_cdi.state);
820 	}
821 	if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
822 		fprintf(stderr, "CDgetstatus(cdrom_stat): ");
823 		perror("CDgetstatus");
824 		return(-1);
825 	}
826 
827 	switch (cdrom_stat.state) {
828 	case CD_ERROR:
829 		return(CD_ERROR);
830 	case CD_NODISC:
831 		return(CD_NODISC);
832 	case CD_READY:
833 		return(CD_READY);
834 	case CD_PLAYING:
835 		return(CD_PLAYING);
836 	case CD_PAUSED:
837 		return(CD_PAUSED);
838 	case CD_STILL:
839 		return(CD_STILL);
840 	}
841 
842 	return(-1);
843 }
844 
845 int
cdrom_playing(track)846 cdrom_playing(track)
847 	int			*track;
848 {
849 	CDSTATUS cdrom_stat;
850 
851 	if (cdi.scsi_audio && cdrom_audio_opened &&
852 	    ((cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING) ||
853 	     (cdrom_shmem->cdrom_audio_cdi.state == CD_PAUSED))) {
854 		return(cdrom_shmem->cdrom_audio_cdi.state);
855 	}
856 
857 	if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
858 		fprintf(stderr, "CDgetstatus(cdrom_playing): ");
859 		perror("CDstatus");
860 		return(-1);
861 	}
862 
863 	*track = cdrom_stat.track;
864 	if (cdrom_stat.state == CD_PLAYING) {
865 		return(1);
866 	}
867 
868 	return(0);
869 }
870 
871 int
cdrom_paused(track)872 cdrom_paused(track)
873 	int			*track;
874 {
875 	CDSTATUS cdrom_stat;
876 
877 	if (cdi.scsi_audio && cdrom_audio_opened &&
878 	    ((cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING) ||
879 	     (cdrom_shmem->cdrom_audio_cdi.state == CD_PAUSED))) {
880 		return(cdrom_shmem->cdrom_audio_cdi.state);
881 	}
882 
883 	if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
884 		fprintf(stderr, "CDgetstatus(cdrom_paused): ");
885 		perror("CDgetstatus");
886 		return(-1);
887 	}
888 
889 	*track = cdrom_stat.track;
890 	if (cdrom_status() == CD_PAUSED) {
891 		return(1);
892 	}
893 
894 	return(0);
895 }
896 
897 # if defined(notused)
898 int
mounted(name)899 mounted(name)
900 	char		*name;
901 {
902 	char		buf[MAXPATHLEN], *cp;
903 	struct stat	st;
904 	dev_t		bdevno;
905 	FILE		*fp;
906 	struct mntent	*mnt;
907 
908 	/*
909 	 * Get the block device corresponding to the raw device opened,
910 	 * and find its device number.
911 	 */
912 	if (stat(name, &st) != 0) {
913 		(void) fprintf(stderr, "stat: ");
914 		perror(name);
915 		return(UNMOUNTED);
916 	}
917 
918 	/*
919 	 * If this is a raw device, we have to build the block device name.
920 	 */
921 	if ((st.st_mode & S_IFMT) == S_IFCHR) {
922 		if ((cp = strchr(name, 'r')) != NULL)
923 			cp++;
924 
925 		(void) sprintf(buf, "/dev/%s", cp);
926 		if (stat(buf, &st) != 0) {
927 			(void) fprintf(stderr, "stat: ");
928 			perror(buf);
929 			return(UNMOUNTED);
930 		}
931 	}
932 
933 	if ((st.st_mode & S_IFMT) != S_IFBLK)
934 		return(UNMOUNTED);
935 
936 	bdevno = st.st_rdev & (dev_t)(~0x07);	/* Mask out partition. */
937 
938 	/*
939 	 * Now go through the mtab, looking at all hsfs filesystems.
940 	 * Compare the device mounted with our bdevno.
941 	 */
942 	if ((fp = setmntent(MOUNTED, "r")) == NULL) {
943 		(void) fprintf(stderr, "couldn't open %s\n", MOUNTED);
944 		return(UNMOUNTED);
945 	}
946 
947 	while ((mnt = getmntent(fp)) != NULL) {
948 		/* avoid obvious excess stat(2)'s */
949 		if (strcmp(mnt->mnt_type, "hsfs") != 0)
950 			continue;
951 
952 		if (stat(mnt->mnt_fsname, &st) != 0)
953 			continue;
954 
955 		if (((st.st_mode & S_IFMT) == S_IFBLK) &&
956 		    ((st.st_rdev & (dev_t)(~0x07)) == bdevno)) {
957 			(void) endmntent(fp);
958 			return(STILL_MOUNTED);
959 		}
960 	}
961 
962 	(void) endmntent(fp);
963 
964 	return(UNMOUNTED);
965 }
966 # endif /* defined(notused) */
967 
968 int
cdrom_play_frames(number)969 cdrom_play_frames(number)
970 	int	number;
971 {
972 	int	frames_to_read = number;
973 	int	num_frames;
974 	int	frame_ctr;
975 	struct msf msf;
976 	CDSTATUS cdrom_stat;
977 
978 	if (cdrom_audio_opened &&
979 	    cdrom_shmem->cdrom_audio_cdi.state != CD_PLAYING) {
980 		sleep(1);
981 		return(-1);
982 	}
983 
984 	if (frames_to_read > INIT_READ) {
985 		frames_to_read = INIT_READ;
986 	}
987 	if ((num_frames =
988 	     CDreadda(cdrom_fd, &cd_audio_buff[0], frames_to_read)) == -1) {
989 		perror("CDreadda");
990 		return(-1);
991 	}
992 	if (num_frames == 0) {
993 		msf = cdi.addrs[cdi.maxtrack];
994 		if ((cdrom_shmem->cdrom_audio_msf.minute >= (msf.minute-1)) &&
995 		    (cdrom_shmem->cdrom_audio_msf.second >= (msf.second-1)) ) {
996 			cdrom_shmem->cdrom_audio_cdi.curtrack = 0;
997 			cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
998 		}
999 		return(0);
1000 	}
1001 	for (frame_ctr=0;
1002 	     frame_ctr<num_frames &&
1003 	     cdrom_shmem->cdrom_audio_cdi.state == CD_PLAYING;
1004 	     frame_ctr++) {
1005 		CDparseframe(cd_parser, &cd_audio_buff[frame_ctr]);
1006 	}
1007 	if (cdrom_shmem->cdrom_audio_cdi.state == CD_ABORT) {
1008 		cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
1009 	}
1010 	return(num_frames);
1011 }
1012 
1013 int
cdrom_child_setup()1014 cdrom_child_setup() {
1015 	cdrom_shmem = shmat(shmid, NULL, SHM_RND);
1016 	cdrom_shmem->cdrom_audio_cdi.state = CD_PLAYING;
1017 	signal(SIGHUP,cdrom_child_quit);
1018 }
1019 
1020 void
cdrom_child_died()1021 cdrom_child_died() {
1022 	cdrom_stop();
1023 	wait(NULL);
1024 	cdrom_shmem->cdrom_audio_cdi.child_pid = 0;
1025 	cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
1026 	cdrom_shmem->cdrom_audio_cdi.curtrack = 0;
1027 	cdi.curtrack = 0;
1028 	cdrom_shmem->cdrom_audio_msf.minute = 0;
1029 	cdrom_shmem->cdrom_audio_msf.second = 0;
1030 	cdrom_shmem->cdrom_audio_msf.frame = 0;
1031 	signal(SIGCLD,cdrom_child_died);
1032 }
1033 
1034 void
cdrom_child_quit()1035 cdrom_child_quit() {
1036 	shmdt(cdrom_shmem);
1037 	exit(1);
1038 }
1039 
1040 void
cdrom_kill_child()1041 cdrom_kill_child()
1042 {
1043 	if (!(cdrom_audio_opened && cdrom_shmem->cdrom_audio_cdi.child_pid)) {
1044 		return;
1045 	}
1046 	kill(cdrom_shmem->cdrom_audio_cdi.child_pid, SIGHUP);
1047 	wait(NULL);
1048 	cdrom_shmem->cdrom_audio_cdi.state = CD_READY;
1049 	cdrom_shmem->cdrom_audio_cdi.child_pid = 0;
1050 }
1051 
1052 int
cdrom_audio_avail()1053 cdrom_audio_avail() {
1054 	CDSTATUS	cdrom_stat;
1055 
1056 	if (cdrom_audio_opened && (! audio_button_state())) {
1057 		return(0);
1058 	}
1059 	cdrom_audio_opened = 1;
1060 
1061 	if (! CDgetstatus(cdrom_fd, (CDSTATUS *) &cdrom_stat)) {
1062 		fprintf(stderr, "CDgetstatus(cdrom_stat): ");
1063 		perror("CDgetstatus");
1064 		return(-1);
1065 	}
1066 
1067 	if ( cdrom_stat.scsi_audio && (cdrom_audio_open() >= 0) ) {
1068 		return(1);
1069 	} else {
1070 		return(0);
1071 	}
1072 }
1073 
1074 unsigned short *
ushort_malloc(n)1075 ushort_malloc(n)
1076 	int		n;
1077 {
1078 	extern char	*calloc();
1079 	unsigned short	*ptr;
1080 
1081 	ptr = (unsigned short *) calloc(n, sizeof(unsigned short));
1082 	if (ptr == NULL) {
1083 		perror("calloc");
1084 		exit(1);
1085 	}
1086 
1087 	return(ptr);
1088 }
1089 
1090 struct msf *
msf_malloc(n)1091 msf_malloc(n)
1092 	int		n;
1093 {
1094 	extern char	*calloc();
1095 	struct msf	*ptr;
1096 
1097 	ptr = (struct msf *) calloc(n, sizeof(struct msf));
1098 	if (ptr == NULL) {
1099 		perror("calloc");
1100 		exit(1);
1101 	}
1102 
1103 	return(ptr);
1104 }
1105 
1106 int
cdrom_disp_cdi()1107 cdrom_disp_cdi() {
1108 	int trk;
1109 
1110 	fprintf(stderr,"CDI structure:\n");
1111 	fprintf(stderr,"\tcurtrack: %d\n",cdi.curtrack);
1112 	fprintf(stderr,"\tmin: %d  max: %d  total: %d\n",
1113 		cdi.mintrack, cdi.maxtrack, cdi.ntracks);
1114 	fprintf(stderr,"\tdur: %d  state: %2x\n",cdi.duration, cdi.state);
1115 	fprintf(stderr,"\tcurrand: %d  lastprog: %d\n",
1116 		cdi.currand, cdi.lastprog);
1117 	fprintf(stderr,"\n\tTracklist:\n");
1118 	if (cdi.maxtrack != cdi.mintrack) {
1119 		for (trk=cdi.mintrack; trk<=cdi.maxtrack; trk++) {
1120 			fprintf(stderr,"\t%3d: %d %02d:%02d %d\n",trk,cdi.times[trk],
1121 				cdi.addrs[trk].minute,cdi.addrs[trk].second,
1122 				cdi.addrs[trk].frame);
1123 		}
1124 	}
1125 
1126 	if (cdi.scsi_audio) {
1127 		fprintf(stderr,"AUDIO_CDI structure:\n");
1128 		fprintf(stderr,"\tcurtrack: %d\n",cdrom_shmem->cdrom_audio_cdi.curtrack);
1129 		fprintf(stderr,"\tdur: %d  state: %d\n",cdrom_shmem->cdrom_audio_cdi.duration, cdrom_shmem->cdrom_audio_cdi.state);
1130 	}
1131 }
1132 
1133 # endif /* defined(sgi) */
1134