; /*\ ; |*| cdmaster.c ; |*| ; |*| routines for c-interface to cdrom audio functions ; |*| contains routines accessing internal data structures ; |*| ; |*| Copyright (c) 1992, Media Vision, Inc. All Rights Reserved ; |*| ; \*/ #include #include "cdmaster.h" static struct cdtable OURCDTABLES[26]; ; /*\ ; |*| struct cdtable *createaudiotoc(int drive) ; |*| ; |*| allocate memory for table of contents for audio disc in drive ; |*| call destroyaudiotoc() to free memory and clear internal table ; |*| ; |*| Entry: drive number, address of buffer ; |*| ; |*| Exit: return address of internal table of contents ; |*| ; \*/ struct cdtable *createaudiotoc(int drive) { int status; struct discinfo *di; struct trackinfo *ti; /* destroy any existing toc for this drive */ destroyaudiotoc(drive); di= &OURCDTABLES[drive].di; status= cddiscinfo(drive, di); if (status& 0x8000) return((struct cdtable *) 0); ti= (struct trackinfo *) calloc(di->ltrk- di->strk+ 1+ 1, sizeof(struct trackinfo)); if (!ti) return((struct cdtable *) 0); { int i; struct trackinfo *dti; /* for now, do nothing; we will cdtrackinfo(drive, i, dti); */ for (i= di->strk, dti= ti; i <= di->ltrk; i++, dti++) ; { int dmin, dsec, dframe; dmin= ((di->eodisc& 0x00FF0000)>> 16); dsec= ((di->eodisc& 0x0000FF00)>> 8); dframe= ((di->eodisc& 0x000000FF)>> 0); /* audio data starts 2 seconds into the disc */ /* dsec-= 2; !! removed and put into cdplay */ fixmsf(&dmin, &dsec, &dframe); dti->track= i; dti->min= (char) dmin; dti->sec= (char) dsec; dti->frame= (char) dframe; } } OURCDTABLES[drive].ti= ti; return(&OURCDTABLES[drive]); } ; /*\ ; |*| struct cdtable *buildaudiotoc(int drive) ; |*| ; |*| allocate memory and build table of contents for audio disc in drive ; |*| call destroyaudiotoc() to free memory and clear internal table ; |*| ; |*| Entry: drive number, address of buffer ; |*| ; |*| Exit: return address of internal table of contents ; |*| ; \*/ struct cdtable *buildaudiotoc(int drive) { int i; struct cdtable *cdt= createaudiotoc(drive); if (!cdt) return(cdt); for (i= cdt->di.strk; i <= cdt->di.ltrk; i++) gettrackframes(drive, i); return(cdt); } ; /*\ ; |*| void destroyaudiotoc(int drive) ; |*| ; |*| free memory allocated by buildaudiotoc() and clear internal tables ; |*| if passed address is not the same as internal table ; |*| ; |*| Entry: drive number, address of buffer ; |*| ; |*| Exit: return 0 if table entry for drive was not 0, else -1 ; |*| ; \*/ destroyaudiotoc(int drive) { int notallocated= 0; if (OURCDTABLES[drive].ti) free(OURCDTABLES[drive].ti); else notallocated= -1; OURCDTABLES[drive].ti= (struct trackinfo *) 0; // OURCDTABLES[drive].di= (struct discinfo *) 0; return(notallocated); } ; /*\ ; |*| struct cdtable *getcdtable(int drive) ; |*| ; |*| return address of internal cd table for drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: address of internal cd table ; |*| ; \*/ struct cdtable *getcdtable(int drive) { return(&OURCDTABLES[drive]); } ; /*\ ; |*| struct discinfo *getdiscinfotable(int drive) ; |*| ; |*| return address of internal discinfo structure for drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: address of internal discinfo structure ; |*| ; \*/ struct discinfo *getdiscinfotable(int drive) { return(&OURCDTABLES[drive].di); } ; /*\ ; |*| struct trackinfo *gettrackinfotable(int drive) ; |*| ; |*| return address of internal table of contents for drive ; |*| ; |*| Entry: drive number ; |*| ; |*| Exit: address of internal table of contents ; |*| ; \*/ struct trackinfo *gettrackinfotable(int drive) { return(OURCDTABLES[drive].ti); } ; /*\ ; |*| long gettrackframes(int drive, int track) ; |*| ; |*| return the number of frames for given track on the disc ; |*| ; |*| Entry: drive number, track number ; |*| ; |*| Exit: return length of track in frames, or ; |*| return 0 if internal tables not initialized or track ; |*| number out of range ; |*| ; \*/ long gettrackframes(int drive, int track) { int lframe; int lsec; int lmin; struct discinfo *di; struct trackinfo *dti; struct trackinfo *nti; long tframe; di= &OURCDTABLES[drive].di; dti= OURCDTABLES[drive].ti; if (!di || !dti || track < di->strk || track > di->ltrk) return(0); dti+= track- di->strk; nti= dti+ 1; if (!dti->track) { cdtrackinfo(drive, track, dti); // dti->sec-= 2; /* data starts 2 seconds into disc */ } if (!nti->track) { cdtrackinfo(drive, track+ 1, nti); // nti->sec-= 2; /* data starts 2 seconds into disc */ } lmin= nti->min- dti->min; lsec= nti->sec- dti->sec; lframe= nti->frame- dti->frame; if (fixmsf(&lmin, &lsec, &lframe) == -1) return(-1); tframe= lmin; tframe*= 60; tframe+= lsec; tframe*= 75; tframe+= lframe; return(tframe); } ; /*\ ; |*| playcdtrack(int drive, int track, int offset, int length) ; |*| ; |*| begin audio play on disc for specified track at offset for length ; |*| ; |*| Entry: drive number, track number, offset in seconds in track, ; |*| length in seconds or -1 for rest of disc or -2 for track ; |*| ; |*| Exit: return -1 if no disc present, no internal table of contents, ; |*| track is out of range, offset is past end of track or disc ; |*| else return driver status ; |*| ; \*/ playcdtrack(int drive, int track, int offset, int length) { int ourtrack; int ourstatus; struct discinfo *di; struct trackinfo *ti, *sti, *dti; int min, sec, frame; int dmin, dsec, dframe; ourstatus= cdstatus(drive); if (!(ourstatus& CDISHERE)) return(-1); if (!OURCDTABLES[drive].ti) return(-1); di= &OURCDTABLES[drive].di; ourtrack= track- di->strk; if (ourtrack < 0 || ourtrack >= di->ltrk) return(-1); if (ourstatus& (CDISPLAYING| CDISPAUSED)) cdstop(drive); /* get starting MSF for our track * sti points to first trackinfo structure for disc * ti will point to the track to play * dti will point to the ending point */ ti= dti= sti= OURCDTABLES[drive].ti; ti+= ourtrack; if (!ti->track) { cdtrackinfo(drive, track, ti); // ti->sec-= 2; } /* min,sec,frame will hold the start m:s:f address */ min= ti->min; sec= ti->sec; frame= ti->frame; /* length is amount of seconds to play, a negative is special */ if (length < 0) { switch (length) { case -1: dti+= di->ltrk- di->strk+ 1; break; /* rest of disc */ case -2: dti+= ourtrack+ 1; break; /* rest of track */ } length= 0; } if (!dti->track) { cdtrackinfo(drive, dti- sti+ di->strk, dti); // dti->sec-= 2; } /* dmin,dsec,drame holds the amount of time to play */ dmin= dti->min- min; dsec= dti->sec- sec; dframe= dti->frame- frame; /* offset and length are passed as parameters as seconds, affect */ sec+= offset; dsec+= length- offset; /* adjust length (endofdisc- startofdisc) */ dmin-= sti->min; dsec-= sti->sec; dframe-= sti->frame; if (fixmsf(&min, &sec, &frame) < 0) return(-1); if (fixmsf(&dmin, &dsec, &dframe) < 0) return(-1); return(cdplaymsf(drive, min, sec, frame, dmin, dsec, dframe)); } ; /*\ ; |*| seektotrack(int drive, int track) ; |*| ; |*| move head on drive to specified track ; |*| ; |*| Entry: drive number, track number ; |*| ; |*| Exit: return 0 if no internal tables or track out of range, ; |*| else return driver status ; |*| ; \*/ seektotrack(int drive, int track) { struct discinfo *d= &OURCDTABLES[drive].di; struct trackinfo *t= OURCDTABLES[drive].ti; if (!d || !t) return(0); if (track < d->strk || track > d->ltrk) return(0); t+= track- d->strk; if (!t->track) { cdtrackinfo(drive, track, t); // t->sec-= 2; } return(cdseekmsf(drive, t->min, t->sec, t->frame)); }