Code

8909638b05e866a7fae8896ee2887bbdf57dedbf
[ncmpc.git] / src / screen_artist.c
1 /* 
2  * $Id$
3  *
4  * (c) 2005 by Kalle Wallin <kaw@linux.se>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <glib.h>
25 #include <ncurses.h>
27 #include "config.h"
28 #ifndef DISABLE_ARTIST_SCREEN
29 #include "ncmpc.h"
30 #include "options.h"
31 #include "support.h"
32 #include "mpdclient.h"
33 #include "utils.h"
34 #include "strfsong.h"
35 #include "command.h"
36 #include "screen.h"
37 #include "screen_utils.h"
38 #include "screen_browse.h"
40 #define BUFSIZE 1024
42 typedef enum { LIST_ARTISTS, LIST_ALBUMS, LIST_SONGS } artist_mode_t;
44 static artist_mode_t mode = LIST_ARTISTS;
45 static char *artist = NULL;
46 static char *album  = NULL;
47 static list_window_t *lw = NULL;
48 static mpdclient_filelist_t *filelist = NULL;
49 static int metalist_length = 0;
50 static GList *metalist = NULL;
51 static list_window_state_t *lw_state = NULL;
53 /* list_window callback */
54 static char *
55 artist_lw_callback(int index, int *highlight, void *data)
56 {
57   static char buf[BUFSIZE];
58   char *str, *str_utf8;
59   
60   *highlight = 0;
61   if( (str_utf8=(char *) g_list_nth_data(metalist,index))==NULL )
62     return NULL;
64   str = utf8_to_locale(str_utf8);
65   g_snprintf(buf, BUFSIZE, "[%s]", str);
66   g_free(str);
68   return buf;
69 }
71 /* the playlist have been updated -> fix highlights */
72 static void 
73 playlist_changed_callback(mpdclient_t *c, int event, gpointer data)
74 {
75   if( filelist==NULL )
76     return;
77   D("screen_artist.c> playlist_callback() [%d]\n", event);
78   switch(event)
79     {
80     case PLAYLIST_EVENT_CLEAR:
81       clear_highlights(filelist);
82       break;
83     default:
84       sync_highlights(c, filelist);
85       break;
86     }
87 }
89 /* fetch artists/albums/songs from mpd */
90 static void
91 update_metalist(mpdclient_t *c, char *m_artist, char *m_album)
92 {
93   g_free(artist);
94   g_free(album);
95   artist = NULL;
96   album = NULL;
97   if( metalist )
98     metalist = string_list_free(metalist);
99   if (filelist ) {
100     mpdclient_remove_playlist_callback(c, playlist_changed_callback);
101     filelist = mpdclient_filelist_free(filelist);
102   }
103   if( m_album ) /* retreive songs... */
104     {
105       artist = m_artist;
106       album = m_album;
107       if( album[0] == 0 )
108         {
109           album = g_strdup(_("All tracks"));
110           filelist = mpdclient_filelist_search_utf8(c,  
111                                                     TRUE,
112                                                     MPD_TABLE_ARTIST,
113                                                     artist);
114         }
115       else
116         filelist = mpdclient_filelist_search_utf8(c,  
117                                                   TRUE,
118                                                   MPD_TABLE_ALBUM,
119                                                   album);
120       /* add a dummy entry for ".." */
121       filelist_entry_t *entry = g_malloc0(sizeof(filelist_entry_t));
122       entry->entity = NULL;
123       filelist->list = g_list_insert(filelist->list, entry, 0);
124       filelist->length++;
125       /* install playlist callback and fix highlights */
126       sync_highlights(c, filelist);
127       mpdclient_install_playlist_callback(c, playlist_changed_callback);
128       mode = LIST_SONGS;
129     }
130   else if( m_artist ) /* retreive albums... */
131     {
132       artist = m_artist;
133       metalist = mpdclient_get_albums_utf8(c, m_artist);
134       /* add a dummy entry for ".." */
135       metalist = g_list_insert(metalist, g_strdup(".."), 0);
136       /* add a dummy entry for all songs */
137       metalist = g_list_insert(metalist, g_strdup(_("All tracks")), -1);
138       mode = LIST_ALBUMS;
139     }
140   else /* retreive artists... */
141     {
142       metalist = mpdclient_get_artists_utf8(c);
143       mode = LIST_ARTISTS;
144     }
145   metalist_length = g_list_length(metalist);
146   lw->clear = TRUE;
149 /* db updated */
150 static void 
151 browse_callback(mpdclient_t *c, int event, gpointer data)
153   switch(event)
154     {
155     case BROWSE_DB_UPDATED:
156       D("screen_artist.c> browse_callback() [BROWSE_DB_UPDATED]\n");
157       lw->clear = 1;
158       lw->repaint = 1;
159       update_metalist(c, g_strdup(artist), g_strdup(album));
160       break;
161     default:
162       break;
163     }
166 static void
167 init(WINDOW *w, int cols, int rows)
169   lw = list_window_init(w, cols, rows);
170   lw_state = list_window_init_state();
171   artist = NULL;
172   album = NULL;
175 static void
176 quit(void)
178   if( filelist )
179     filelist = mpdclient_filelist_free(filelist);
180   if( metalist )
181     metalist = string_list_free(metalist);
182   g_free(artist);
183   g_free(album);
184   artist = NULL;
185   album = NULL;
186   lw = list_window_free(lw);  
187   lw_state = list_window_free_state(lw_state);
190 static void
191 open(screen_t *screen, mpdclient_t *c)
193   static gboolean callback_installed = FALSE;
195   if( metalist==NULL && filelist ==NULL)
196     update_metalist(c, NULL, NULL);
197   if( !callback_installed )
198     {
199       mpdclient_install_browse_callback(c, browse_callback);
200       callback_installed = TRUE;
201     }
204 static void
205 resize(int cols, int rows)
207   lw->cols = cols;
208   lw->rows = rows;
211 static void
212 close(void)
216 static void 
217 paint(screen_t *screen, mpdclient_t *c)
219   lw->clear = 1;
220   
221   if( filelist )
222     {
223       list_window_paint(lw, browse_lw_callback, (void *) filelist);
224       filelist->updated = FALSE;
225     }
226   else if( metalist )
227     {
228       list_window_paint(lw, artist_lw_callback, (void *) metalist);
229     }
230   else
231     {
232       wmove(lw->w, 0, 0);
233       wclrtobot(lw->w);
234     }
235   wnoutrefresh(lw->w);
238 static void 
239 update(screen_t *screen, mpdclient_t *c)
241   if( filelist && !filelist->updated )
242     {
243       list_window_paint(lw, browse_lw_callback, (void *) filelist);
244     }
245   else if( metalist )
246     {
247       list_window_paint(lw, artist_lw_callback, (void *) metalist);
248     }
249   else
250     {
251       paint(screen, c);
252     }
253   wnoutrefresh(lw->w);
256 static char *
257 get_title(char *str, size_t size)
259   char *s1 = artist ? utf8_to_locale(artist) : NULL;
260   char *s2 = album ? utf8_to_locale(album) : NULL;
262   switch(mode)
263     {
264     case LIST_ARTISTS:
265       g_snprintf(str, size,  _("Artist: [db browser - EXPERIMENTAL]"));
266       break;
267     case LIST_ALBUMS:
268       g_snprintf(str, size,  _("Artist: %s"), s1);
269       break;
270     case LIST_SONGS:
271       g_snprintf(str, size,  _("Artist: %s - %s"), s1, s2);
272       break;
273     }
274   g_free(s1);
275   g_free(s2);
276   return str;
279 static list_window_t *
280 get_filelist_window()
282   return lw;
285 static void
286 add_query(mpdclient_t *c, int table, char *filter)
288   char *str;
289   mpdclient_filelist_t *addlist;
291   str = utf8_to_locale(filter);
292   if( table== MPD_TABLE_ALBUM )
293     screen_status_printf("Adding album %s...", str);
294   else
295     screen_status_printf("Adding %s...", str);
296   g_free(str);
297   addlist = mpdclient_filelist_search_utf8(c, TRUE, table, filter);
298   if( addlist )
299     {
300       mpdclient_filelist_add_all(c, addlist);
301       addlist = mpdclient_filelist_free(addlist);
302     }
305 static int 
306 artist_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
308   char *selected;
310   switch(cmd)
311     {
312     case CMD_PLAY:
313       switch(mode)
314         {
315         case LIST_ARTISTS:
316           selected = (char *) g_list_nth_data(metalist, lw->selected);
317           update_metalist(c, g_strdup(selected), NULL);
318           list_window_push_state(lw_state,lw); 
319           break;
320         case LIST_ALBUMS:
321           if( lw->selected == 0 )  /* handle ".." */
322             {
323               update_metalist(c, NULL, NULL);
324               list_window_reset(lw);
325               /* restore previous list window state */
326               list_window_pop_state(lw_state,lw); 
327             }
328           else if( lw->selected == metalist_length-1) /* handle "show all" */
329             {
330               update_metalist(c, g_strdup(artist), g_strdup("\0"));
331               list_window_push_state(lw_state,lw); 
332             }
333           else /* select album */
334             {
335               selected = (char *) g_list_nth_data(metalist, lw->selected);
336               update_metalist(c, g_strdup(artist), g_strdup(selected));
337               list_window_push_state(lw_state,lw); 
338             }
339           break;
340         case LIST_SONGS:
341           if( lw->selected==0 )  /* handle ".." */
342             {
343               update_metalist(c, g_strdup(artist), NULL);
344               list_window_reset(lw);
345               /* restore previous list window state */
346               list_window_pop_state(lw_state,lw); 
347             }
348           else
349             browse_handle_enter(screen, c, lw, filelist);
350           break;
351         }
352       return 1;
354     case CMD_SELECT:
355       switch(mode)
356         {
357         case LIST_ARTISTS:
358           selected = (char *) g_list_nth_data(metalist, lw->selected);
359           add_query(c, MPD_TABLE_ARTIST, selected);
360           cmd = CMD_LIST_NEXT; /* continue and select next item... */
361           break;
362         case LIST_ALBUMS:
363           if( lw->selected && lw->selected == metalist_length-1)
364             {
365               add_query(c, MPD_TABLE_ARTIST, artist);
366             }
367           else if( lw->selected > 0 )
368             {
369               selected = (char *) g_list_nth_data(metalist, lw->selected);
370               add_query(c, MPD_TABLE_ALBUM, selected);
371               cmd = CMD_LIST_NEXT; /* continue and select next item... */
372             }
373           break;
374         case LIST_SONGS:
375           if( browse_handle_select(screen, c, lw, filelist) == 0 )
376             {
377               cmd = CMD_LIST_NEXT; /* continue and select next item... */
378             }
379           break;
380         }
381       break;
383       /* continue and update... */
384     case CMD_SCREEN_UPDATE:
385       screen->painted = 0;
386       lw->clear = 1;
387       lw->repaint = 1;
388       update_metalist(c, g_strdup(artist), g_strdup(album));
389       screen_status_printf(_("Screen updated!"));
390       return 0;
392     case CMD_LIST_FIND:
393     case CMD_LIST_RFIND:
394     case CMD_LIST_FIND_NEXT:
395     case CMD_LIST_RFIND_NEXT:
396       if( filelist )
397         return screen_find(screen, c, 
398                            lw, filelist->length,
399                            cmd, browse_lw_callback, (void *) filelist);
400       else if ( metalist )
401         return screen_find(screen, c, 
402                            lw, metalist_length,
403                            cmd, artist_lw_callback, (void *) metalist);
404       else
405         return 1;
407     case CMD_MOUSE_EVENT:
408       return browse_handle_mouse_event(screen,c,lw,filelist);
410     default:
411       break;
412     }
414   if( filelist )
415     return list_window_cmd(lw, filelist->length, cmd);
416   else if( metalist )
417     return list_window_cmd(lw, metalist_length, cmd);
419   
420   return 0;
423 screen_functions_t *
424 get_screen_artist(void)
426   static screen_functions_t functions;
428   memset(&functions, 0, sizeof(screen_functions_t));
429   functions.init   = init;
430   functions.exit   = quit;
431   functions.open   = open;
432   functions.close  = close;
433   functions.resize = resize;
434   functions.paint  = paint;
435   functions.update = update;
436   functions.cmd    = artist_cmd;
437   functions.get_lw = get_filelist_window;
438   functions.get_title = get_title;
440   return &functions;
444 #endif /* ENABLE_ARTIST_SCREEN */