Code

e09d9f04927779ba0ff4481b9cc42a30f3ec3713
[ncmpc.git] / src / screen_artist.c
1 /* 
2  * $Id$
3  *
4  * (c) 2004 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 static char *artist = NULL;
43 static char *album  = NULL;
44 static list_window_t *lw = NULL;
45 static mpdclient_filelist_t *filelist = NULL;
46 static int metalist_length = 0;
47 static GList *metalist = NULL;
48 static GList *lw_state_list = NULL;
50 /* store current state when entering a subdirectory */
51 static void
52 push_lw_state(void)
53 {
54   list_window_t *tmp = g_malloc(sizeof(list_window_t));
56   memcpy(tmp, lw, sizeof(list_window_t));
57   lw_state_list = g_list_prepend(lw_state_list, (gpointer) tmp);
58 }
60 /* get previous state when leaving a directory */
61 static void
62 pop_lw_state(void)
63 {
64   if( lw_state_list )
65     {
66       list_window_t *tmp = lw_state_list->data;
68       memcpy(lw, tmp, sizeof(list_window_t));
69       g_free(tmp);
70       lw_state_list->data = NULL;
71       lw_state_list = g_list_delete_link(lw_state_list, lw_state_list);
72     }
73 }
75 /* list_window callback */
76 static char *
77 artist_lw_callback(int index, int *highlight, void *data)
78 {
79   static char buf[BUFSIZE];
80   char *str, *str_utf8;
81   
82   *highlight = 0;
83   if( (str_utf8=(char *) g_list_nth_data(metalist,index))==NULL )
84     return NULL;
86   str = utf8_to_locale(str_utf8);
87   g_snprintf(buf, BUFSIZE, "[%s]", str);
88   g_free(str);
90   return buf;
91 }
93 /* the playlist have been updated -> fix highlights */
94 static void 
95 playlist_changed_callback(mpdclient_t *c, int event, gpointer data)
96 {
97   if( filelist==NULL )
98     return;
99   D("screen_artist.c> playlist_callback() [%d]\n", event);
100   switch(event)
101     {
102     case PLAYLIST_EVENT_CLEAR:
103       clear_highlights(filelist);
104       break;
105     default:
106       sync_highlights(c, filelist);
107       break;
108     }
111 static void
112 update_metalist(mpdclient_t *c, char *m_artist, char *m_album)
114   g_free(artist);
115   g_free(album);
116   artist = NULL;
117   album = NULL;
118   if( metalist )
119     metalist = string_list_free(metalist);
120   if (filelist ) {
121     mpdclient_remove_playlist_callback(c, playlist_changed_callback);
122     filelist = mpdclient_filelist_free(filelist);
123   }
124   if( m_album ) /* retreive songs... */
125     {
126       artist = m_artist;
127       album = m_album;
128       if( album[0] == 0 )
129         {
130           album = g_strdup(_("All tracks"));
131           filelist = mpdclient_filelist_search_utf8(c,  
132                                                     MPD_TABLE_ARTIST,
133                                                     artist);
134         }
135       else
136         filelist = mpdclient_filelist_search_utf8(c,  
137                                                   MPD_TABLE_ALBUM,
138                                                   album);
139       /* add a dummy entry for ".." */
140       filelist_entry_t *entry = g_malloc0(sizeof(filelist_entry_t));
141       entry->entity = NULL;
142       filelist->list = g_list_insert(filelist->list, entry, 0);
143       filelist->length++;
144       /* install playlist callback and fix highlights */
145       sync_highlights(c, filelist);
146       mpdclient_install_playlist_callback(c, playlist_changed_callback);
147     }
148   else if( m_artist ) /* retreive albums... */
149     {
150       artist = m_artist;
151       metalist = mpdclient_get_albums_utf8(c, m_artist);
152       /* add a dummy entry for ".." */
153       metalist = g_list_insert(metalist, g_strdup(".."), 0);
154       /* add a dummy entry for all songs */
155       metalist = g_list_insert(metalist, g_strdup(_("All tracks")), -1);
157     }
158   else /* retreive artists... */
159     {
160       metalist = mpdclient_get_artists_utf8(c);
161     }
162   metalist_length = g_list_length(metalist);
165 static void
166 init(WINDOW *w, int cols, int rows)
168   lw = list_window_init(w, cols, rows);
169   artist = NULL;
170   album = NULL;
173 static void
174 quit(void)
176   /* clear list window state */
177   if( lw_state_list )
178     {
179       GList *list = lw_state_list;
180       while( list )
181         {
182           g_free(list->data);
183           list->data = NULL;
184           list = list->next;
185         }
186       g_list_free(lw_state_list);
187       lw_state_list = NULL;
188     }
189   
190   if( filelist )
191     filelist = mpdclient_filelist_free(filelist);
192   if( metalist )
193     metalist = string_list_free(metalist);
194   g_free(artist);
195   g_free(album);
196   artist = NULL;
197   album = NULL;
198   list_window_free(lw);  
201 static void
202 open(screen_t *screen, mpdclient_t *c)
204   if( metalist==NULL && filelist ==NULL)
205     update_metalist(c, NULL, NULL);
208 static void
209 resize(int cols, int rows)
211   lw->cols = cols;
212   lw->rows = rows;
215 static void
216 close(void)
220 static void 
221 paint(screen_t *screen, mpdclient_t *c)
223   lw->clear = 1;
224   
225   if( filelist )
226     {
227       list_window_paint(lw, browse_lw_callback, (void *) filelist);
228       filelist->updated = FALSE;
229     }
230   else if( metalist )
231     {
232       list_window_paint(lw, artist_lw_callback, (void *) metalist);
233     }
234   else
235     {
236       wmove(lw->w, 0, 0);
237       wclrtobot(lw->w);
238     }
239   wnoutrefresh(lw->w);
242 static void 
243 update(screen_t *screen, mpdclient_t *c)
245   if( filelist==NULL || filelist->updated )
246     {
247       paint(screen, c);
248       return;
249     }
250   list_window_paint(lw, browse_lw_callback, (void *) filelist);
251   wnoutrefresh(lw->w);
254 static char *
255 get_title(char *str, size_t size)
257   char *s1 = artist ? utf8_to_locale(artist) : NULL;
258   char *s2 = album ? utf8_to_locale(album) : NULL;
260   if( album )
261     g_snprintf(str, size,  _("Artist: %s - %s"), s1, s2);
262   else if( artist )
263     g_snprintf(str, size,  _("Artist: %s"), s1);
264   else
265     g_snprintf(str, size,  _("Artist: [db browser - EXPERIMENTAL]"));
266   g_free(s1);
267   g_free(s2);
268   return str;
271 static list_window_t *
272 get_filelist_window()
274   return lw;
277 static int 
278 artist_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
280   switch(cmd)
281     {
282     case CMD_PLAY:
283       if( artist && album )
284         {
285           if( lw->selected==0 )  /* handle ".." */
286             {
287               update_metalist(c, g_strdup(artist), NULL);
288               list_window_reset(lw);
289               /* restore previous list window state */
290               pop_lw_state(); 
291             }
292           else
293             browse_handle_enter(screen, c, lw, filelist);
294         }
295       else if ( artist )
296         {
297           if( lw->selected == 0 )  /* handle ".." */
299             {
300               update_metalist(c, NULL, NULL);
301               list_window_reset(lw);
302               /* restore previous list window state */
303               pop_lw_state(); 
304             }
305           else if( lw->selected == metalist_length-1) /* handle "show all" */
306             {
307               update_metalist(c, g_strdup(artist), g_strdup("\0"));
308               push_lw_state(); 
309               list_window_reset(lw);
310             }
311           else /* select album */
312             {
313               char *selected = (char *) g_list_nth_data(metalist, lw->selected);
314               update_metalist(c, g_strdup(artist), g_strdup(selected));
315               push_lw_state(); 
316               list_window_reset(lw);
317             }
318         }
319       else
320         {
321           char *selected = (char *) g_list_nth_data(metalist, lw->selected);
322           update_metalist(c, g_strdup(selected), NULL);
323           push_lw_state(); 
324           list_window_reset(lw);
325         }
326       return 1;
328     case CMD_SELECT:
329       if( browse_handle_select(screen, c, lw, filelist) == 0 )
330         {
331           /* continue and select next item... */
332           cmd = CMD_LIST_NEXT;
333         }
334       return 1;
336       /* continue and update... */
337     case CMD_SCREEN_UPDATE:
338       return 0;
340     case CMD_LIST_FIND:
341     case CMD_LIST_RFIND:
342     case CMD_LIST_FIND_NEXT:
343     case CMD_LIST_RFIND_NEXT:
344       if( filelist )
345         return screen_find(screen, c, 
346                            lw, filelist->length,
347                            cmd, browse_lw_callback, (void *) filelist);
348       else if ( metalist )
349         return screen_find(screen, c, 
350                            lw, metalist_length,
351                            cmd, artist_lw_callback, (void *) metalist);
352       else
353         return 1;
355     case CMD_MOUSE_EVENT:
356       return browse_handle_mouse_event(screen,c,lw,filelist);
358     default:
359       if( filelist )
360         return list_window_cmd(lw, filelist->length, cmd);
361       else if( metalist )
362         return list_window_cmd(lw, metalist_length, cmd);
363     }
364   
365   return 0;
368 screen_functions_t *
369 get_screen_artist(void)
371   static screen_functions_t functions;
373   memset(&functions, 0, sizeof(screen_functions_t));
374   functions.init   = init;
375   functions.exit   = quit;
376   functions.open   = open;
377   functions.close  = close;
378   functions.resize = resize;
379   functions.paint  = paint;
380   functions.update = update;
381   functions.cmd    = artist_cmd;
382   functions.get_lw = get_filelist_window;
383   functions.get_title = get_title;
385   return &functions;
389 #endif /* ENABLE_ARTIST_SCREEN */