DatabasePrint.cxx 5.59 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2014 The Music Player Daemon Project
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * http://www.musicpd.org
 *
 * 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.
 *
 * 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.
 */

#include "config.h"
21
#include "DatabasePrint.hxx"
Max Kellermann's avatar
Max Kellermann committed
22
#include "Selection.hxx"
23
#include "SongFilter.hxx"
Max Kellermann's avatar
Max Kellermann committed
24 25
#include "SongPrint.hxx"
#include "TimePrint.hxx"
26
#include "client/Client.hxx"
27
#include "tag/Tag.hxx"
28
#include "LightSong.hxx"
29 30
#include "LightDirectory.hxx"
#include "PlaylistInfo.hxx"
31
#include "Interface.hxx"
32
#include "fs/Traits.hxx"
33

34
#include <functional>
35

36 37 38 39 40 41 42 43
static const char *
ApplyBaseFlag(const char *uri, bool base)
{
	if (base)
		uri = PathTraitsUTF8::GetBase(uri);
	return uri;
}

44
static void
45
PrintDirectoryURI(Client &client, bool base, const LightDirectory &directory)
46
{
47 48
	client_printf(client, "directory: %s\n",
		      ApplyBaseFlag(directory.GetPath(), base));
49 50
}

51
static bool
52
PrintDirectoryBrief(Client &client, bool base, const LightDirectory &directory)
53
{
54
	if (!directory.IsRoot())
55
		PrintDirectoryURI(client, base, directory);
56

57
	return true;
58 59
}

60
static bool
61
PrintDirectoryFull(Client &client, bool base, const LightDirectory &directory)
62 63
{
	if (!directory.IsRoot()) {
64
		PrintDirectoryURI(client, base, directory);
65 66 67

		if (directory.mtime > 0)
			time_print(client, "Last-Modified", directory.mtime);
68 69 70 71 72
	}

	return true;
}

73
static void
74
print_playlist_in_directory(Client &client, bool base,
75 76 77
			    const char *directory,
			    const char *name_utf8)
{
78 79 80
	if (base || directory == nullptr)
		client_printf(client, "playlist: %s\n",
			      ApplyBaseFlag(name_utf8, base));
81 82 83 84
	else
		client_printf(client, "playlist: %s/%s\n",
			      directory, name_utf8);
}
85

86
static void
87
print_playlist_in_directory(Client &client, bool base,
88
			    const LightDirectory *directory,
89 90
			    const char *name_utf8)
{
91
	if (base || directory == nullptr || directory->IsRoot())
92 93 94
		client_printf(client, "playlist: %s\n", name_utf8);
	else
		client_printf(client, "playlist: %s/%s\n",
95
			      directory->GetPath(), name_utf8);
96 97
}

98
static bool
99
PrintSongBrief(Client &client, bool base, const LightSong &song)
100
{
101
	song_print_uri(client, song, base);
102

103
	if (song.tag->has_playlist)
104
		/* this song file has an embedded CUE sheet */
105 106
		print_playlist_in_directory(client, base,
					    song.directory, song.uri);
107

108
	return true;
109 110
}

111
static bool
112
PrintSongFull(Client &client, bool base, const LightSong &song)
113
{
114
	song_print_info(client, song, base);
115

116
	if (song.tag->has_playlist)
117
		/* this song file has an embedded CUE sheet */
118 119
		print_playlist_in_directory(client, base,
					    song.directory, song.uri);
120 121

	return true;
122 123
}

124
static bool
125
PrintPlaylistBrief(Client &client, bool base,
126
		   const PlaylistInfo &playlist,
127
		   const LightDirectory &directory)
128
{
129 130
	print_playlist_in_directory(client, base,
				    &directory, playlist.name.c_str());
131 132 133 134
	return true;
}

static bool
135
PrintPlaylistFull(Client &client, bool base,
136
		  const PlaylistInfo &playlist,
137
		  const LightDirectory &directory)
138
{
139 140
	print_playlist_in_directory(client, base,
				    &directory, playlist.name.c_str());
141

142 143
	if (playlist.mtime > 0)
		time_print(client, "Last-Modified", playlist.mtime);
144 145 146 147

	return true;
}

148
bool
149
db_selection_print(Client &client, const DatabaseSelection &selection,
150
		   bool full, bool base, Error &error)
151
{
152
	const Database *db = client.GetDatabase(error);
153 154 155
	if (db == nullptr)
		return false;

156
	using namespace std::placeholders;
157
	const auto d = selection.filter == nullptr
158
		? std::bind(full ? PrintDirectoryFull : PrintDirectoryBrief,
159
			    std::ref(client), base, _1)
160
		: VisitDirectory();
161
	const auto s = std::bind(full ? PrintSongFull : PrintSongBrief,
162
				 std::ref(client), base, _1);
163
	const auto p = selection.filter == nullptr
164
		? std::bind(full ? PrintPlaylistFull : PrintPlaylistBrief,
165
			    std::ref(client), base, _1, _2)
166
		: VisitPlaylist();
167

168
	return db->Visit(selection, d, s, p, error);
169 170
}

171
static bool
172
PrintSongURIVisitor(Client &client, const LightSong &song)
173
{
174
	song_print_uri(client, song);
175

176
	return true;
177 178
}

179
static bool
180
PrintUniqueTag(Client &client, TagType tag_type,
181
	       const Tag &tag)
182
{
183 184
	const char *value = tag.GetValue(tag_type);
	assert(value != nullptr);
185
	client_printf(client, "%s: %s\n", tag_item_names[tag_type], value);
186

187
	for (const auto &item : tag)
188 189 190 191
		if (item.type != tag_type)
			client_printf(client, "%s: %s\n",
				      tag_item_names[item.type], item.value);

192
	return true;
193 194
}

195
bool
196 197 198
PrintUniqueTags(Client &client, unsigned type, uint32_t group_mask,
		const SongFilter *filter,
		Error &error)
199
{
200
	const Database *db = client.GetDatabase(error);
201 202 203
	if (db == nullptr)
		return false;

204
	const DatabaseSelection selection("", true, filter);
205

206 207
	if (type == LOCATE_TAG_FILE_TYPE) {
		using namespace std::placeholders;
208 209
		const auto f = std::bind(PrintSongURIVisitor,
					 std::ref(client), _1);
210
		return db->Visit(selection, f, error);
211
	} else {
212 213
		assert(type < TAG_NUM_OF_ITEM_TYPES);

214
		using namespace std::placeholders;
215
		const auto f = std::bind(PrintUniqueTag, std::ref(client),
216 217
					 (TagType)type, _1);
		return db->VisitUniqueTags(selection, (TagType)type,
218
					   group_mask,
219
					   f, error);
220
	}
221
}