|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /*
- * 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 "%P \"%T\" (%N tracks)\n"
- #define T_TEMPLATE "%n: %p \"%t\"\n"
-
- char *progname;
- char *d_template = D_TEMPLATE; /* disc template */
- char *t_template = T_TEMPLATE; /* track template */
-
- 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)
- {
- 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;
- /* 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 (optind == argc) {
- info("-", format);
- } else {
- for (; optind < argc; optind++)
- info(argv[optind], format);
- }
-
- return 0;
- }
|