Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
20 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  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. }