/*- * Copyright (c) 1997 Antti Kaipila * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include "cdplay.h" extern int cd_fd; extern char *cd_device,*message; extern struct cd_info cdinfo; extern struct ioc_toc_header header; extern struct ioc_read_subchannel cd_s; extern struct cd_sub_channel_info cd_data; /* This updates the cdinfo structure */ void update_cdinfo(void) { if(ioctl(cd_fd,CDIOREADTOCHEADER,&cd_header)<0){ message="no cd in drive?"; init_cd(); } if(ioctl(cd_fd,CDIOCREADSUBCHANNEL,(char *)&cd_s)<0) per(); cdinfo.c_track=cd_s.data->what.position.track_number; cdinfo.c_sec =cd_s.data->what.position.reladdr.msf.second; cdinfo.c_min =cd_s.data->what.position.reladdr.msf.minute; cdinfo.c_frame=cd_s.data->what.position.reladdr.msf.frame; cdinfo.l_track=cd_header.ending_track; cdinfo.c_seca=cd_s.data->what.position.absaddr.msf.second+cd_s.data->what.position.absaddr.msf.minute*60; } /* Used to initalise cd */ void init_cd(void) { struct ioc_read_toc_entry read_entry; struct cd_toc_entry toc_buffer[100]; int i; while((cd_fd=open(cd_device,O_RDONLY))<0) sleep(2); cdinfo.eject=0; bzero(&cd_s,sizeof(cd_s)); cd_s.data = &cd_data; cd_s.data_len=sizeof (cd_data); cd_s.address_format=CD_MSF_FORMAT; cd_s.data_format=CD_CURRENT_POSITION; update_cdinfo(); read_entry.address_format=CD_MSF_FORMAT; read_entry.starting_track=1; read_entry.data_len=(cdinfo.l_track+1)*sizeof(struct cd_toc_entry); read_entry.data=toc_buffer; if(ioctl(cd_fd,CDIOREADTOCENTRYS,(char *) &read_entry)<0) per(); for(i=1;i<=cdinfo.l_track;i++){ cdinfo.s_sec[i]=toc_buffer[i].addr.msf.second; cdinfo.s_min[i]=toc_buffer[i].addr.msf.minute; cdinfo.s_frame[i]=toc_buffer[i].addr.msf.frame; } cdinfo.c_track = 1; } /* Plays trakcks nicely */ void play_track(int track) { struct ioc_play_msf cd_play; if(cdinfo.eject) init_cd(); track--; cd_play.start_m=cdinfo.s_min[track]; cd_play.start_s=cdinfo.s_sec[track]; cd_play.start_f=cdinfo.s_frame[track]; cd_play.end_m=cdinfo.s_min[cdinfo.l_track-1]; cd_play.end_s=cdinfo.s_sec[cdinfo.l_track-1]; cd_play.end_f=cdinfo.s_frame[cdinfo.l_track-1]; if(ioctl (cd_fd, CDIOCPLAYMSF, (char *) &cd_play)<0) { /* Hack for IDE CD-ROMs */ if (cd_play.start_s < 2) { cd_play.start_s=2; if(ioctl (cd_fd, CDIOCPLAYMSF, (char *) &cd_play)<0) per(); } else per(); } cdinfo.pause=0; } /* Skips one track forward */ void next(void) { play_track(cdinfo.c_track+1); } /* Quess */ void prev(void) { if(cdinfo.c_sec<4) play_track(cdinfo.c_track-1); else play_track(cdinfo.c_track); } /* Stop */ void stop(void) { if(ioctl (cd_fd, CDIOCSTOP)<0) per(); cdinfo.c_track=1; } /* Pauses cd. If cdinfo tells its already paused continues */ void cdpause(void) { if(cdinfo.pause){ message="continue"; if(ioctl (cd_fd, CDIOCRESUME)<0) per(); cdinfo.pause=0; } else { message="pause"; if(ioctl (cd_fd, CDIOCPAUSE)<0) per(); cdinfo.pause=1; } } /* Softly pauses the cd, or unpauses, as appropriate */ void cdsoftpause(void) { struct ioc_vol real_vol, cur_vol; int i; if(ioctl(cd_fd,CDIOCGETVOL,(char *) &real_vol)) per(); cur_vol = real_vol; if(cdinfo.pause){ message="continue"; memset (cur_vol.vol, 0, sizeof(cur_vol.vol)); if(ioctl(cd_fd,CDIOCSETVOL,(char *) &cur_vol)) per(); if(ioctl(cd_fd,CDIOCRESUME)<0) per(); else cdinfo.pause=0; for (i=0; i<20; usleep(21), i++) { cur_vol.vol[0] += (real_vol.vol[0] / 20); cur_vol.vol[1] += (real_vol.vol[1] / 20); cur_vol.vol[2] += (real_vol.vol[2] / 20); cur_vol.vol[3] += (real_vol.vol[3] / 20); if(ioctl(cd_fd,CDIOCSETVOL,(char *) &cur_vol)) per(); } if(ioctl(cd_fd,CDIOCSETVOL,(char *) &real_vol)) per(); } else { message="pause"; for (i=0; i<20; usleep(21), i++) { cur_vol.vol[0] -= (real_vol.vol[0] / 20); cur_vol.vol[1] -= (real_vol.vol[1] / 20); cur_vol.vol[2] -= (real_vol.vol[2] / 20); cur_vol.vol[3] -= (real_vol.vol[3] / 20); if(ioctl(cd_fd,CDIOCSETVOL,(char *) &cur_vol)) per(); } if(ioctl (cd_fd, CDIOCPAUSE)<0) per(); else cdinfo.pause=1; if(ioctl (cd_fd, CDIOCSETVOL,(char *) &real_vol)) per(); } } /* Huge kludge */ void ff(int n_times) { int secs; struct ioc_play_msf cd_play; secs=4*n_times; if (secs > 59) secs=59; if(cdinfo.c_seca%60+secs>=60){ cd_play.start_s=((cdinfo.c_seca%60)+secs)%60; cd_play.start_m=cdinfo.c_seca/60+1; } else { cd_play.start_s=(cdinfo.c_seca%60)+secs; cd_play.start_m=cdinfo.c_seca/60; } cd_play.start_f=1; cd_play.end_s=cdinfo.s_sec[cdinfo.l_track-1]; cd_play.end_m=cdinfo.s_min[cdinfo.l_track-1]; cd_play.end_f=cdinfo.s_frame[cdinfo.l_track-1]; if(ioctl(cd_fd,CDIOCPLAYMSF,(char *) &cd_play)<0) per(); cdinfo.pause=0; } /* Hi mom!! */ void rew(int n_times) { int secs; struct ioc_play_msf cd_play; secs=4*n_times; if (secs > 59) secs=59; if(cdinfo.c_seca%60-secs<0){ cd_play.start_s=((cdinfo.c_seca%60)-secs)+60; cd_play.start_m=cdinfo.c_seca/60-1; } else { cd_play.start_s=(cdinfo.c_seca%60)-secs; cd_play.start_m=cdinfo.c_seca/60; } cd_play.start_f=1; cd_play.end_s=cdinfo.s_sec[cdinfo.l_track-1]; cd_play.end_m=cdinfo.s_min[cdinfo.l_track-1]; cd_play.end_f=cdinfo.s_frame[cdinfo.l_track-1]; if(ioctl(cd_fd,CDIOCPLAYMSF,(char *) &cd_play)<0) per(); cdinfo.pause=0; } /* Spit cd out */ void eject(void) { if(ioctl (cd_fd, CDIOCALLOW)<0) per(); if(ioctl(cd_fd, CDIOCEJECT)<0) per(); close(cd_fd); cdinfo.eject=1; cdinfo.pause=1; }