Fix rating menu.
[gmpc.git] / src / Tools / advanced-search.c
blob2ea9b76239f9945a49a890b60ff3aa619b5f004a
1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.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.
19 #include <config.h>
20 #include <glib.h>
21 #include "main.h"
22 #include "misc.h"
23 #include "advanced-search.h"
25 static GRegex *search_regex = NULL;
27 /**
28 * Initialize the advanced_search system.
30 void advanced_search_init(void)
32 int i = 0;
33 GString *string = g_string_new("(");
34 if (search_regex) {
35 g_regex_unref(search_regex);
36 search_regex = NULL;
38 for (i = 0; i < MPD_TAG_NUM_OF_ITEM_TYPES; i++)
40 if (mpd_server_tag_supported(connection, i))
42 g_string_append(string, mpdTagItemKeys[i]);
43 if (i < (MPD_TAG_NUM_OF_ITEM_TYPES - 1))
44 g_string_append(string, "|");
47 g_string_append(string, ")[ ]*[=:][ ]*|[ ]*(\\|\\|)[ ]*");
48 search_regex = g_regex_new(string->str, G_REGEX_CASELESS, 0, NULL);
49 g_string_free(string, TRUE);
52 /**
53 * Update the advanced_search regex to include only the supported tags
55 void advanced_search_update_taglist(void)
57 advanced_search_init();
60 /**
61 * Destroy all the advanced_search system and clean all allocated memory.
63 void advanced_search_destroy(void)
65 if (search_regex)
66 g_regex_unref(search_regex);
67 search_regex = NULL;
70 /**
71 * Execute query.
72 * @param query the query to execute.
73 * @param playlist set to TRUE to search only songs in the playlist.
75 * @returns the search result in a #MpdData list.
77 MpdData *advanced_search(const gchar * query, int in_playlist)
79 MpdData *data_return = NULL;
80 gchar **text = g_regex_split(search_regex, query, 0);
81 int i = 0;
82 gboolean found = FALSE;
83 for (i = 0; text && text[i]; i++)
85 int type;
86 /* Or sign, if hit, a new query is started */
87 if (strcmp(text[i], "||") == 0)
89 MpdData *data;
90 /* Commit the currently in active search and append the results */
91 if (in_playlist)
92 data = mpd_playlist_search_commit(connection);
93 else
94 data = mpd_database_search_commit(connection);
95 data_return = mpd_data_concatenate(data_return, data);
96 found = FALSE;
97 continue;
99 /* empty element */
100 if (text[i][0] == '\0')
101 continue;
103 /* Parse the tag name. */
104 type = mpd_misc_get_tag_by_name(g_strstrip(text[i]));
105 if (type != MPD_TAG_NOT_FOUND && text[i + 1])
107 gchar **split = tokenize_string(text[i + 1]);
108 int j;
109 for (j = 0; split && split[j]; j++)
111 if (!found)
113 if (in_playlist)
114 mpd_playlist_search_start(connection, FALSE);
115 else
116 mpd_database_search_start(connection, FALSE);
117 found = TRUE;
119 if (in_playlist)
120 mpd_playlist_search_add_constraint(connection, type, g_strstrip(split[j]));
121 else
122 mpd_database_search_add_constraint(connection, type, g_strstrip(split[j]));
124 if (split)
125 g_strfreev(split);
126 i++;
127 } else
129 gchar **split = tokenize_string(text[i]);
130 int j;
131 for (j = 0; split && split[j]; j++)
133 if (!found)
135 if (in_playlist)
136 mpd_playlist_search_start(connection, FALSE);
137 else
138 mpd_database_search_start(connection, FALSE);
139 found = TRUE;
141 if (in_playlist)
142 mpd_playlist_search_add_constraint(connection, MPD_TAG_ITEM_ANY, split[j]);
143 else
144 mpd_database_search_add_constraint(connection, MPD_TAG_ITEM_ANY, split[j]);
146 if (split)
147 g_strfreev(split);
150 if (text)
151 g_strfreev(text);
152 /* Execute the active search and append the results */
153 if (found)
155 MpdData *data;
156 if (in_playlist)
157 data = mpd_playlist_search_commit(connection);
158 else
159 data = mpd_database_search_commit(connection);
160 data_return = mpd_data_concatenate(data_return, data);
162 /* remove possible duplicates (because of concatenating queries) */
163 return misc_mpddata_remove_duplicate_songs(data_return);
166 /* vim: set noexpandtab ts=4 sw=4 sts=4 tw=120: */