Plan 9 from Bell Labs’s /usr/web/sources/contrib/cnielsen/cuetools/cueprint.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/* 
 * cueprint.c -- print cd information based on a template
 *
 * Copyright (C) 2004 Svend Sorensen
 * For license terms, see the file COPYING in this distribution.
 */

#include <stdio.h>
#include <stdlib.h>		/* exit() */
#include <string.h>		/* strcmp() */
#include <unistd.h>		/* getopt() */
#include <ctype.h>		/* isdigit() */
#include "cuefile.h"

/* default templates */

#define D_TEMPLATE "\
Disc Information\n\
arranger:	%A\n\
composer:	%C\n\
genre:		%G\n\
message:	%M\n\
no. of tracks:	%N\n\
performer:	%P\n\
songwriter:	%S\n\
title:		%T\n\
UPC/EAN:	%U\n\
"

#define T_TEMPLATE "\
\n\
Track %n Information\n\
arranger:	%a\n\
composer:	%c\n\
genre:		%g\n\
ISRC:		%i\n\
message:	%m\n\
track number:	%n\n\
perfomer:	%p\n\
title:		%t\n\
ISRC (CD-TEXT):	%u\n\
"

char *progname;

void usage (int status)
{
	if (0 == status) {
		fprintf(stdout, "%s: usage: cueprint [-h] [-i cue|toc] [-d TEMPLATE] [-t TEMPLATE] [file...]\n", progname);
		fputs("\
\n\
OPTIONS\n\
-h 			print usage\n\
-i cue|toc		set format of file(s)\n\
-d TEMPLATE		set disc template (see TEMPLATE EXPANSION)\n\
-t TEMPLATE		set track template (see TEMPLATE EXPANSION)\n\
\n\
Template Expansion\n\
Disc:\n\
%A - album arranger\n\
%C - album composer\n\
%G - album genre\n\
%M - album message\n\
%N - number of tracks\n\
%P - album performer\n\
%S - album songwriter\n\
%T - album title\n\
%U - album UPC/EAN\n\
Track:\n\
%a - track arranger\n\
%c - track composer\n\
%g - track genre\n\
%i - track ISRC\n\
%m - track message\n\
%n - track number\n\
%p - track perfomer\n\
%t - track title\n\
%u - track ISRC (CD-TEXT)\n\
\n\
Any other %<character> is expanded to that character.  For example, to get a\n\
'%', use %%.\n\
", stdout);
		fprintf(stdout, "default disc template is:\n%s\n", D_TEMPLATE);
		fprintf(stdout, "default track template is:\n%s\n", T_TEMPLATE);
	} else {
		fprintf(stderr, "%s: syntax error\n", progname);
		fprintf(stderr, "run `%s -h' for usage\n", progname);
	}

	exit (status);
}

void disc_field (char *conv, int length, Cd *cd)
{
	char *c;	/* pointer to conversion character */

	Cdtext *cdtext = NULL;
	cdtext = cd_get_cdtext(cd);

	c = conv + length - 1;

	switch (*c) {
	case 'A':
		*c = 's';
		printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
		break;
	case 'C':
		*c = 's';
		printf(conv, cdtext_get(PTI_COMPOSER, cdtext));
		break;
	case 'G':
		*c = 's';
		printf(conv, cdtext_get(PTI_GENRE, cdtext));
		break;
	case 'M':
		*c = 's';
		printf(conv, cdtext_get(PTI_MESSAGE, cdtext));
		break;
	case 'N':
		*c = 'd';	/* tracks is an integer */
		printf(conv, cd_get_ntrack(cd));
		break;
	case 'P':
		*c = 's';
		printf(conv, cdtext_get(PTI_PERFORMER, cdtext));
		break;
	case 'R':
		*c = 's';
		printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
		break;
	case 'S':
		*c = 's';
		printf(conv, cdtext_get(PTI_SONGWRITER, cdtext));
		break;
	case 'T':
		*c = 's';
		printf(conv, cdtext_get(PTI_TITLE, cdtext));
		break;
	case 'U':
		*c = 's';
		printf(conv, cdtext_get(PTI_UPC_ISRC, cdtext));
		break;
	default:
		putchar(*c);
		break;
	}
}

