]> diplodocus.org Git - flac-archive/blob - taglib.cc
750bd870ead2e74721a0437bef2a04c6a6095861
[flac-archive] / taglib.cc
1 #include <sys/types.h>
2 #include <sys/stat.h>
3
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10
11 #include <attachedpictureframe.h>
12 #include <id3v2tag.h>
13 #include <mpegfile.h>
14
15 static const char *
16 taglib_apic(const char *mp3_path, const char *image_bytes, size_t image_len,
17 const char *description_utf8, const char *mime_type)
18 {
19 TagLib::MPEG::File *f;
20 TagLib::ID3v2::Tag *t;
21 TagLib::ByteVector *bv;
22 TagLib::ID3v2::AttachedPictureFrame *p;
23
24 /* GAH! Opening the file is entangled with allocating the object;
25 * if this fails, am i out of memory, or is there a problem with
26 * the file? Hate C++... */
27 f = new TagLib::MPEG::File (mp3_path);
28 if (f == 0) {
29 return "new TagLib::MPEG::File failed";
30 }
31
32 t = f->ID3v2Tag(true);
33 if (t == 0) {
34 return "taglib failed to return ID3v2";
35 }
36
37 bv = new TagLib::ByteVector (image_bytes, image_len);
38 if (bv == 0) {
39 return "new TagLib::ByteVector failed";
40 }
41
42 p = new TagLib::ID3v2::AttachedPictureFrame;
43 if (p == 0) {
44 return "new TagLib::ID3v2::AttachedPictureFrame failed";
45 }
46
47 /* Um, look at all these void-returning functions. I'm sure they can fail,
48 * i just have no way to detect it... */
49 p->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
50 p->setMimeType(mime_type);
51 if (description_utf8 != 0) {
52 p->setDescription(description_utf8);
53 p->setTextEncoding(TagLib::String::UTF8);
54 }
55 p->setPicture(*bv);
56
57 // another void-returning function that i bet fails
58 t->addFrame(p);
59
60 errno = 0;
61 if (!f->save()) {
62 if (errno != 0) {
63 return strerror(errno);
64 }
65 return "taglib failed to save";
66 }
67
68 return 0;
69 }
70
71 int
72 main(int argc, char **argv)
73 {
74 char *description = 0;
75 char *mime_type = 0;
76
77 int c;
78 while ((c = getopt(argc, argv, "d:m:")) != -1) {
79 switch (c) {
80 case 'd':
81 description = optarg;
82 break;
83 case 'm':
84 mime_type = optarg;
85 break;
86 default:
87 // getopt printed an error.
88 return 2;
89 }
90 }
91
92 if (mime_type == 0) {
93 fputs("must specify MIME type with -m\n", stderr);
94 return 2;
95 }
96
97 argc -= optind; argv += optind;
98
99 if (argc == 0) {
100 fputs("must specify mp3 filename", stderr);
101 return 2;
102 }
103 const char *mp3_path = argv[0];
104
105 char *image_bytes;
106 size_t image_len;
107 if (argc == 2) {
108 const char *image_path = argv[1];
109 int fd = open(image_path, O_RDONLY);
110 if (fd == -1) {
111 fprintf(stderr, "open(%s): %s\n", image_path, strerror(errno));
112 return 3;
113 }
114 struct stat st;
115 if (fstat(fd, &st) != 0) {
116 fprintf(stderr, "stat(%s): %s\n", image_path, strerror(errno));
117 return 3;
118 }
119 image_len = st.st_size;
120 image_bytes = (char *)malloc(image_len);
121 if (read(fd, image_bytes, image_len) != image_len) {
122 fprintf(stderr, "read(%s): %s\n", image_path, strerror(errno));
123 return 3;
124 }
125 } else {
126 fputs("not yet reading image from stdin\n", stderr);
127 return 3;
128 }
129
130 printf("mp3: %s imagelen: %ld desc: %s mime: %s\n",
131 mp3_path, (long)image_len, description, mime_type);
132 return 0;
133
134 const char *result = taglib_apic(mp3_path, image_bytes, image_len, description, mime_type);
135 if (result != 0) {
136 fprintf(stderr, "%s\n", result);
137 return 2;
138 }
139 return 0;
140 }