DatabasePrint.cxx 5.75 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2013 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"
22
#include "DatabaseSelection.hxx"
23
#include "SongFilter.hxx"
Max Kellermann's avatar
Max Kellermann committed
24 25
#include "SongPrint.hxx"
#include "TimePrint.hxx"
26
#include "Directory.hxx"
Max Kellermann's avatar
Max Kellermann committed
27
#include "Client.hxx"
28
#include "tag/Tag.hxx"
29
#include "Song.hxx"
30 31
#include "DatabaseGlue.hxx"
#include "DatabasePlugin.hxx"
32

33
#include <functional>
34

35
static bool
36
PrintDirectoryBrief(Client &client, const Directory &directory)
37
{
38 39
	if (!directory.IsRoot())
		client_printf(client, "directory: %s\n", directory.GetPath());
40

41
	return true;
42 43
}

44
static bool
45
PrintDirectoryFull(Client &client, const Directory &directory)
46 47 48 49 50 51 52 53 54 55
{
	if (!directory.IsRoot()) {
		client_printf(client, "directory: %s\n", directory.GetPath());
		time_print(client, "Last-Modified", directory.mtime);
	}

	return true;
}


56
static void
57
print_playlist_in_directory(Client &client,
58
			    const Directory *directory,
59 60
			    const char *name_utf8)
{
61
	if (directory == nullptr || directory->IsRoot())
62 63 64
		client_printf(client, "playlist: %s\n", name_utf8);
	else
		client_printf(client, "playlist: %s/%s\n",
65
			      directory->GetPath(), name_utf8);
66 67
}

68
static bool
69
PrintSongBrief(Client &client, const Song &song)
70
{
71
	song_print_uri(client, song);
72

73
	if (song.tag != nullptr && song.tag->has_playlist)
74
		/* this song file has an embedded CUE sheet */
75
		print_playlist_in_directory(client, song.parent, song.uri);
76

77
	return true;
78 79
}

80
static bool
81
PrintSongFull(Client &client, const Song &song)
82
{
83
	song_print_info(client, song);
84

85
	if (song.tag != nullptr && song.tag->has_playlist)
86
		/* this song file has an embedded CUE sheet */
87
		print_playlist_in_directory(client, song.parent, song.uri);
88 89

	return true;
90 91
}

92
static bool
93
PrintPlaylistBrief(Client &client,
94
		   const PlaylistInfo &playlist,
95
		   const Directory &directory)
96
{
97
	print_playlist_in_directory(client, &directory, playlist.name.c_str());
98 99 100 101
	return true;
}

static bool
102
PrintPlaylistFull(Client &client,
103
		  const PlaylistInfo &playlist,
104
		  const Directory &directory)
105
{
106
	print_playlist_in_directory(client, &directory, playlist.name.c_str());
107

108 109
	if (playlist.mtime > 0)
		time_print(client, "Last-Modified", playlist.mtime);
110 111 112 113

	return true;
}

114
bool
115
db_selection_print(Client &client, const DatabaseSelection &selection,
116
		   bool full, Error &error)
117
{
118
	const Database *db = GetDatabase(error);
119 120 121
	if (db == nullptr)
		return false;

122
	using namespace std::placeholders;
123
	const auto d = selection.filter == nullptr
124
		? std::bind(full ? PrintDirectoryFull : PrintDirectoryBrief,
125
			    std::ref(client), _1)
126
		: VisitDirectory();
127
	const auto s = std::bind(full ? PrintSongFull : PrintSongBrief,
128
				 std::ref(client), _1);
129
	const auto p = selection.filter == nullptr
130
		? std::bind(full ? PrintPlaylistFull : PrintPlaylistBrief,
131
			    std::ref(client), _1, _2)
132
		: VisitPlaylist();
133

134
	return db->Visit(selection, d, s, p, error);
135 136
}

137 138 139 140 141
struct SearchStats {
	int numberOfSongs;
	unsigned long playTime;
};

142
static void printSearchStats(Client &client, SearchStats *stats)
143 144 145 146 147
{
	client_printf(client, "songs: %i\n", stats->numberOfSongs);
	client_printf(client, "playtime: %li\n", stats->playTime);
}

148
static bool
149
stats_visitor_song(SearchStats &stats, Song &song)
150
{
151
	stats.numberOfSongs++;
152
	stats.playTime += song.GetDuration();
153

154
	return true;
155 156
}

157
bool
158
searchStatsForSongsIn(Client &client, const char *name,
159
		      const SongFilter *filter,
160
		      Error &error)
161
{
162
	const Database *db = GetDatabase(error);
163 164 165
	if (db == nullptr)
		return false;

166
	const DatabaseSelection selection(name, true, filter);
167

168
	SearchStats stats;
169 170 171
	stats.numberOfSongs = 0;
	stats.playTime = 0;

172
	using namespace std::placeholders;
173
	const auto f = std::bind(stats_visitor_song, std::ref(stats),
174
				 _1);
175
	if (!db->Visit(selection, f, error))
176
		return false;
177

178 179
	printSearchStats(client, &stats);
	return true;
180 181
}

182
bool
183
printAllIn(Client &client, const char *uri_utf8, Error &error)
184
{
185
	const DatabaseSelection selection(uri_utf8, true);
186
	return db_selection_print(client, selection, false, error);
187 188
}

189
bool
190
printInfoForAllIn(Client &client, const char *uri_utf8,
191
		  Error &error)
192
{
193
	const DatabaseSelection selection(uri_utf8, true);
194
	return db_selection_print(client, selection, true, error);
195 196
}

197
static bool
198
PrintSongURIVisitor(Client &client, Song &song)
199
{
200
	song_print_uri(client, song);
201

202
	return true;
203 204
}

205
static bool
206
PrintUniqueTag(Client &client, TagType tag_type,
207
	       const char *value)
208
{
209
	client_printf(client, "%s: %s\n", tag_item_names[tag_type], value);
210
	return true;
211 212
}

213
bool
214
listAllUniqueTags(Client &client, int type,
215
		  const SongFilter *filter,
216
		  Error &error)
217
{
218
	const Database *db = GetDatabase(error);
219 220 221
	if (db == nullptr)
		return false;

222
	const DatabaseSelection selection("", true, filter);
223

224 225
	if (type == LOCATE_TAG_FILE_TYPE) {
		using namespace std::placeholders;
226 227
		const auto f = std::bind(PrintSongURIVisitor,
					 std::ref(client), _1);
228
		return db->Visit(selection, f, error);
229 230
	} else {
		using namespace std::placeholders;
231
		const auto f = std::bind(PrintUniqueTag, std::ref(client),
232 233
					 (TagType)type, _1);
		return db->VisitUniqueTags(selection, (TagType)type,
234
					   f, error);
235
	}
236
}