Tag.cxx 3.24 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright 2003-2017 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
 */

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

25
#include <assert.h>
26

Max Kellermann's avatar
Max Kellermann committed
27
void
28
Tag::Clear() noexcept
Max Kellermann's avatar
Max Kellermann committed
29
{
30
	duration = SignedSongTime::Negative();
Max Kellermann's avatar
Max Kellermann committed
31 32 33 34 35 36 37
	has_playlist = false;

	tag_pool_lock.lock();
	for (unsigned i = 0; i < num_items; ++i)
		tag_pool_put_item(items[i]);
	tag_pool_lock.unlock();

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

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

Max Kellermann's avatar
Max Kellermann committed
51 52 53 54 55
		tag_pool_lock.lock();
		for (unsigned i = 0; i < num_items; i++)
			items[i] = tag_pool_dup_item(other.items[i]);
		tag_pool_lock.unlock();
	}
56 57
}

Max Kellermann's avatar
Max Kellermann committed
58 59
Tag *
Tag::Merge(const Tag &base, const Tag &add)
60
{
61 62
	TagBuilder builder(add);
	builder.Complement(base);
63
	return builder.CommitNew();
64 65
}

Max Kellermann's avatar
Max Kellermann committed
66 67
Tag *
Tag::MergeReplace(Tag *base, Tag *add)
68
{
Max Kellermann's avatar
Max Kellermann committed
69
	if (add == nullptr)
70 71
		return base;

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

Max Kellermann's avatar
Max Kellermann committed
75 76 77
	Tag *tag = Merge(*base, *add);
	delete base;
	delete add;
78 79 80 81

	return tag;
}

82
const char *
83
Tag::GetValue(TagType type) const noexcept
84 85 86
{
	assert(type < TAG_NUM_OF_ITEM_TYPES);

87 88 89
	for (const auto &item : *this)
		if (item.type == type)
			return item.value;
90

Max Kellermann's avatar
Max Kellermann committed
91
	return nullptr;
92
}
93

Max Kellermann's avatar
Max Kellermann committed
94
bool
95
Tag::HasType(TagType type) const noexcept
96
{
Max Kellermann's avatar
Max Kellermann committed
97
	return GetValue(type) != nullptr;
98
}
99 100

static TagType
101
DecaySort(TagType type) noexcept
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
{
	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
119
Fallback(TagType type) noexcept
120 121 122 123 124 125 126 127 128 129 130 131 132 133
{
	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 *
134
Tag::GetSortValue(TagType type) const noexcept
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
{
	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 "";
}