view cddb-id.c @ 3:74031379d3cb CDDB-STUFF_1_0

Initial revision
author darius
date Wed, 09 Aug 2000 02:18:47 +0000
parents
children ad83a38c3f5a
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_RDWR)) == -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);
}