summaryrefslogtreecommitdiff
path: root/tag.cpp
blob: f65470f1bf7f2500eebe7e26433f2d8eaee4fde2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "tag.h"

#include <id3tag.h>

#include <cstdlib>
#include <stdexcept>

// TODO: Make this a "smart" tag loader
Tag::p Tag::load(const std::string filename) {
	return Tag::p(new ID3Tag(filename));
}

bool Tag::has_field(const std::string name) {
	return fields.find(name) != fields.end();
}

void ID3Tag::tag_add_string(struct id3_tag *id3tag, const char *type, const char *id) {
	struct id3_frame *frame = id3_tag_findframe(id3tag, id, 0);

	if(frame == NULL) {
		return;
	}

	if(frame->nfields != 2) {
		throw std::runtime_error("unexpected nfields value");
	}

	const union id3_field *field = id3_frame_field(frame, 1);
	unsigned int nstrings = id3_field_getnstrings(field);

	for(unsigned int i = 0; i < nstrings; i++) {
		const id3_ucs4_t *ucs4 = id3_field_getstrings(field, i);

		if(ucs4 == NULL) {
			throw std::runtime_error("ucs4 is NULL");
		}

		id3_utf8_t *utf8 = id3_ucs4_utf8duplicate(ucs4);
		fields[type] = (char*)utf8;
		free(utf8);
	}
}

ID3Tag::ID3Tag(const std::string filename) {
	struct id3_file *file = id3_file_open(filename.c_str(), ID3_FILE_MODE_READONLY);

	if(file == NULL) {
		throw std::runtime_error("failed to open file for reading");
	}

	struct id3_tag *id3tag = id3_file_tag(file);

	if(id3tag == NULL) {
		throw std::runtime_error("tag is NULL");
	}

	tag_add_string(id3tag, "artist", ID3_FRAME_ARTIST);
	tag_add_string(id3tag, "title", ID3_FRAME_TITLE);
	tag_add_string(id3tag, "album", ID3_FRAME_ALBUM);

	id3_file_close(file);
}