/* CDP plays arbitrary segment of a Music CD */
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <alloc.h>
#include <cdrom.h>
#define FALSE 0
#define TRUE 1
int cdrom_loaded, cdrom_drive;
struct ioctl_struc ioctl_block;
struct diskinfo_struc diskinfo_block;
struct trackinfo_struc trackinfo_block[100];
unsigned long red2hsg(unsigned long redval);
main(int argc, char *argv[])
{
int drive, i;
unsigned long start_sect, end_sect, leadout_sect, num_sect;
unsigned char filename[80];
FILE *outfp;
int track, start_min, start_sec, start_frame, end_min, end_sec, end_frame;
char local_buffer[132];
char c = ':';
if(argc > 1) {
if (! check_cd2f()){
printf("MSCDEX NOT LOADED\n");
exit(1);
}
Stop();
if((argv[1][0] == 's') || (argv[1][0] == 'S'))
exit(1);
while(get_diskinfo() != STAT_DONE);
for(i = diskinfo_block.low_track; i <= diskinfo_block.high_track; i++)
get_trackinfo(i);
leadout_sect = red2hsg(diskinfo_block.start_leadout);
track = atoi(argv[1]);
if( (track < 1) || (track > diskinfo_block.high_track)) {
printf("Error: Track must be between %d and %d\n",
diskinfo_block.low_track, diskinfo_block.high_track);
errexit();
}
start_min = 0;
start_sec = 0;
start_frame = 0;
end_min = 0;
end_sec = 0;
end_frame = 0;
if(argc > 2)
{
strcpy(local_buffer, argv[2]);
start_min = atoi(strtok(local_buffer, ":"));
start_sec = atoi(strtok(NULL,":"));
start_frame = atoi(&local_buffer[strrchr(argv[2],c)+1-local_buffer]);
}
start_sect = red2hsg(trackinfo_block[track].start_point)+(start_min*60L+((long)start_sec))*75L+((long)start_frame) -150L;
if(argc > 3)
{
strcpy(local_buffer, argv[3]);
end_min = atoi(strtok(local_buffer, ":"));
end_sec = atoi(strtok(NULL, ":"));
end_frame = atoi(&local_buffer[strrchr(argv[3],c)+1-local_buffer]);
end_sect = red2hsg(trackinfo_block[track].start_point)+(end_min*60L+((long)end_sec))*75L+((long)end_frame) -150L;
}
else end_sect = leadout_sect;
num_sect = end_sect-start_sect;
printf("Start sector : %lu\n", start_sect);
printf("End sector : %lu\n", end_sect);
printf("Number of sectors: %lu\n", num_sect);
printf("CDDA data size : %lu bytes\n", num_sect * 2352L);
play(start_sect, num_sect);
}
else {
printf("CDP Plays an arbitrary section of a CD\n");
printf("usage: cdp <track> [<start MM:SS:FF>] [<end MM:SS:FF>]\n");
printf(" \"cdp s\" stops playing\n");
}
}
check_cd2f()
{
union REGS regs;
regs.x.ax = INIT_MP_INT;
int86(MULTIPLEX_INT,®s,®s);
cdrom_loaded = regs.x.bx;
cdrom_drive = regs.x.cx;
}
get_diskinfo()
{
union REGS regs;
struct SREGS sregs;
diskinfo_block.cntrl_code = GET_AUDIO_DISKINFO;
ioctl_block.req_hdr.param_length = 13;
ioctl_block.req_hdr.sub_unit = 0;
ioctl_block.req_hdr.command_code = READ_IOCTL_COMMAND;
ioctl_block.req_hdr.status = 0;
ioctl_block.med_descr = 0;
ioctl_block.transf_addr = (unsigned long)&diskinfo_block;
ioctl_block.num_bytes = 7;
ioctl_block.start_sect = 0;
ioctl_block.vol_id = 0;
regs.x.ax = CDREQ_MP_INT;
regs.x.bx = FP_OFF(&ioctl_block);
regs.x.cx = cdrom_drive;
sregs.es = FP_SEG(&ioctl_block);
int86x(MULTIPLEX_INT,®s,®s,&sregs);
return(ioctl_block.req_hdr.status);
}
get_trackinfo(unsigned char trk)
{
union REGS regs;
struct SREGS sregs;
trackinfo_block[trk].cntrl_code = GET_AUDIO_TRACKINFO;
trackinfo_block[trk].track_num = trk;
ioctl_block.req_hdr.param_length = 13;
ioctl_block.req_hdr.sub_unit = 0;
ioctl_block.req_hdr.command_code = READ_IOCTL_COMMAND;
ioctl_block.req_hdr.status = 0;
ioctl_block.med_descr = 0;
ioctl_block.transf_addr = (unsigned long)&(trackinfo_block[trk]);
ioctl_block.num_bytes = 7;
ioctl_block.start_sect = 0;
ioctl_block.vol_id = 0;
regs.x.ax = CDREQ_MP_INT;
regs.x.bx = FP_OFF(&ioctl_block);
regs.x.cx = cdrom_drive;
sregs.es = FP_SEG(&ioctl_block);
int86x(MULTIPLEX_INT,®s,®s,&sregs);
return(ioctl_block.req_hdr.status);
}
play(unsigned long ssec,unsigned long numsecs)
{
union REGS regs;
struct SREGS sregs;
struct play_struc play_block;
struct qinfo_struc qinfo_block;
play_block.req_hdr.param_length = 13;
play_block.req_hdr.sub_unit = 0;
play_block.req_hdr.command_code = CD_PLAY_AUDIO;
play_block.req_hdr.status = 0;
play_block.address_mode = ADDR_HSG;
play_block.start_sect = ssec;
play_block.num_sect = numsecs;
regs.x.ax = CDREQ_MP_INT;
regs.x.bx = FP_OFF(&play_block);
regs.x.cx = cdrom_drive;
sregs.es = FP_SEG(&play_block);
int86x(MULTIPLEX_INT,®s,®s,&sregs);
/*
do {
qinfo_block.cntrl_code = GET_QCHAN_INFO;
ioctl_block.req_hdr.param_length = 13;
ioctl_block.req_hdr.sub_unit = 0;
ioctl_block.req_hdr.command_code = READ_IOCTL_COMMAND;
ioctl_block.req_hdr.status = 0;
ioctl_block.med_descr = 0;
ioctl_block.transf_addr = (unsigned long)&qinfo_block;
ioctl_block.num_bytes = 11;
ioctl_block.start_sec = 0;
ioctl_block.vol_id = 0;
regs.x.ax = CDREQ_MP_INT;
regs.x.bx = FP_OFF(&ioctl_block);
regs.x.cx = cdrom_drive;
sregs.es = FP_SEG(&ioctl_block);
int86x(MULTIPLEX_INT,®s,®s,&sregs);
if(kbhit()){
getch();
Stop();
break;
}
} while (ioctl_block.req_hdr.status & STAT_BUSY);
*/
}
Stop()
{
union REGS regs;
struct SREGS sregs;
struct reqhdr_struc stop_block;
stop_block.param_length = 13;
stop_block.sub_unit = 0;
stop_block.command_code = CD_STOP_AUDIO;
stop_block.status = 0;
regs.x.ax = CDREQ_MP_INT;
regs.x.bx = FP_OFF(&stop_block);
regs.x.cx = cdrom_drive;
sregs.es = FP_SEG(&stop_block);
int86x(MULTIPLEX_INT,®s,®s,&sregs);
return(stop_block.status);
}
unsigned long red2hsg(unsigned long redval)
{
unsigned long mins;
unsigned long secs;
unsigned long plus_frames;
plus_frames = redval & 0x000000ffL;
secs = ((redval & 0x0000ff00L) >> 8);
mins = ((redval & 0x00ff0000L) >> 16);
return((mins*60+secs)*75+plus_frames);
}
errexit()
{
exit(1);
}