Display rounds instead of turns
[oggquiz.git] / oggfile.c
blob786b298e362fa7d080abdf4a96ffe5d52673f607
1 /*-
2 * "THE BEER-WARE LICENSE" (Revision 42):
3 * <tobias.rehbein@web.de> wrote this file. As long as you retain this notice
4 * you can do whatever you want with this stuff. If we meet some day, and you
5 * think this stuff is worth it, you can buy me a beer in return.
6 * Tobias Rehbein
7 */
9 #include <assert.h>
10 #include <err.h>
11 #include <iconv.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <sysexits.h>
15 #include <vorbis/vorbisfile.h>
17 #include "oggfile.h"
19 struct ogg_context {
20 iconv_t cd;
23 static int fill_comments(struct ogg_context *ctx, struct ogg_oggfile *ogg);
24 static void do_iconv(struct ogg_context *ctx, const char *in, char *out, size_t outlen);
26 int
27 ogg_oggfile_create(struct ogg_context *ctx, struct ogg_oggfile *ogg, char *filename)
29 assert(ctx != NULL);
30 assert(ogg != NULL);
31 assert(filename != NULL);
33 strncpy(ogg->filename, filename, sizeof(ogg->filename) - 1);
34 ogg->filename[sizeof(ogg->filename) - 1] = '\0';
36 if (fill_comments(ctx, ogg) != 0)
37 return (1);
39 return (0);
42 static int
43 fill_comments(struct ogg_context *ctx, struct ogg_oggfile *ogg)
45 OggVorbis_File ovf;
46 vorbis_comment *ovc;
47 char *key, *value;
48 int i;
50 assert(ctx != NULL);
51 assert(ogg != NULL);
53 if (ov_fopen(ogg->filename, &ovf) != 0) {
54 warnx("could not open file: %s", ogg->filename);
55 return (1);
57 if ((ovc = ov_comment(&ovf, -1)) == NULL) {
58 warnx("could not read comments for file: %s", ogg->filename);
59 return (1);
61 for (i = 0; i < ovc->comments; i++) {
62 value = ovc->user_comments[i];
63 key = strsep(&value, "=");
64 if (strcasecmp(key, "artist") == 0)
65 do_iconv(ctx, value, ogg->artist, sizeof(ogg->artist));
66 else if (strcasecmp(key, "album") == 0)
67 do_iconv(ctx, value, ogg->album, sizeof(ogg->album));
68 else if (strcasecmp(key, "title") == 0)
69 do_iconv(ctx, value, ogg->title, sizeof(ogg->title));
70 if (ogg->artist == NULL || ogg->album == NULL || ogg->title == NULL) {
71 warnx("insufficient comments for file: %s", ogg->filename);
72 return (1);
76 if (ov_clear(&ovf) != 0)
77 warnx("could not close file: %s", ogg->filename);
79 return (0);
82 struct ogg_context *
83 ogg_context_open()
85 struct ogg_context *ctx;
86 iconv_t cd;
88 if ((cd = iconv_open("char", "UTF-8")) == (iconv_t) (-1))
89 return (NULL);
90 if ((ctx = malloc(sizeof(*ctx))) == NULL)
91 return (NULL);
93 ctx->cd = cd;
95 return (ctx);
98 int
99 ogg_context_close(struct ogg_context *ctx)
101 assert(ctx != NULL);
103 if (iconv_close(ctx->cd) == -1)
104 return (1);
105 free(ctx);
107 return (0);
110 static void
111 do_iconv(struct ogg_context *ctx, const char *in, char *out, size_t outlen)
113 const char *inp;
114 char *outp;
115 size_t inlen = strlen(in);
117 assert(ctx != NULL);
118 assert(in != NULL);
119 assert(out != NULL);
120 assert(outlen > 0);
122 inp = in;
123 outp = out;
125 if (iconv(ctx->cd, NULL, NULL, &outp, &outlen) == (size_t) (-1))
126 errx(EX_SOFTWARE, "could not set initial conversion state");
128 while (inlen > 0) {
129 if (iconv(ctx->cd, &inp, &inlen, &outp, &outlen) == (size_t) (-1))
130 errx(EX_SOFTWARE, "string conversion failed");
133 *outp = '\0';