Mercurial > ~darius > hgwebdir.cgi > cddb-stuff
view cddb-id.c @ 11:c122160e07da
Use Tcl 8.2
author | darius |
---|---|
date | Thu, 18 Jul 2002 06:38:42 +0000 |
parents | ad83a38c3f5a |
children |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sysexits.h> #include <fcntl.h> #include <sys/errno.h> #include <sys/ioctl.h> #include <sys/cdio.h> int cddb_sum(int n); unsigned long cddb_discid(int tot_trks, struct cd_toc_entry *cdtoc); void usage(void); int main(int argc, char **argv) { int cd_fd, tot_tracks, i, machine, disc_length, tracknums; unsigned long disc_id; struct ioc_toc_header toc_head; struct ioc_read_toc_entry toc_entries_head; struct cd_toc_entry *toc_entries; char cd_path[256], ch; /* Default CD path */ strcpy(cd_path, "/dev/cd0c"); /* Default to human readable */ machine = 0; /* Default to no track number stuff */ tracknums = 0; while ((ch = getopt(argc, argv, "f:mhn")) != -1) { switch(ch) { case 'f': if (strlen(optarg) > 255) { warnx("Filename too long"); exit(EX_USAGE); } strcpy(cd_path, optarg); break; case 'm': machine = 1; break; case 'n': tracknums = 1; break; case '?': case 'h': default: usage(); break; } } if ((cd_fd = open(cd_path, O_RDONLY)) == -1) { warnx("Failed to open %s, reason: %s", cd_path, strerror(errno)); exit(EX_IOERR); } if (ioctl(cd_fd, CDIOREADTOCHEADER, &toc_head) == -1) { warnx("Failed to get TOC header, reason: %s", strerror(errno)); exit(EX_UNAVAILABLE); } tot_tracks = toc_head.ending_track - toc_head.starting_track + 1; toc_entries = (struct cd_toc_entry *)malloc(sizeof(struct cd_toc_entry) * (tot_tracks + 1)); if (toc_entries == NULL) { warnx("Couldn't allocate memeory for TOC entries"); exit(EX_UNAVAILABLE); } toc_entries_head.data = toc_entries; toc_entries_head.data_len = sizeof(struct cd_toc_entry) * (tot_tracks + 1); toc_entries_head.starting_track = 0; toc_entries_head.address_format = CD_MSF_FORMAT; if (ioctl(cd_fd, CDIOREADTOCENTRYS, &toc_entries_head) == -1) { warnx("Failed to get TOC entries, reason: %s\n", strerror(errno)); exit(EX_UNAVAILABLE); } if (tracknums) { for (i = 1; i <= tot_tracks; i++) if (!(toc_entries[i].control & 4)) printf("%d ", i); printf("\n"); exit(0); } disc_id = cddb_discid(tot_tracks, toc_entries); disc_length = (toc_entries[tot_tracks].addr.msf.minute * 60) + (toc_entries[tot_tracks].addr.msf.second); if (machine == 0) { printf("Start track = %d, end track = %d, length = %d\n", toc_head.starting_track, toc_head.ending_track, toc_head.len); printf("Disc ID is %08x\n", disc_id); printf("Length is %d seconds\n", disc_length); } else { printf("%08x", disc_id); } for (i = 0; i < tot_tracks; i++) { if (machine == 0) { printf("Track %d, Minute = %d, Second = %d, Frame = %d, Type = %s, Offset = %d\n", toc_entries[i].track, toc_entries[i].addr.msf.minute, toc_entries[i].addr.msf.second, toc_entries[i].addr.msf.frame, (toc_entries[i].control & 4) ? "data" : "audio", (toc_entries[i].addr.msf.minute * 60 * 75) + (toc_entries[i].addr.msf.second * 75) + toc_entries[i].addr.msf.frame); } else { printf(" %d", (toc_entries[i].addr.msf.minute * 60 * 75) + (toc_entries[i].addr.msf.second * 75) + toc_entries[i].addr.msf.frame); } } if (machine == 1) { printf(" %d\n", disc_length); } } int cddb_sum(int n) { int ret; /* For backward compatibility this algorithm must not change */ ret = 0; while (n > 0) { ret = ret + (n % 10); n = n / 10; } return (ret); } unsigned long cddb_discid(int tot_trks, struct cd_toc_entry *cdtoc) { int i, t = 0, n = 0; /* For backward compatibility this algorithm must not change */ i = 0; while (i < tot_trks) { n = n + cddb_sum((cdtoc[i].addr.msf.minute * 60) + cdtoc[i].addr.msf.second); i++; } t = ((cdtoc[tot_trks].addr.msf.minute * 60) + cdtoc[tot_trks].addr.msf.second) - ((cdtoc[0].addr.msf.minute * 60) + cdtoc[0].addr.msf.second); return ((n % 0xff) << 24 | t << 8 | tot_trks); } void usage(void) { printf("Usage:\n"); printf("cddb-id [-f <cd-dev>] [-m]\n"); printf("<cd-dev> is the cd device to use (Default: /dev/cd0c)\n"); printf("-m causes machine readable output\n"); exit(EX_USAGE); }