1 /* ncmpc (Ncurses MPD Client)
2 * (c) 2004-2018 The Music Player Daemon Project
3 * Project homepage: http://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 "AlbumListPage.hxx"
21 #include "screen_interface.hxx"
22 #include "screen_status.hxx"
23 #include "screen_find.hxx"
24 #include "screen_browser.hxx"
27 #include "charset.hxx"
28 #include "mpdclient.hxx"
29 #include "filelist.hxx"
42 CompareUTF8(const std::string &a, const std::string &b)
44 char *key1 = g_utf8_collate_key(a.c_str(), -1);
45 char *key2 = g_utf8_collate_key(b.c_str(), -1);
46 int n = strcmp(key1,key2);
52 /* list_window callback */
54 album_lw_callback(unsigned idx, void *data)
56 const auto &list = *(const std::vector<std::string> *)data;
58 assert(idx < list.size());
60 const char *str_utf8 = list[idx].c_str();
61 char *str = utf8_to_locale(str_utf8);
63 static char buf[BUFSIZE];
64 g_strlcpy(buf, str, sizeof(buf));
70 /* list_window callback */
72 AlbumListCallback(unsigned idx, void *data)
74 const auto &list = *(const std::vector<std::string> *)data;
78 else if (idx == list.size() + 1)
79 return _("All tracks");
83 return album_lw_callback(idx, data);
87 recv_tag_values(struct mpd_connection *connection, enum mpd_tag_type tag,
88 std::vector<std::string> &list)
90 struct mpd_pair *pair;
92 while ((pair = mpd_recv_pair_tag(connection, tag)) != nullptr) {
93 list.emplace_back(pair->value);
94 mpd_return_pair(connection, pair);
99 AlbumListPage::LoadAlbumList(struct mpdclient &c)
101 struct mpd_connection *connection = mpdclient_get_connection(&c);
105 if (connection != nullptr) {
106 mpd_search_db_tags(connection, MPD_TAG_ALBUM);
107 mpd_search_add_tag_constraint(connection,
108 MPD_OPERATOR_DEFAULT,
111 mpd_search_commit(connection);
113 recv_tag_values(connection, MPD_TAG_ALBUM, album_list);
115 mpdclient_finish_command(&c);
119 std::sort(album_list.begin(), album_list.end(), CompareUTF8);
120 lw.SetLength(album_list.size() + 2);
124 AlbumListPage::Reload(struct mpdclient &c)
130 * Paint one item in the album list. There are two virtual items
131 * inserted: at the beginning, there's the special item ".." to go to
132 * the parent directory, and at the end, there's the item "All tracks"
133 * to view the tracks of all albums.
136 paint_album_callback(WINDOW *w, unsigned i,
137 gcc_unused unsigned y, unsigned width,
138 bool selected, const void *data)
140 const auto &list = *(const std::vector<std::string> *)data;
146 else if (i == list.size() + 1)
149 p = q = utf8_to_locale(list[i - 1].c_str());
151 screen_browser_paint_directory(w, width, selected, p);
156 AlbumListPage::Paint() const
158 lw.Paint(paint_album_callback, &album_list);
162 AlbumListPage::GetTitle(char *str, size_t size) const
167 char *s1 = utf8_to_locale(artist.c_str());
168 g_snprintf(str, size, _("Albums of artist: %s"), s1);
174 AlbumListPage::Update(struct mpdclient &c, unsigned events)
176 if (events & MPD_IDLE_DATABASE) {
177 /* the db has changed -> update the list */
183 /* add_query - Add all songs satisfying specified criteria.
184 _artist is actually only used in the ALBUM case to distinguish albums with
185 the same name from different artists. */
187 add_query(struct mpdclient *c, enum mpd_tag_type table, const char *_filter,
190 struct mpd_connection *connection = mpdclient_get_connection(c);
192 assert(_filter != nullptr);
194 if (connection == nullptr)
197 char *str = utf8_to_locale(_filter);
198 screen_status_printf(_("Adding \'%s\' to queue"), str);
201 mpd_search_db_songs(connection, true);
202 mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT,
204 if (table == MPD_TAG_ALBUM)
205 mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT,
206 MPD_TAG_ARTIST, _artist);
207 mpd_search_commit(connection);
209 auto *addlist = filelist_new_recv(connection);
211 if (mpdclient_finish_command(c))
212 mpdclient_filelist_add_all(c, addlist);
218 AlbumListPage::OnCommand(struct mpdclient &c, command_t cmd)
221 const char *selected;
224 if (lw.selected == 0) {
226 screen.OnCommand(c, CMD_GO_PARENT_DIRECTORY);
234 for (const unsigned i : lw.GetRange()) {
235 if(i == album_list.size() + 1)
236 add_query(&c, MPD_TAG_ARTIST, artist.c_str(),
239 selected = album_list[lw.selected - 1].c_str();
240 add_query(&c, MPD_TAG_ALBUM, selected,
242 cmd = CMD_LIST_NEXT; /* continue and select next item... */
247 /* continue and update... */
248 case CMD_SCREEN_UPDATE:
254 case CMD_LIST_FIND_NEXT:
255 case CMD_LIST_RFIND_NEXT:
256 screen_find(screen, &lw, cmd,
257 AlbumListCallback, &album_list);
262 screen_jump(screen, &lw,
263 AlbumListCallback, &album_list,
264 paint_album_callback, &album_list);
272 if (lw.HandleCommand(cmd)) {