void track_field (char *conv, int length, Cd *cd, int trackno)
{
	char *c;	/* pointer to conversion character */

	Track *track = NULL;
	Cdtext *cdtext = NULL;

	track = cd_get_track(cd, trackno);
	cdtext = track_get_cdtext(track);

	c = conv + length - 1;

	switch (*c) {
	case 'a':
		*c = 's';
		printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
		break;
	case 'c':
		*c = 's';
		printf(conv, cdtext_get(PTI_COMPOSER, cdtext));
		break;
	case 'f':
		*c = 's';
		printf(conv, track_get_filename(track));
		break;
	case 'g':
		*c = 's';
		printf(conv, cdtext_get(PTI_GENRE, cdtext));
		break;
	case 'i':
		*c = 's';
		printf(conv, track_get_isrc(track));
		break;
	case 'm':
		*c = 's';
		printf(conv, cdtext_get(PTI_MESSAGE, cdtext));
		break;
	case 'n':
		*c = 'd';	/* track number is an integer */
		printf(conv, trackno);
		break;
	case 'p':
		*c = 's';
		printf(conv, cdtext_get(PTI_PERFORMER, cdtext));
		break;
	case 's':
		*c = 's';
		printf(conv, cdtext_get(PTI_SONGWRITER, cdtext));
		break;
	case 't':
		*c = 's';
		printf(conv, cdtext_get(PTI_TITLE, cdtext));
		break;
	case 'u':
		*c = 's';
		printf(conv, cdtext_get(PTI_UPC_ISRC, cdtext));
		break;
	default:
		disc_field(conv, length, cd);
		break;
	}
}

/* print a % conversion specification
 * %[flag(s)][width][.precision]<conversion-char>
 */
void print_conv (char *start, int length, Cd *cd, int trackno)
{
	char *conv;	/* copy of conversion specification */

	/* TODO: use strndup? */
	conv = malloc ((unsigned) (length + 1));
	strncpy(conv, start, length);
	conv[length] = '\0';

	/* conversion character */
	if (0 == trackno)
		disc_field(conv, length, cd);
	else
		track_field(conv, length, cd, trackno);

	free(conv);
}

/* print an single-character escape
 * `c' is the character after the `/'
 * NOTE: this does not handle octal and hexidecimal escapes
 *       except for \0
 */
void print_esc (char *c)
{
	switch (*c) {
		case 'a':
			putchar('\a');
			break;
		case 'b':
			putchar('\b');
			break;
		case 'f':
			putchar('\f');
			break;
		case 'n':
			putchar('\n');
			break;
		case 'r':
			putchar('\r');
			break;
		case 't':
			putchar('\t');
			break;
		case 'v':
			putchar('\v');
			break;
		case '0':
			putchar('\0');
			break;
		default:
			/* ?, ', " are handled by the default */
			putchar(*c);
			break;
	}
}

void cd_printf (char *format, Cd *cd, int trackno)
{
	char *c;	/* pointer into format */
	char *conv_start;
	int conv_length;

	for (c = format; '\0' != *c; c++) {
		switch (*c) {
		case '%':
			conv_start = c;
			conv_length = 1;
			c++;

			/* flags */
			while ( \
				'-' == *c \
				|| '+' == *c \
				|| ' ' == *c \
				|| '0' == *c \
				|| '#' == *c \
			) {
				conv_length++;
				c++;
			}

			/* field width */
			/* '*' not recognized */
			while (0 != isdigit(*c)) {
				conv_length++;
				c++;
			}
			
			/* precision */
			/* '*' not recognized */
			if ('.' == *c) {
				conv_length++;
				c++;

				while (0 != isdigit(*c)) {
					conv_length++;
					c++;
				}
			}

			/* length modifier (h, l, or L) */
			/* not recognized */

			/* conversion character */
			conv_length++;

			print_conv(conv_start, conv_length, cd, trackno);
			break;
		case '\\':
			c++;

			print_esc(c);
			break;
		default:
			putchar(*c);
			break;
		}
	}
}

int info (char *name, int format, char *d_template, char *t_template)
{
	Cd *cd = NULL;
	int i;		/* track number */

	if (NULL == (cd = cf_parse(name, &format))) {
		fprintf(stderr, "%s: input file error\n", name);
		return -1;
	}

	cd_printf(d_template, cd, 0);

	for (i = 1; i <= cd_get_ntrack(cd); i++) {
		cd_printf(t_template, cd, i);
	}

	return 0;
}

int main (int argc, char **argv)
{
	int format = UNKNOWN;
	char *d_template = NULL;	/* disc template */
	char *t_template = NULL;	/* track template */
	/* getopt () variables */
	char c;
	extern char *optarg;
	extern int optind;

	progname = *argv;

	while (-1 != (c = getopt(argc, argv, "hi:d:t:"))) {
		switch (c) {
		case 'h':
			usage(0);
			break;
		case 'i':
			if (0 == strcmp("cue", optarg))
				format = CUE;
			else if (0 == strcmp("toc", optarg))
				format = TOC;
			break;
		case 'd':
			d_template = optarg;
			break;
		case 't':
			t_template = optarg;
			break;
		default:
			usage(1);
			break;
		}
	}

	/* if no disc or track template is set, use the defaults for both */
	if (NULL == d_template && NULL == t_template) {
		d_template = D_TEMPLATE;
		t_template = T_TEMPLATE;
	} else {
		if (NULL == d_template)
			d_template = "";

		if (NULL == t_template)
			t_template = "";
	}

	if (optind == argc) {
		info("-", format, d_template, t_template);
	} else {
		for (; optind < argc; optind++)
			info(argv[optind], format, d_template, t_template);
	}

	return 0;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.