You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

287 lines
5.5 KiB

  1. /*
  2. * cueprint.c -- print cd information based on a template
  3. *
  4. * Copyright (C) 2004 Svend Sorensen
  5. * For license terms, see the file COPYING in this distribution.
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h> /* exit() */
  9. #include <string.h> /* strcmp() */
  10. #include <unistd.h> /* getopt() */
  11. #include <ctype.h> /* isdigit() */
  12. #include "cuefile.h"
  13. /* default templates */
  14. #define D_TEMPLATE "%P \"%T\" (%N tracks)\n"
  15. #define T_TEMPLATE "%n: %p \"%t\"\n"
  16. char *progname;
  17. char *d_template = D_TEMPLATE; /* disc template */
  18. char *t_template = T_TEMPLATE; /* track template */
  19. void usage (int status)
  20. {
  21. if (0 == status) {
  22. fprintf(stdout, "%s: usage: cueprint [-h] [-i cue|toc] [-d TEMPLATE] [-t TEMPLATE] [file...]\n", progname);
  23. fputs("\
  24. \n\
  25. OPTIONS\n\
  26. -h print usage\n\
  27. -i cue|toc set format of file(s)\n\
  28. -d TEMPLATE set disc template (see TEMPLATE EXPANSION)\n\
  29. -t TEMPLATE set track template (see TEMPLATE EXPANSION)\n\
  30. \n\
  31. Template Expansion\n\
  32. Disc:\n\
  33. %A - album arranger\n\
  34. %C - album composer\n\
  35. %G - album genre\n\
  36. %M - album message\n\
  37. %N - number of tracks\n\
  38. %P - album performer\n\
  39. %S - album songwriter\n\
  40. %T - album title\n\
  41. %U - album UPC/EAN\n\
  42. Track:\n\
  43. %a - track arranger\n\
  44. %c - track composer\n\
  45. %g - track genre\n\
  46. %i - track ISRC\n\
  47. %m - track message\n\
  48. %n - track number\n\
  49. %p - track perfomer\n\
  50. %t - track title\n\
  51. %u - track ISRC (CD-TEXT)\n\
  52. \n\
  53. Any other %<character> is expanded to that character. For example, to get a\n\
  54. '%', use %%.\n\
  55. ", stdout);
  56. fprintf(stdout, "default disc template is:\n\"%s\"\n", D_TEMPLATE);
  57. fprintf(stdout, "default track template is:\n\"%s\"\n", T_TEMPLATE);
  58. } else {
  59. fprintf(stderr, "%s: syntax error\n", progname);
  60. fprintf(stderr, "run `%s -h' for usage\n", progname);
  61. }
  62. exit (status);
  63. }
  64. void disc_field (char *c, Cd *cd)
  65. {
  66. Cdtext *cdtext = NULL;
  67. cdtext = cd_get_cdtext(cd);
  68. switch (*c) {
  69. case 'A':
  70. printf("%s", cdtext_get(PTI_ARRANGER, cdtext));
  71. break;
  72. case 'C':
  73. printf("%s", cdtext_get(PTI_COMPOSER, cdtext));
  74. break;
  75. case 'G':
  76. printf("%s", cdtext_get(PTI_GENRE, cdtext));
  77. break;
  78. case 'M':
  79. printf("%s", cdtext_get(PTI_MESSAGE, cdtext));
  80. break;
  81. case 'N':
  82. printf("%0*d", 2, cd_get_ntrack(cd));
  83. break;
  84. case 'P':
  85. printf("%s", cdtext_get(PTI_PERFORMER, cdtext));
  86. break;
  87. case 'R':
  88. printf("%s", cdtext_get(PTI_ARRANGER, cdtext));
  89. break;
  90. case 'S':
  91. printf("%s", cdtext_get(PTI_SONGWRITER, cdtext));
  92. break;
  93. case 'T':
  94. printf("%s", cdtext_get(PTI_TITLE, cdtext));
  95. break;
  96. case 'U':
  97. printf("%s", cdtext_get(PTI_UPC_ISRC, cdtext));
  98. break;
  99. default:
  100. putchar(*c);
  101. break;
  102. }
  103. }
  104. void track_field (char *c, Cd *cd, int trackno, int width)
  105. {
  106. Track *track = NULL;
  107. Cdtext *cdtext = NULL;
  108. track = cd_get_track(cd, trackno);
  109. cdtext = track_get_cdtext(track);
  110. switch (*c) {
  111. case 'a':
  112. printf("%*s", width, cdtext_get(PTI_ARRANGER, cdtext));
  113. break;
  114. case 'c':
  115. printf("%*s", width, cdtext_get(PTI_COMPOSER, cdtext));
  116. break;
  117. case 'f':
  118. printf("%*s", width, track_get_filename(track));
  119. break;
  120. case 'g':
  121. printf("%*s", width, cdtext_get(PTI_GENRE, cdtext));
  122. break;
  123. case 'i':
  124. printf("%*s", width, track_get_isrc(track));
  125. break;
  126. case 'm':
  127. printf("%*s", width, cdtext_get(PTI_MESSAGE, cdtext));
  128. break;
  129. case 'n':
  130. printf("%0*d", width, trackno);
  131. break;
  132. case 'p':
  133. printf("%*s", width, cdtext_get(PTI_PERFORMER, cdtext));
  134. break;
  135. case 's':
  136. printf("%*s", width, cdtext_get(PTI_SONGWRITER, cdtext));
  137. break;
  138. case 't':
  139. printf("%*s", width, cdtext_get(PTI_TITLE, cdtext));
  140. break;
  141. case 'u':
  142. printf("%*s", width, cdtext_get(PTI_UPC_ISRC, cdtext));
  143. break;
  144. default:
  145. disc_field(c, cd);
  146. break;
  147. }
  148. }
  149. void print_info (Cd *cd)
  150. {
  151. int i; /* track */
  152. char *c;
  153. /* field flags */
  154. int flag = 1; /* flags remain */
  155. int zeropad = 0;
  156. /* field width */
  157. int width;
  158. for (c = d_template; '\0' != *c; c++) {
  159. if ('%' == *c) {
  160. c++;
  161. disc_field(c, cd);
  162. } else {
  163. putchar(*c);
  164. }
  165. }
  166. for (i = 1; i <= cd_get_ntrack(cd); i++) {
  167. for (c = t_template; '\0' != *c; c++) {
  168. /* TODO: should apply escapes and width to disc
  169. * template as well
  170. */
  171. if ('\\' == *c) {
  172. c++;
  173. /* TODO: add more (all?) escapes */
  174. switch (*c) {
  175. case 'n':
  176. putchar('\n');
  177. break;
  178. case 't':
  179. putchar('\t');
  180. break;
  181. default:
  182. putchar(*c);
  183. break;
  184. }
  185. } else if ('%' == *c) {
  186. c++;
  187. /* parse flags */
  188. /* TODO: zero-padding does nothing */
  189. do {
  190. switch (*c) {
  191. case '0': /* zero-padding */
  192. c++;
  193. zeropad = 1;
  194. break;
  195. default:
  196. flag = 0;
  197. }
  198. } while (0 != flag);
  199. /* parse width */
  200. width = 0;
  201. while (0 != isdigit(*c)) {
  202. width = width * 10 + *c++ - '0';
  203. }
  204. track_field(c, cd, i, width);
  205. } else {
  206. putchar(*c);
  207. }
  208. }
  209. }
  210. }
  211. int info (char *name, int format)
  212. {
  213. Cd *cd = NULL;
  214. if (NULL == (cd = cf_parse(name, &format))) {
  215. fprintf(stderr, "%s: input file error\n", name);
  216. return -1;
  217. }
  218. print_info(cd);
  219. return 0;
  220. }
  221. int main (int argc, char **argv)
  222. {
  223. int format = UNKNOWN;
  224. /* getopt () variables */
  225. char c;
  226. extern char *optarg;
  227. extern int optind;
  228. progname = *argv;
  229. while (-1 != (c = getopt(argc, argv, "hi:d:t:"))) {
  230. switch (c) {
  231. case 'h':
  232. usage(0);
  233. break;
  234. case 'i':
  235. if (0 == strcmp("cue", optarg))
  236. format = CUE;
  237. else if (0 == strcmp("toc", optarg))
  238. format = TOC;
  239. break;
  240. case 'd':
  241. d_template = optarg;
  242. break;
  243. case 't':
  244. t_template = optarg;
  245. break;
  246. default:
  247. usage(1);
  248. break;
  249. }
  250. }
  251. if (optind == argc) {
  252. info("-", format);
  253. } else {
  254. for (; optind < argc; optind++)
  255. info(argv[optind], format);
  256. }
  257. return 0;
  258. }