Code

screen_artist: don't convert _() to locale
[ncmpc.git] / src / screen_artist.c
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2009 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.
18 */
20 #include "screen_artist.h"
21 #include "screen_interface.h"
22 #include "screen_message.h"
23 #include "screen_find.h"
24 #include "screen.h"
25 #include "i18n.h"
26 #include "charset.h"
27 #include "mpdclient.h"
28 #include "screen_browser.h"
29 #include "filelist.h"
31 #include <assert.h>
32 #include <string.h>
33 #include <glib.h>
35 #define BUFSIZE 1024
37 typedef enum { LIST_ARTISTS, LIST_ALBUMS, LIST_SONGS } artist_mode_t;
39 static artist_mode_t mode = LIST_ARTISTS;
40 static GPtrArray *artist_list, *album_list;
41 static char *artist = NULL;
42 static char *album  = NULL;
44 static struct screen_browser browser;
46 static gint
47 compare_utf8(gconstpointer s1, gconstpointer s2)
48 {
49         const char *const*t1 = s1, *const*t2 = s2;
50         char *key1, *key2;
51         int n;
53         key1 = g_utf8_collate_key(*t1,-1);
54         key2 = g_utf8_collate_key(*t2,-1);
55         n = strcmp(key1,key2);
56         g_free(key1);
57         g_free(key2);
58         return n;
59 }
61 /* list_window callback */
62 static const char *
63 screen_artist_lw_callback(unsigned idx, void *data)
64 {
65         GPtrArray *list = data;
66         static char buf[BUFSIZE];
67         char *str, *str_utf8;
69         if (mode == LIST_ALBUMS) {
70                 if (idx == 0)
71                         return "[..]";
72                 else if (idx == list->len + 1) {
73                         g_snprintf(buf, BUFSIZE, "[%s]", _("All tracks"));
74                         return buf;
75                 }
77                 --idx;
78         }
80         assert(idx < list->len);
82         str_utf8 = g_ptr_array_index(list, idx);
83         assert(str_utf8 != NULL);
85         str = utf8_to_locale(str_utf8);
86         g_snprintf(buf, BUFSIZE, "[%s]", str);
87         g_free(str);
89         return buf;
90 }
92 static void
93 screen_artist_paint(void);
95 static void
96 artist_repaint(void)
97 {
98         screen_artist_paint();
99         wrefresh(browser.lw->w);
102 static void
103 string_array_free(GPtrArray *array)
105         unsigned i;
107         for (i = 0; i < array->len; ++i) {
108                 char *value = g_ptr_array_index(array, i);
109                 g_free(value);
110         }
112         g_ptr_array_free(array, TRUE);
115 static void
116 free_lists(void)
118         if (artist_list != NULL) {
119                 string_array_free(artist_list);
120                 artist_list = NULL;
121         }
123         if (album_list != NULL) {
124                 string_array_free(album_list);
125                 album_list = NULL;
126         }
128         if (browser.filelist) {
129                 filelist_free(browser.filelist);
130                 browser.filelist = NULL;
131         }
134 static void
135 recv_tag_values(struct mpd_connection *connection, enum mpd_tag_type tag,
136                 GPtrArray *list)
138         struct mpd_pair *pair;
140         while ((pair = mpd_recv_pair_tag(connection, tag)) != NULL) {
141                 g_ptr_array_add(list, g_strdup(pair->value));
142                 mpd_return_pair(connection, pair);
143         }
146 static void
147 load_artist_list(struct mpdclient *c)
149         struct mpd_connection *connection = mpdclient_get_connection(c);
151         assert(mode == LIST_ARTISTS);
152         assert(artist == NULL);
153         assert(album == NULL);
154         assert(artist_list == NULL);
155         assert(album_list == NULL);
156         assert(browser.filelist == NULL);
158         artist_list = g_ptr_array_new();
160         if (connection != NULL) {
161                 mpd_search_db_tags(connection, MPD_TAG_ARTIST);
162                 mpd_search_commit(connection);
163                 recv_tag_values(connection, MPD_TAG_ARTIST, artist_list);
165                 if (!mpd_response_finish(connection))
166                         mpdclient_handle_error(c);
167         }
169         /* sort list */
170         g_ptr_array_sort(artist_list, compare_utf8);
171         list_window_set_length(browser.lw, artist_list->len);
174 static void
175 load_album_list(struct mpdclient *c)
177         struct mpd_connection *connection = mpdclient_get_connection(c);
179         assert(mode == LIST_ALBUMS);
180         assert(artist != NULL);
181         assert(album == NULL);
182         assert(album_list == NULL);
183         assert(browser.filelist == NULL);
185         album_list = g_ptr_array_new();
187         if (connection != NULL) {
188                 mpd_search_db_tags(connection, MPD_TAG_ALBUM);
189                 mpd_search_add_tag_constraint(connection,
190                                               MPD_OPERATOR_DEFAULT,
191                                               MPD_TAG_ARTIST, artist);
192                 mpd_search_commit(connection);
194                 recv_tag_values(connection, MPD_TAG_ALBUM, album_list);
196                 if (!mpd_response_finish(connection))
197                         mpdclient_handle_error(c);
198         }
200         /* sort list */
201         g_ptr_array_sort(album_list, compare_utf8);
203         list_window_set_length(browser.lw, album_list->len + 2);
206 static void
207 load_song_list(struct mpdclient *c)
209         struct mpd_connection *connection = mpdclient_get_connection(c);
211         assert(mode == LIST_SONGS);
212         assert(artist != NULL);
213         assert(album != NULL);
214         assert(browser.filelist == NULL);
216         browser.filelist = filelist_new();
217         /* add a dummy entry for ".." */
218         filelist_append(browser.filelist, NULL);
220         if (connection != NULL) {
221                 mpd_search_db_songs(connection, true);
222                 mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT,
223                                               MPD_TAG_ARTIST, artist);
224                 if (album[0] != 0)
225                         mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT,
226                                                       MPD_TAG_ALBUM, album);
227                 mpd_search_commit(connection);
229                 filelist_recv(browser.filelist, connection);
231                 if (!mpd_response_finish(connection))
232                         mpdclient_handle_error(c);
233         }
235         /* fix highlights */
236         screen_browser_sync_highlights(browser.filelist, &c->playlist);
237         list_window_set_length(browser.lw, filelist_length(browser.filelist));
240 static void
241 free_state(void)
243         g_free(artist);
244         g_free(album);
245         artist = NULL;
246         album = NULL;
248         free_lists();
251 static void
252 open_artist_list(struct mpdclient *c)
254         free_state();
256         mode = LIST_ARTISTS;
257         load_artist_list(c);
260 static void
261 open_album_list(struct mpdclient *c, char *_artist)
263         assert(_artist != NULL);
265         free_state();
267         mode = LIST_ALBUMS;
268         artist = _artist;
269         load_album_list(c);
272 static void
273 open_song_list(struct mpdclient *c, char *_artist, char *_album)
275         assert(_artist != NULL);
276         assert(_album != NULL);
278         free_state();
280         mode = LIST_SONGS;
281         artist = _artist;
282         album = _album;
283         load_song_list(c);
286 static void
287 reload_lists(struct mpdclient *c)
289         free_lists();
291         switch (mode) {
292         case LIST_ARTISTS:
293                 load_artist_list(c);
294                 break;
296         case LIST_ALBUMS:
297                 load_album_list(c);
298                 break;
300         case LIST_SONGS:
301                 load_song_list(c);
302                 break;
303         }
306 static void
307 screen_artist_init(WINDOW *w, int cols, int rows)
309         browser.lw = list_window_init(w, cols, rows);
310         artist = NULL;
311         album = NULL;
314 static void
315 screen_artist_quit(void)
317         free_state();
318         list_window_free(browser.lw);
321 static void
322 screen_artist_open(struct mpdclient *c)
324         if (artist_list == NULL && album_list == NULL &&
325             browser.filelist == NULL)
326                 reload_lists(c);
329 static void
330 screen_artist_resize(int cols, int rows)
332         list_window_resize(browser.lw, cols, rows);
335 static void
336 screen_artist_paint(void)
338         if (browser.filelist) {
339                 screen_browser_paint(&browser);
340         } else if (album_list != NULL)
341                 list_window_paint(browser.lw, screen_artist_lw_callback,
342                                   album_list);
343         else if (artist_list != NULL)
344                 list_window_paint(browser.lw, screen_artist_lw_callback,
345                                   artist_list);
346         else {
347                 wmove(browser.lw->w, 0, 0);
348                 wclrtobot(browser.lw->w);
349         }
352 static const char *
353 screen_artist_get_title(char *str, size_t size)
355         char *s1, *s2;
357         switch(mode) {
358         case LIST_ARTISTS:
359                 g_snprintf(str, size, _("All artists"));
360                 break;
362         case LIST_ALBUMS:
363                 s1 = utf8_to_locale(artist);
364                 g_snprintf(str, size, _("Albums of artist: %s"), s1);
365                 g_free(s1);
366                 break;
368         case LIST_SONGS:
369                 s1 = utf8_to_locale(artist);
370                 if (*album != 0) {
371                         s2 = utf8_to_locale(album);
372                         g_snprintf(str, size,
373                                    _("Album: %s - %s"), s1, s2);
374                         g_free(s2);
375                 } else
376                         g_snprintf(str, size,
377                                    _("All tracks of artist: %s"), s1);
378                 g_free(s1);
379                 break;
380         }
382         return str;
385 static void
386 screen_artist_update(struct mpdclient *c)
388         if (browser.filelist == NULL)
389                 return;
391         if (c->events & MPD_IDLE_DATABASE)
392                 /* the db has changed -> update the list */
393                 reload_lists(c);
395         if (c->events & (MPD_IDLE_DATABASE | MPD_IDLE_QUEUE))
396                 screen_browser_sync_highlights(browser.filelist, &c->playlist);
398         if (c->events & (MPD_IDLE_DATABASE
399 #ifndef NCMPC_MINI
400                          | MPD_IDLE_QUEUE
401 #endif
402                          ))
403                 artist_repaint();
406 static void
407 add_query(struct mpdclient *c, enum mpd_tag_type table, char *_filter)
409         struct mpd_connection *connection = mpdclient_get_connection(c);
410         char *str;
411         struct filelist *addlist;
413         assert(filter != NULL);
415         if (connection == NULL)
416                 return;
418         str = utf8_to_locale(_filter);
419         if (table == MPD_TAG_ALBUM)
420                 screen_status_printf("Adding album %s...", str);
421         else
422                 screen_status_printf("Adding %s...", str);
423         g_free(str);
425         mpd_search_db_songs(connection, true);
426         mpd_search_add_tag_constraint(connection, MPD_OPERATOR_DEFAULT,
427                                       table, _filter);
428         mpd_search_commit(connection);
430         addlist = filelist_new_recv(connection);
432         if (mpd_response_finish(connection))
433                 mpdclient_filelist_add_all(c, addlist);
434         else
435                 mpdclient_handle_error(c);
437         filelist_free(addlist);
440 static int
441 screen_artist_lw_cmd(struct mpdclient *c, command_t cmd)
443         switch (mode) {
444         case LIST_ARTISTS:
445         case LIST_ALBUMS:
446                 return list_window_cmd(browser.lw, cmd);
448         case LIST_SONGS:
449                 return browser_cmd(&browser, c, cmd);
450         }
452         assert(0);
453         return 0;
456 static int
457 string_array_find(GPtrArray *array, const char *value)
459         guint i;
461         for (i = 0; i < array->len; ++i)
462                 if (strcmp((const char*)g_ptr_array_index(array, i),
463                            value) == 0)
464                         return i;
466         return -1;
469 static bool
470 screen_artist_cmd(struct mpdclient *c, command_t cmd)
472         struct list_window_range range;
473         char *selected;
474         char *old;
475         int idx;
477         switch(cmd) {
478         case CMD_PLAY:
479                 switch (mode) {
480                 case LIST_ARTISTS:
481                         if (browser.lw->selected >= artist_list->len)
482                                 return true;
484                         selected = g_ptr_array_index(artist_list,
485                                                      browser.lw->selected);
486                         open_album_list(c, g_strdup(selected));
487                         list_window_reset(browser.lw);
489                         artist_repaint();
490                         return true;
492                 case LIST_ALBUMS:
493                         if (browser.lw->selected == 0) {
494                                 /* handle ".." */
495                                 old = g_strdup(artist);
497                                 open_artist_list(c);
498                                 list_window_reset(browser.lw);
499                                 /* restore previous list window state */
500                                 idx = string_array_find(artist_list, old);
501                                 g_free(old);
503                                 if (idx >= 0) {
504                                         list_window_set_cursor(browser.lw, idx);
505                                         list_window_center(browser.lw, idx);
506                                 }
507                         } else if (browser.lw->selected == album_list->len + 1) {
508                                 /* handle "show all" */
509                                 open_song_list(c, g_strdup(artist), g_strdup("\0"));
510                                 list_window_reset(browser.lw);
511                         } else {
512                                 /* select album */
513                                 selected = g_ptr_array_index(album_list,
514                                                              browser.lw->selected - 1);
515                                 open_song_list(c, g_strdup(artist), g_strdup(selected));
516                                 list_window_reset(browser.lw);
517                         }
519                         artist_repaint();
520                         return true;
522                 case LIST_SONGS:
523                         if (browser.lw->selected == 0) {
524                                 /* handle ".." */
525                                 old = g_strdup(album);
527                                 open_album_list(c, g_strdup(artist));
528                                 list_window_reset(browser.lw);
529                                 /* restore previous list window state */
530                                 idx = *old == 0
531                                         ? (int)album_list->len
532                                         : string_array_find(album_list, old);
533                                 g_free(old);
535                                 if (idx >= 0) {
536                                         ++idx;
537                                         list_window_set_cursor(browser.lw, idx);
538                                         list_window_center(browser.lw, idx);
539                                 }
541                                 artist_repaint();
542                                 return true;
543                         }
544                         break;
545                 }
546                 break;
548                 /* FIXME? CMD_GO_* handling duplicates code from CMD_PLAY */
550         case CMD_GO_PARENT_DIRECTORY:
551                 switch (mode) {
552                 case LIST_ARTISTS:
553                         break;
555                 case LIST_ALBUMS:
556                         old = g_strdup(artist);
558                         open_artist_list(c);
559                         list_window_reset(browser.lw);
560                         /* restore previous list window state */
561                         idx = string_array_find(artist_list, old);
562                         g_free(old);
564                         if (idx >= 0) {
565                                 list_window_set_cursor(browser.lw, idx);
566                                 list_window_center(browser.lw, idx);
567                         }
568                         break;
570                 case LIST_SONGS:
571                         old = g_strdup(album);
573                         open_album_list(c, g_strdup(artist));
574                         list_window_reset(browser.lw);
575                         /* restore previous list window state */
576                         idx = *old == 0
577                                 ? (int)album_list->len
578                                 : string_array_find(album_list, old);
579                         g_free(old);
581                         if (idx >= 0) {
582                                 ++idx;
583                                 list_window_set_cursor(browser.lw, idx);
584                                 list_window_center(browser.lw, idx);
585                         }
586                         break;
587                 }
589                 artist_repaint();
590                 break;
592         case CMD_GO_ROOT_DIRECTORY:
593                 switch (mode) {
594                 case LIST_ARTISTS:
595                         break;
597                 case LIST_ALBUMS:
598                 case LIST_SONGS:
599                         open_artist_list(c);
600                         list_window_reset(browser.lw);
601                         /* restore first list window state (pop while returning true) */
602                         /* XXX */
603                         break;
604                 }
606                 artist_repaint();
607                 break;
609         case CMD_SELECT:
610         case CMD_ADD:
611                 switch(mode) {
612                 case LIST_ARTISTS:
613                         if (browser.lw->selected >= artist_list->len)
614                                 return true;
616                         list_window_get_range(browser.lw, &range);
617                         for (unsigned i = range.start; i < range.end; ++i) {
618                                 selected = g_ptr_array_index(artist_list, i);
619                                 add_query(c, MPD_TAG_ARTIST, selected);
620                                 cmd = CMD_LIST_NEXT; /* continue and select next item... */
621                         }
622                         break;
624                 case LIST_ALBUMS:
625                         list_window_get_range(browser.lw, &range);
626                         for (unsigned i = range.start; i < range.end; ++i) {
627                                 if(i == album_list->len + 1)
628                                         add_query(c, MPD_TAG_ARTIST, artist);
629                                 else if (i > 0)
630                                 {
631                                         selected = g_ptr_array_index(album_list,
632                                                                      browser.lw->selected - 1);
633                                         add_query(c, MPD_TAG_ALBUM, selected);
634                                         cmd = CMD_LIST_NEXT; /* continue and select next item... */
635                                 }
636                         }
637                         break;
639                 case LIST_SONGS:
640                         /* handled by browser_cmd() */
641                         break;
642                 }
643                 break;
645                 /* continue and update... */
646         case CMD_SCREEN_UPDATE:
647                 reload_lists(c);
648                 return false;
650         case CMD_LIST_FIND:
651         case CMD_LIST_RFIND:
652         case CMD_LIST_FIND_NEXT:
653         case CMD_LIST_RFIND_NEXT:
654                 switch (mode) {
655                 case LIST_ARTISTS:
656                         screen_find(browser.lw, cmd,
657                                     screen_artist_lw_callback, artist_list);
658                         artist_repaint();
659                         return true;
661                 case LIST_ALBUMS:
662                         screen_find(browser.lw, cmd,
663                                     screen_artist_lw_callback, album_list);
664                         artist_repaint();
665                         return true;
667                 case LIST_SONGS:
668                         /* handled by browser_cmd() */
669                         break;
670                 }
671         case CMD_LIST_JUMP:
672                 switch (mode) {
673                 case LIST_ARTISTS:
674                         screen_jump(browser.lw, screen_artist_lw_callback,
675                                     NULL, artist_list);
676                         artist_repaint();
677                         return true;
679                 case LIST_ALBUMS:
680                         screen_jump(browser.lw, screen_artist_lw_callback,
681                                     NULL, album_list);
682                         artist_repaint();
683                         return true;
685                 case LIST_SONGS:
686                         /* handled by browser_cmd() */
687                         break;
688                 }
690                 break;
692         default:
693                 break;
694         }
696         if (screen_artist_lw_cmd(c, cmd)) {
697                 if (screen_is_visible(&screen_artist))
698                         artist_repaint();
699                 return true;
700         }
702         return false;
705 const struct screen_functions screen_artist = {
706         .init = screen_artist_init,
707         .exit = screen_artist_quit,
708         .open = screen_artist_open,
709         .resize = screen_artist_resize,
710         .paint = screen_artist_paint,
711         .update = screen_artist_update,
712         .cmd = screen_artist_cmd,
713         .get_title = screen_artist_get_title,
714 };