00001 #include <freedb/freedb.hxx>
00002
00003 #include <sys/ioctl.h>
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006 #include <fcntl.h>
00007
00020 vector<TrackPosition> Freedb::getTrackOffsets(string device = "/dev/cdrom")
00021 {
00022
00023 int fd = open(device.c_str(), O_RDONLY | O_NONBLOCK);
00024 if (fd == (-1))
00025 {
00026 Error err;
00027
00028 err.errcode = errno;
00029 err.errmsg = "Error while opening CD-ROM device " + device;
00030 err.extinfo = strerror(errno);
00031
00032 throw(err);
00033 }
00034
00035
00036 struct cdrom_tochdr header;
00037 int retval = ioctl(fd, CDROMREADTOCHDR, &header);
00038 if (fd == (-1))
00039 {
00040 Error err;
00041
00042 err.errcode = errno;
00043 err.errmsg = "Error while reading TOC header on " + device;
00044 err.extinfo = strerror(errno);
00045
00046 throw(err);
00047 }
00048 int num_tracks = header.cdth_trk1;
00049
00050
00051 TrackPosition offset;
00052 vector<TrackPosition> offsets;
00053 struct cdrom_tocentry te;
00054 int pos_frames;
00055
00056 for (int i = 0; i <= num_tracks; i++)
00057 {
00058
00059 te.cdte_track = (i == num_tracks ? CDROM_LEADOUT : i + 1);
00060 te.cdte_format = CDROM_MSF;
00061
00062 retval = ioctl(fd, CDROMREADTOCENTRY, &te);
00063 if (retval == (-1))
00064 {
00065 Error err;
00066
00067 err.errcode = errno;
00068 err.errmsg = "Error while reading TOC entry of track " + itos(i) + " on " + device;
00069 err.extinfo = strerror(errno);
00070
00071 throw(err);
00072 }
00073
00074 offset.min = static_cast<int>(te.cdte_addr.msf.minute);
00075 offset.sec = static_cast<int>(te.cdte_addr.msf.second);
00076 offset.frame = static_cast<int>(te.cdte_addr.msf.frame);
00077
00078 offsets.push_back(offset);
00079
00080
00081
00082
00083
00084
00085
00086 }
00087
00088
00089 return(offsets);
00090 }
00091
00092 int Freedb::generateDiscSum(int n)
00093 {
00094 int sum = 0;
00095
00096 while (n > 0)
00097 {
00098 sum += (n % 10);
00099 n = n / 10;
00100 }
00101
00102 return(sum);
00103 }
00104
00105 unsigned long Freedb::generateDiscID(const vector<TrackPosition> offsets, const int num_tracks)
00106 {
00107 int i = 0, t = 0, n = 0;
00108
00109 while (i < num_tracks)
00110 {
00111 n += Freedb::generateDiscSum((offsets[i].min * 60) + offsets[i].sec);
00112 i++;
00113 }
00114
00115 t = ((offsets[num_tracks].min * 60) + offsets[num_tracks].sec) -
00116 ((offsets[0].min * 60) + offsets[0].sec);
00117
00118 return((n % 0xff) << 24 | t << 8 | num_tracks);
00119 }
00120
00121
00127 unsigned long Freedb::getDiscID(string device = "/dev/cdrom")
00128 {
00129 vector<TrackPosition> offsets;
00130
00131 try
00132 {
00133 offsets = Freedb::getTrackOffsets();
00134 }
00135 catch(const Error& err)
00136 {
00137 throw err;
00138 }
00139
00140 int num_tracks = 0;
00141
00142 vector<TrackPosition>::const_iterator i = offsets.begin();
00143
00144 while (i != offsets.end())
00145 {
00146 num_tracks++;
00147 i++;
00148 }
00149
00150 return(Freedb::generateDiscID(offsets, num_tracks - 1));
00151 }