/* Copyright WSPse * eMail: wsp@gmx.de * * These are the routines for cdrom I/O-handling * Last updated: 20/11/99 * Updated: 2000/06/24 (BSD routines by Scott Aaron Bamford) * 2001/01/07 (64bit-support for CDDB-ID) */ /* Copying: This program is free software; you can redistribute it and/or modify it under the terms of the GNU Gerneral Public License as published by the Free Soft- ware Foundation; either version 2 of License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include "mp3creat.h" #ifdef HAVE_LINUX_CDROM_H #include #endif #ifdef HAVE_SYS_CDIO_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif extern char *def_cdrom_dev; #ifdef HAVE_LINUX_CDROM_H /* Global structs from cdrom.h */ struct cdrom_tochdr tochdr; /* start and endtrack on cd */ struct cdrom_volctrl volctrl; /* structure for volume control */ struct cdrom_ti ti; /* play tracks */ struct cdrom_tocentry tocentry; /* toc entrys */ struct cdrom_subchnl sc; /* status, etc */ #else /* Global structs from cdio.h */ struct ioc_toc_header tochdr; /* start and endtrack on cd */ struct ioc_vol volctrl; /* structure for volume control */ struct ioc_play_track ti; /* play tracks */ struct ioc_read_toc_entry tocentry; /* toc entrys */ struct cd_toc_entry cddata; /* data for toc entrys */ struct cd_sub_channel_info sc; /* status, etc */ #endif /* !HAVE_LINUX_CDROM_H */ /* Globals */ struct { int min; int sec; int frame; } cdtoc[100]; /* Declerations */ unsigned long cddb_discid(int tot_trks); int track_first, track_last; int cd_drv = -1; /* values: -2: toc was read (cd ok), -1: cd failure, >=0: filedes (cd-device open) */ /* Close cdrom device, and set global id */ int close_cdrom() { if(cd_drv >= 0) { close(cd_drv); cd_drv = -2; } return cd_drv; } /* Open cdrom device, and set global id */ int open_cdrom() { close_cdrom(); cd_drv = open(def_cdrom_dev, O_RDONLY | O_NONBLOCK); if(cd_drv <= 0) cd_drv = -1; return cd_drv; } /* Send ioctl to cdrom */ int ioctl_cdrom(int cmd) { int tmp; if(cd_drv >= 0) { tmp = ioctl(cd_drv, cmd); } else { tmp = open_cdrom(); if(tmp >= 0) { tmp = ioctl(cd_drv, cmd); close_cdrom(); } } return tmp; } /* Eject CD-Rom */ int eject_cd () { int tmp; #ifdef HAVE_LINUX_CDROM_H tmp = ioctl_cdrom(CDROMEJECT); #else tmp = ioctl_cdrom(CDIOCEJECT); #endif /* !HAVE_LINUX_CDROM_H */ if(tmp != 0) return 1; return 0; /* Eject ok */ } /* Close the tray of cdrom-drive */ int close_tray () { int tmp; #ifdef HAVE_LINUX_CDROM_H tmp = ioctl_cdrom(CDROMCLOSETRAY); #else tmp = ioctl_cdrom(CDIOCCLOSE); #endif /* !HAVE_LINUX_CDROM_H */ if(tmp != 0) return 1; /* closing the tray failed... */ return 0; /* Tray closed */ } /* init new cdrom volume */ int init_cd () { int tmp; int i; BOOL closeing_needed; track_first = 0; track_last = 0; closeing_needed = FALSE; if(cd_drv < 0) { if(open_cdrom() < 0) { return -1; } closeing_needed = TRUE; } #ifdef HAVE_LINUX_CDROM_H tmp = ioctl(cd_drv, CDROMREADTOCHDR, &tochdr); /* read header of toc */ #else tmp = ioctl(cd_drv, CDIOREADTOCHEADER, &tochdr); /* read header of toc */ #endif /* !HAVE_LINUX_CDROM_H */ if(tmp != 0) { if(closeing_needed) close_cdrom(); return -1; } #ifdef HAVE_LINUX_CDROM_H track_first = tochdr.cdth_trk0; track_last = tochdr.cdth_trk1; tocentry.cdte_track = CDROM_LEADOUT; tocentry.cdte_format = CDROM_MSF; #else track_first = tochdr.starting_track; track_last = tochdr.ending_track; #ifndef CDROM_LEADOUT #define CDROM_LEADOUT 0xAA #endif /* !CDROM_LEADOUT */ tocentry.starting_track = CDROM_LEADOUT; tocentry.address_format = CD_MSF_FORMAT; #endif /* !HAVE_LINUX_CDROM_H */ #ifdef HAVE_LINUX_CDROM_H if(ioctl(cd_drv, CDROMREADTOCENTRY, &tocentry) != 0) { #else tocentry.data = &cddata; tocentry.data_len = sizeof(cddata); if(ioctl(cd_drv, CDIOREADTOCENTRYS, &tocentry) != 0) { #endif /* !HAVE_LINUX_CDROM_H */ if(closeing_needed) close_cdrom(); return -1; } #ifdef HAVE_LINUX_CDROM_H cdtoc[track_last].min = tocentry.cdte_addr.msf.minute; cdtoc[track_last].sec = tocentry.cdte_addr.msf.second; cdtoc[track_last].frame = tocentry.cdte_addr.msf.frame; #else cdtoc[track_last].min = tocentry.data->addr.msf.minute; cdtoc[track_last].sec = tocentry.data->addr.msf.second; cdtoc[track_last].frame = tocentry.data->addr.msf.frame; #endif /* !HAVE_LINUX_CDROM_H */ for(i=track_last;i>=track_first;i--) { #ifdef HAVE_LINUX_CDROM_H tocentry.cdte_track = i; tocentry.cdte_format = CDROM_MSF; if(ioctl(cd_drv, CDROMREADTOCENTRY, &tocentry) != 0) { #else tocentry.starting_track = i; tocentry.address_format = CD_MSF_FORMAT; if(ioctl(cd_drv, CDIOREADTOCENTRYS, &tocentry) == -1) { #endif /* !HAVE_LINUX_CDROM_H */ if(closeing_needed) close_cdrom(); return -1; } #ifdef HAVE_LINUX_CDROM_H cdtoc[i-1].min = tocentry.cdte_addr.msf.minute; cdtoc[i-1].sec = tocentry.cdte_addr.msf.second; cdtoc[i-1].frame = tocentry.cdte_addr.msf.frame; #else cdtoc[i-1].min = tocentry.data->addr.msf.minute; cdtoc[i-1].sec = tocentry.data->addr.msf.second; cdtoc[i-1].frame = tocentry.data->addr.msf.frame; #endif /* !HAVE_LINUX_CDROM_H */ } if(closeing_needed) close_cdrom(); return 0; } /* hard reset drive */ int hard_reset () { int tmp; #ifdef HAVE_LINUX_CDROM_H tmp = ioctl_cdrom(CDROMRESET); #else tmp = ioctl_cdrom(CDIOCRESET); #endif /* !HAVE_LINUX_CDROM_H */ return tmp; } /* play (a) track(s) */ int play_track (int tr_begin, int tr_end) { int tmp; #ifdef HAVE_LINUX_CDROM_H ti.cdti_trk0 = tr_begin; ti.cdti_trk1 = tr_end; ti.cdti_ind0 = 0; ti.cdti_ind1 = 0; #else ti.start_track = tr_begin; ti.end_track = tr_end; ti.start_index = 0; ti.end_index = 0; #endif /* !HAVE_LINUX_CDROM_H */ if(cd_drv < 0) { if(open_cdrom() < 0) { return -1; } #ifdef HAVE_LINUX_CDROM_H tmp = ioctl(cd_drv, CDROMPLAYTRKIND, &ti); #else tmp = ioctl(cd_drv, CDIOCPLAYTRACKS, &ti); #endif /* !HAVE_LINUX_CDROM_H */ close_cdrom(); } else { #ifdef HAVE_LINUX_CDROM_H tmp = ioctl(cd_drv, CDROMPLAYTRKIND, &ti); #else tmp = ioctl(cd_drv, CDIOCPLAYTRACKS, &ti); #endif /* !HAVE_LINUX_CDROM_H */ } if(tmp != 0) return -1; return 0; } /* Stop CD */ int stop_cd () { int tmp; #ifdef HAVE_LINUX_CDROM_H tmp = ioctl_cdrom(CDROMSTOP); #else tmp = ioctl_cdrom(CDIOCSTOP); #endif /* !HAVE_LINUX_CDROM_H */ if(tmp != 0) return -1; return 0; } /* Pause CD */ int pause_cd () { int tmp; #ifdef HAVE_LINUX_CDROM_H tmp = ioctl_cdrom(CDROMPAUSE); #else tmp = ioctl_cdrom(CDIOCPAUSE); #endif /* !HAVE_LINUX_CDROM_H */ if(tmp != 0) return -1; return 0; } /* Resume Pause */ int resume_cd () { int tmp; #ifdef HAVE_LINUX_CDROM_H tmp = ioctl_cdrom(CDROMRESUME); #else tmp = ioctl_cdrom(CDIOCRESUME); #endif /* !HAVE_LINUX_CDROM_H */ if(tmp != 0) return -1; return 0; } /*-----Original Routines for calculating disc-id-----*/ /*-----see "cddb.howto" for copyrights---------------*/ int cddb_sum(int n) { int ret; ret = 0; while (n > 0) { ret = ret + (n % 10); n = n / 10; } return (ret); } unsigned long cddb_discid(int tot_trks) { int i,t,n; i = 0; t = 0; n = 0; while (i < tot_trks) { n = n + cddb_sum((cdtoc[i].min * 60) + cdtoc[i].sec); i++; } t = ((cdtoc[tot_trks].min * 60) + cdtoc[tot_trks].sec) - ((cdtoc[0].min * 60) + cdtoc[0].sec); /* changed for 64-bit compatibilty * Matthias Hensler, 2001/01/07 */ return ((n % 0xff) << 24 | t << 8 | tot_trks) & 0xffffffff; } /*-----end-----*/