Tag.cxx 3.26 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2020 The Music Player Daemon Project
3
 * http://www.musicpd.org
Warren Dukes's avatar
Warren Dukes committed
4 5 6 7 8 9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Warren Dukes's avatar
Warren Dukes committed
18 19
 */

Max Kellermann's avatar
Max Kellermann committed
20
#include "Tag.hxx"
21 22
#include "Pool.hxx"
#include "Builder.hxx"
Warren Dukes's avatar
Warren Dukes committed
23

24
#include <cassert>
25

Max Kellermann's avatar
Max Kellermann committed
26
void
27
Tag::Clear() noexcept
Max Kellermann's avatar
Max Kellermann committed
28
{
29
	duration = SignedSongTime::Negative();
Max Kellermann's avatar
Max Kellermann committed
30 31
	has_playlist = false;

32 33 34 35 36
	{
		const std::lock_guard<Mutex> protect(tag_pool_lock);
		for (unsigned i = 0; i < num_items; ++i)
			tag_pool_put_item(items[i]);
	}
Max Kellermann's avatar
Max Kellermann committed
37

38
	delete[] items;
Max Kellermann's avatar
Max Kellermann committed
39 40 41 42
	items = nullptr;
	num_items = 0;
}

43
Tag::Tag(const Tag &other) noexcept
44
	:duration(other.duration), has_playlist(other.has_playlist),
45
	 num_items(other.num_items)
Avuton Olrich's avatar
Avuton Olrich committed
46
{
Max Kellermann's avatar
Max Kellermann committed
47
	if (num_items > 0) {
48
		items = new TagItem *[num_items];
Warren Dukes's avatar
Warren Dukes committed
49

50
		const std::lock_guard<Mutex> protect(tag_pool_lock);
Max Kellermann's avatar
Max Kellermann committed
51 52 53
		for (unsigned i = 0; i < num_items; i++)
			items[i] = tag_pool_dup_item(other.items[i]);
	}
54 55
}

56 57
std::unique_ptr<Tag>
Tag::Merge(const Tag &base, const Tag &add) noexcept
58
{
59 60
	TagBuilder builder(add);
	builder.Complement(base);
61
	return builder.CommitNew();
62 63
}

64
std::unique_ptr<Tag>
65
Tag::Merge(std::unique_ptr<Tag> base, std::unique_ptr<Tag> add) noexcept
66
{
Max Kellermann's avatar
Max Kellermann committed
67
	if (add == nullptr)
68 69
		return base;

Max Kellermann's avatar
Max Kellermann committed
70
	if (base == nullptr)
71 72
		return add;

73
	return Merge(*base, *add);
74 75
}

76
const char *
77
Tag::GetValue(TagType type) const noexcept
78 79 80
{
	assert(type < TAG_NUM_OF_ITEM_TYPES);

81 82 83
	for (const auto &item : *this)
		if (item.type == type)
			return item.value;
84

Max Kellermann's avatar
Max Kellermann committed
85
	return nullptr;
86
}
87

Max Kellermann's avatar
Max Kellermann committed
88
bool
89
Tag::HasType(TagType type) const noexcept
90
{
Max Kellermann's avatar
Max Kellermann committed
91
	return GetValue(type) != nullptr;
92
}
93 94

static TagType
95
DecaySort(TagType type) noexcept
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
{
	switch (type) {
	case TAG_ARTIST_SORT:
		return TAG_ARTIST;

	case TAG_ALBUM_SORT:
		return TAG_ALBUM;

	case TAG_ALBUM_ARTIST_SORT:
		return TAG_ALBUM_ARTIST;

	default:
		return TAG_NUM_OF_ITEM_TYPES;
	}
}

static TagType
113
Fallback(TagType type) noexcept
114 115 116 117 118 119 120 121 122 123 124 125 126 127
{
	switch (type) {
	case TAG_ALBUM_ARTIST:
		return TAG_ARTIST;

	case TAG_MUSICBRAINZ_ALBUMARTISTID:
		return TAG_MUSICBRAINZ_ARTISTID;

	default:
		return TAG_NUM_OF_ITEM_TYPES;
	}
}

const char *
128
Tag::GetSortValue(TagType type) const noexcept
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
{
	const char *value = GetValue(type);
	if (value != nullptr)
		return value;

	/* try without *_SORT */
	const auto no_sort_type = DecaySort(type);
	if (no_sort_type != TAG_NUM_OF_ITEM_TYPES) {
		value = GetValue(no_sort_type);
		if (value != nullptr)
			return value;
	}

	/* fall back from TAG_ALBUM_ARTIST to TAG_ALBUM */

	type = Fallback(type);
	if (type != TAG_NUM_OF_ITEM_TYPES)
		return GetSortValue(type);

	if (no_sort_type != TAG_NUM_OF_ITEM_TYPES) {
		type = Fallback(no_sort_type);
		if (type != TAG_NUM_OF_ITEM_TYPES)
			return GetSortValue(type);
	}

	/* finally fall back to empty string */

	return "";
}