Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 
 

411 Zeilen
7.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 "\
  15. Disc Information\n\
  16. arranger: %A\n\
  17. composer: %C\n\
  18. genre: %G\n\
  19. message: %M\n\
  20. no. of tracks: %N\n\
  21. performer: %P\n\
  22. songwriter: %S\n\
  23. title: %T\n\
  24. UPC/EAN: %U\n\
  25. "
  26. #define T_TEMPLATE "\
  27. \n\
  28. Track %n Information\n\
  29. arranger: %a\n\
  30. composer: %c\n\
  31. genre: %g\n\
  32. ISRC: %i\n\
  33. message: %m\n\
  34. track number: %n\n\
  35. perfomer: %p\n\
  36. title: %t\n\
  37. ISRC (CD-TEXT): %u\n\
  38. "
  39. char *progname;
  40. char *d_template = NULL; /* disc template */
  41. char *t_template = NULL; /* track template */
  42. void usage (int status)
  43. {
  44. if (0 == status) {
  45. fprintf(stdout, "%s: usage: cueprint [-h] [-i cue|toc] [-d TEMPLATE] [-t TEMPLATE] [file...]\n", progname);
  46. fputs("\
  47. \n\
  48. OPTIONS\n\
  49. -h print usage\n\
  50. -i cue|toc set format of file(s)\n\
  51. -d TEMPLATE set disc template (see TEMPLATE EXPANSION)\n\
  52. -t TEMPLATE set track template (see TEMPLATE EXPANSION)\n\
  53. \n\
  54. Template Expansion\n\
  55. Disc:\n\
  56. %A - album arranger\n\
  57. %C - album composer\n\
  58. %G - album genre\n\
  59. %M - album message\n\
  60. %N - number of tracks\n\
  61. %P - album performer\n\
  62. %S - album songwriter\n\
  63. %T - album title\n\
  64. %U - album UPC/EAN\n\
  65. Track:\n\
  66. %a - track arranger\n\
  67. %c - track composer\n\
  68. %g - track genre\n\
  69. %i - track ISRC\n\
  70. %m - track message\n\
  71. %n - track number\n\
  72. %p - track perfomer\n\
  73. %t - track title\n\
  74. %u - track ISRC (CD-TEXT)\n\
  75. \n\
  76. Any other %<character> is expanded to that character. For example, to get a\n\
  77. '%', use %%.\n\
  78. ", stdout);
  79. fprintf(stdout, "default disc template is:\n%s\n", D_TEMPLATE);
  80. fprintf(stdout, "default track template is:\n%s\n", T_TEMPLATE);
  81. } else {
  82. fprintf(stderr, "%s: syntax error\n", progname);
  83. fprintf(stderr, "run `%s -h' for usage\n", progname);
  84. }
  85. exit (status);
  86. }
  87. void disc_field (char *conv, int length, Cd *cd)
  88. {
  89. char *c; /* pointer to conversion character */
  90. Cdtext *cdtext = NULL;
  91. cdtext = cd_get_cdtext(cd);
  92. c = conv + length - 1;
  93. switch (*c) {
  94. case 'A':
  95. *c = 's';
  96. printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
  97. break;
  98. case 'C':
  99. *c = 's';
  100. printf(conv, cdtext_get(PTI_COMPOSER, cdtext));
  101. break;
  102. case 'G':
  103. *c = 's';
  104. printf(conv, cdtext_get(PTI_GENRE, cdtext));
  105. break;
  106. case 'M':
  107. *c = 's';
  108. printf(conv, cdtext_get(PTI_MESSAGE, cdtext));
  109. break;
  110. case 'N':
  111. *c = 'd'; /* tracks is an integer */
  112. printf(conv, cd_get_ntrack(cd));
  113. break;
  114. case 'P':
  115. *c = 's';
  116. printf(conv, cdtext_get(PTI_PERFORMER, cdtext));
  117. break;
  118. case 'R':
  119. *c = 's';
  120. printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
  121. break;
  122. case 'S':
  123. *c = 's';
  124. printf(conv, cdtext_get(PTI_SONGWRITER, cdtext));
  125. break;
  126. case 'T':
  127. *c = 's';
  128. printf(conv, cdtext_get(PTI_TITLE, cdtext));
  129. break;
  130. case 'U':
  131. *c = 's';
  132. printf(conv, cdtext_get(PTI_UPC_ISRC, cdtext));
  133. break;
  134. default:
  135. putchar(*c);
  136. break;
  137. }
  138. }
  139. void track_field (char *conv, int length, Cd *cd, int trackno)
  140. {
  141. char *c; /* pointer to conversion character */
  142. Track *track = NULL;
  143. Cdtext *cdtext = NULL;
  144. track = cd_get_track(cd, trackno);
  145. cdtext = track_get_cdtext(track);
  146. c = conv + length - 1;
  147. switch (*c) {
  148. case 'a':
  149. *c = 's';
  150. printf(conv, cdtext_get(PTI_ARRANGER, cdtext));
  151. break;
  152. case 'c':
  153. *c = 's';
  154. printf(conv, cdtext_get(PTI_COMPOSER, cdtext));
  155. break;
  156. case 'f':
  157. *c = 's';
  158. printf(conv, track_get_filename(track));
  159. break;
  160. case 'g':
  161. *c = 's';
  162. printf(conv, cdtext_get(PTI_GENRE, cdtext));
  163. break;
  164. case 'i':
  165. *c = 's';
  166. printf(conv, track_get_isrc(track));
  167. break;
  168. case 'm':
  169. *c = 's';
  170. printf(conv, cdtext_get(PTI_MESSAGE, cdtext));
  171. break;
  172. case 'n':
  173. *c = 'd'; /* track number is an integer */
  174. printf(conv, trackno);
  175. break;
  176. case 'p':
  177. *c = 's';
  178. printf(conv, cdtext_get(PTI_PERFORMER, cdtext));
  179. break;
  180. case 's':
  181. *c = 's';
  182. printf(conv, cdtext_get(PTI_SONGWRITER, cdtext));
  183. break;
  184. case 't':
  185. *c = 's';
  186. printf(conv, cdtext_get(PTI_TITLE, cdtext));
  187. break;
  188. case 'u':
  189. *c = 's';
  190. printf(conv, cdtext_get(PTI_UPC_ISRC, cdtext));
  191. break;
  192. default:
  193. disc_field(conv, length, cd);
  194. break;
  195. }
  196. }
  197. /* print a % conversion specification
  198. * %[flag(s)][width][.precision]<conversion-char>
  199. */
  200. void print_conv (char *start, int length, Cd *cd, int trackno)
  201. {
  202. char *conv; /* copy of conversion specification */
  203. /* TODO: use strndup? */
  204. conv = malloc ((unsigned) (length + 1));
  205. strncpy(conv, start, length);
  206. conv[length] = '\0';
  207. /* conversion character */
  208. if (0 == trackno)
  209. disc_field(conv, length, cd);
  210. else
  211. track_field(conv, length, cd, trackno);
  212. free(conv);
  213. }
  214. /* print an single-character escape
  215. * `c' is the character after the `/'
  216. * NOTE: this does not handle octal and hexidecimal escapes
  217. * except for \0
  218. */
  219. void print_esc (char *c)
  220. {
  221. switch (*c) {
  222. case 'a':
  223. putchar('\a');
  224. break;
  225. case 'b':
  226. putchar('\b');
  227. break;
  228. case 'f':
  229. putchar('\f');
  230. break;
  231. case 'n':
  232. putchar('\n');
  233. break;
  234. case 'r':
  235. putchar('\r');
  236. break;
  237. case 't':
  238. putchar('\t');
  239. break;
  240. case 'v':
  241. putchar('\v');
  242. break;
  243. case '0':
  244. putchar('\0');
  245. break;
  246. default:
  247. /* ?, ', " are handled by the default */
  248. putchar(*c);
  249. break;
  250. }
  251. }
  252. void cd_printf (char *format, Cd *cd, int trackno)
  253. {
  254. char *c; /* pointer into format */
  255. char *conv_start;
  256. int conv_length;
  257. for (c = format; '\0' != *c; c++) {
  258. switch (*c) {
  259. case '%':
  260. conv_start = c;
  261. conv_length = 1;
  262. c++;
  263. /* flags */
  264. while ( \
  265. '-' == *c \
  266. || '+' == *c \
  267. || ' ' == *c \
  268. || '0' == *c \
  269. || '#' == *c \
  270. ) {
  271. conv_length++;
  272. c++;
  273. }
  274. /* field width */
  275. /* '*' not recognized */
  276. while (0 != isdigit(*c)) {
  277. conv_length++;
  278. c++;
  279. }
  280. /* precision */
  281. /* '*' not recognized */
  282. if ('.' == *c) {
  283. conv_length++;
  284. c++;
  285. while (0 != isdigit(*c)) {
  286. conv_length++;
  287. c++;
  288. }
  289. }
  290. /* length modifier (h, l, or L) */
  291. /* not recognized */
  292. /* conversion character */
  293. conv_length++;
  294. print_conv(conv_start, conv_length, cd, trackno);
  295. break;
  296. case '\\':
  297. c++;
  298. print_esc(c);
  299. break;
  300. default:
  301. putchar(*c);
  302. break;
  303. }
  304. }
  305. }
  306. int info (char *name, int format)
  307. {
  308. Cd *cd = NULL;
  309. int i; /* track number */
  310. if (NULL == (cd = cf_parse(name, &format))) {
  311. fprintf(stderr, "%s: input file error\n", name);
  312. return -1;
  313. }
  314. cd_printf(d_template, cd, 0);
  315. for (i = 1; i <= cd_get_ntrack(cd); i++) {
  316. cd_printf(t_template, cd, i);
  317. }
  318. return 0;
  319. }
  320. int main (int argc, char **argv)
  321. {
  322. int format = UNKNOWN;
  323. /* getopt () variables */
  324. char c;
  325. extern char *optarg;
  326. extern int optind;
  327. progname = *argv;
  328. while (-1 != (c = getopt(argc, argv, "hi:d:t:"))) {
  329. switch (c) {
  330. case 'h':
  331. usage(0);
  332. break;
  333. case 'i':
  334. if (0 == strcmp("cue", optarg))
  335. format = CUE;
  336. else if (0 == strcmp("toc", optarg))
  337. format = TOC;
  338. break;
  339. case 'd':
  340. d_template = optarg;
  341. break;
  342. case 't':
  343. t_template = optarg;
  344. break;
  345. default:
  346. usage(1);
  347. break;
  348. }
  349. }
  350. /* if no disc or track template is set, use the defaults for both */
  351. if (NULL == d_template && NULL == t_template) {
  352. d_template = D_TEMPLATE;
  353. t_template = T_TEMPLATE;
  354. } else {
  355. if (NULL == d_template)
  356. d_template = "";
  357. if (NULL == t_template)
  358. t_template = "";
  359. }
  360. if (optind == argc) {
  361. info("-", format);
  362. } else {
  363. for (; optind < argc; optind++)
  364. info(argv[optind], format);
  365. }
  366. return 0;
  367. }