configure.ac: Add subheaders to Input/Sticker/Autodiscovery/Metadata and Misc.
[mpd-mk.git] / src / dbUtils.c
blobf950d42ccff021c2886bf02fb69cd166e155985f
1 /*
2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "config.h"
21 #include "dbUtils.h"
22 #include "locate.h"
23 #include "directory.h"
24 #include "database.h"
25 #include "client.h"
26 #include "playlist.h"
27 #include "song.h"
28 #include "song_print.h"
29 #include "tag.h"
30 #include "strset.h"
31 #include "stored_playlist.h"
33 #include <glib.h>
35 #include <stdlib.h>
37 typedef struct _ListCommandItem {
38 int8_t tagType;
39 const struct locate_item_list *criteria;
40 } ListCommandItem;
42 typedef struct _SearchStats {
43 const struct locate_item_list *criteria;
44 int numberOfSongs;
45 unsigned long playTime;
46 } SearchStats;
48 static int
49 printDirectoryInDirectory(struct directory *directory, void *data)
51 struct client *client = data;
53 if (!directory_is_root(directory))
54 client_printf(client, "directory: %s\n", directory_get_path(directory));
56 return 0;
59 static int
60 printSongInDirectory(struct song *song, G_GNUC_UNUSED void *data)
62 struct client *client = data;
63 song_print_uri(client, song);
64 return 0;
67 struct search_data {
68 struct client *client;
69 const struct locate_item_list *criteria;
72 static int
73 searchInDirectory(struct song *song, void *_data)
75 struct search_data *data = _data;
77 if (locate_song_search(song, data->criteria))
78 song_print_info(data->client, song);
80 return 0;
83 int
84 searchForSongsIn(struct client *client, const char *name,
85 const struct locate_item_list *criteria)
87 int ret;
88 struct locate_item_list *new_list
89 = locate_item_list_casefold(criteria);
90 struct search_data data;
92 data.client = client;
93 data.criteria = new_list;
95 ret = db_walk(name, searchInDirectory, NULL, &data);
97 locate_item_list_free(new_list);
99 return ret;
102 static int
103 findInDirectory(struct song *song, void *_data)
105 struct search_data *data = _data;
107 if (locate_song_match(song, data->criteria))
108 song_print_info(data->client, song);
110 return 0;
114 findSongsIn(struct client *client, const char *name,
115 const struct locate_item_list *criteria)
117 struct search_data data;
119 data.client = client;
120 data.criteria = criteria;
122 return db_walk(name, findInDirectory, NULL, &data);
125 static void printSearchStats(struct client *client, SearchStats *stats)
127 client_printf(client, "songs: %i\n", stats->numberOfSongs);
128 client_printf(client, "playtime: %li\n", stats->playTime);
131 static int
132 searchStatsInDirectory(struct song *song, void *data)
134 SearchStats *stats = data;
136 if (locate_song_match(song, stats->criteria)) {
137 stats->numberOfSongs++;
138 stats->playTime += song_get_duration(song);
141 return 0;
145 searchStatsForSongsIn(struct client *client, const char *name,
146 const struct locate_item_list *criteria)
148 SearchStats stats;
149 int ret;
151 stats.criteria = criteria;
152 stats.numberOfSongs = 0;
153 stats.playTime = 0;
155 ret = db_walk(name, searchStatsInDirectory, NULL, &stats);
156 if (ret == 0)
157 printSearchStats(client, &stats);
159 return ret;
162 int printAllIn(struct client *client, const char *name)
164 return db_walk(name, printSongInDirectory,
165 printDirectoryInDirectory, client);
168 static int
169 directoryAddSongToPlaylist(struct song *song, G_GNUC_UNUSED void *data)
171 return playlist_append_song(&g_playlist, song, NULL);
174 struct add_data {
175 const char *path;
178 static int
179 directoryAddSongToStoredPlaylist(struct song *song, void *_data)
181 struct add_data *data = _data;
183 if (spl_append_song(data->path, song) != 0)
184 return -1;
185 return 0;
188 int addAllIn(const char *name)
190 return db_walk(name, directoryAddSongToPlaylist, NULL, NULL);
193 int addAllInToStoredPlaylist(const char *name, const char *utf8file)
195 struct add_data data = {
196 .path = utf8file,
199 return db_walk(name, directoryAddSongToStoredPlaylist, NULL, &data);
202 static int
203 findAddInDirectory(struct song *song, void *_data)
205 struct search_data *data = _data;
207 if (locate_song_match(song, data->criteria))
208 return directoryAddSongToPlaylist(song, data);
210 return 0;
213 int findAddIn(struct client *client, const char *name,
214 const struct locate_item_list *criteria)
216 struct search_data data;
218 data.client = client;
219 data.criteria = criteria;
221 return db_walk(name, findAddInDirectory, NULL, &data);
224 static int
225 directoryPrintSongInfo(struct song *song, void *data)
227 struct client *client = data;
228 song_print_info(client, song);
229 return 0;
232 int printInfoForAllIn(struct client *client, const char *name)
234 return db_walk(name, directoryPrintSongInfo,
235 printDirectoryInDirectory, client);
238 static ListCommandItem *
239 newListCommandItem(int tagType, const struct locate_item_list *criteria)
241 ListCommandItem *item = g_new(ListCommandItem, 1);
243 item->tagType = tagType;
244 item->criteria = criteria;
246 return item;
249 static void freeListCommandItem(ListCommandItem * item)
251 g_free(item);
254 static void
255 visitTag(struct client *client, struct strset *set,
256 struct song *song, enum tag_type tagType)
258 struct tag *tag = song->tag;
259 bool found = false;
261 if (tagType == LOCATE_TAG_FILE_TYPE) {
262 song_print_uri(client, song);
263 return;
266 if (!tag)
267 return;
269 for (unsigned i = 0; i < tag->num_items; i++) {
270 if (tag->items[i]->type == tagType) {
271 strset_add(set, tag->items[i]->value);
272 found = true;
276 if (!found)
277 strset_add(set, "");
280 struct list_tags_data {
281 struct client *client;
282 ListCommandItem *item;
283 struct strset *set;
286 static int
287 listUniqueTagsInDirectory(struct song *song, void *_data)
289 struct list_tags_data *data = _data;
290 ListCommandItem *item = data->item;
292 if (locate_song_match(song, item->criteria))
293 visitTag(data->client, data->set, song, item->tagType);
295 return 0;
298 int listAllUniqueTags(struct client *client, int type,
299 const struct locate_item_list *criteria)
301 int ret;
302 ListCommandItem *item = newListCommandItem(type, criteria);
303 struct list_tags_data data = {
304 .client = client,
305 .item = item,
308 if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) {
309 data.set = strset_new();
312 ret = db_walk(NULL, listUniqueTagsInDirectory, NULL, &data);
314 if (type >= 0 && type <= TAG_NUM_OF_ITEM_TYPES) {
315 const char *value;
317 strset_rewind(data.set);
319 while ((value = strset_next(data.set)) != NULL)
320 client_printf(client, "%s: %s\n",
321 tag_item_names[type],
322 value);
324 strset_free(data.set);
327 freeListCommandItem(item);
329 return ret;