Code

Added support for a configuration file ~/.ncmpcrc and color support.
[ncmpc.git] / screen_file.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <glib.h>
4 #include <ncurses.h>
6 #include "config.h"
7 #include "support.h"
8 #include "libmpdclient.h"
9 #include "mpc.h"
10 #include "command.h"
11 #include "screen.h"
12 #include "screen_utils.h"
13 #include "screen_file.h"
15 #define BUFSIZE 1024
17 static char *
18 list_callback(int index, int *highlight, void *data)
19 {
20   static char buf[BUFSIZE];
21   mpd_client_t *c = (mpd_client_t *) data;
22   filelist_entry_t *entry;
23   mpd_InfoEntity *entity;
25   *highlight = 0;
26   if( (entry=(filelist_entry_t *) g_list_nth_data(c->filelist, index))==NULL )
27     return NULL;
29   entity = entry->entity;
30   *highlight = entry->selected;
32   if( entity == NULL )
33     {
34       return "[Back]";
35     }
36   if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY ) 
37     {
38       mpd_Directory *dir = entity->info.directory;
39       char *dirname = utf8_to_locale(basename(dir->path));
41       snprintf(buf, BUFSIZE, "[%s]", dirname);
42       free(dirname);
43       return buf;
44     }
45   else if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
46     {
47       mpd_Song *song = entity->info.song;
48       return mpc_get_song_name(song);
49     }
50   else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
51     {
52       mpd_PlaylistFile *plf = entity->info.playlistFile;
53       char *filename = utf8_to_locale(basename(plf->path));
54       
55       snprintf(buf, BUFSIZE, "%s*", filename);
56       free(filename);
57       return buf;
58     }
59   return "Error: Unknow entry!";
60 }
62 static void
63 change_directory(screen_t *screen, mpd_client_t *c)
64 {
65   list_window_t *w = screen->filelist;
66   filelist_entry_t *entry;
67   mpd_InfoEntity *entity;
69   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
70   if( entry==NULL )
71     return;
73   entity = entry->entity;
74   if( entity==NULL )
75     {
76       char *parent = g_path_get_dirname(c->cwd);
78       if( strcmp(parent,".") == 0 )
79         {
80           parent[0] = '\0';
81         }
82       if( c->cwd )
83         free(c->cwd);
84       c->cwd = parent;
85     }
86   else
87     if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
88       {
89         mpd_Directory *dir = entity->info.directory;
90         if( c->cwd )
91           free(c->cwd);
92         c->cwd = strdup(dir->path);      
93       }
94     else
95       return;
96   
97   mpc_update_filelist(c);
98   list_window_reset(w);
99 }
102 static int
103 add_directory(mpd_client_t *c, char *dir)
105   mpd_InfoEntity *entity;
106   GList *subdir_list = NULL;
107   GList *list = NULL;
108   char *dirname;
110   dirname = utf8_to_locale(dir);
111   screen_status_printf("Adding directory %s...\n", dirname);
112   free(dirname);
113   dirname = NULL;
115   mpd_sendLsInfoCommand(c->connection, dir);
116   mpd_sendCommandListBegin(c->connection);
117   while( (entity=mpd_getNextInfoEntity(c->connection)) )
118     {
119       if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
120         {
121           mpd_Song *song = entity->info.song;
122           mpd_sendAddCommand(c->connection, song->file);
123           mpd_freeInfoEntity(entity);
124         }
125       else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
126         {
127           subdir_list = g_list_append(subdir_list, (gpointer) entity); 
128         }
129       else
130         mpd_freeInfoEntity(entity);
131     }
132   mpd_sendCommandListEnd(c->connection);
133   mpd_finishCommand(c->connection);
134   
135   list = g_list_first(subdir_list);
136   while( list!=NULL )
137     {
138       mpd_Directory *dir;
140       entity = list->data;
141       dir = entity->info.directory;
142       add_directory(c, dir->path);
143       mpd_freeInfoEntity(entity);
144       list->data=NULL;
145       list=list->next;
146     }
147   g_list_free(subdir_list);
148   return 0;
151 static void
152 select_entry(screen_t *screen, mpd_client_t *c)
154   list_window_t *w = screen->filelist;
155   filelist_entry_t *entry;
157   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
158   if( entry==NULL || entry->entity==NULL)
159     return;
161   if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
162     {
163       mpd_Directory *dir = entry->entity->info.directory;
164       add_directory(c, dir->path);
165       return;
166     }
168   if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
169     return; /* No support for adding dirs... :( */
171   entry->selected = !entry->selected;
173   if( entry->selected )
174     {
175       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
176         {
177           mpd_Song *song = entry->entity->info.song;
179           mpd_sendAddCommand(c->connection, song->file);
180           mpd_finishCommand(c->connection);
182           screen_status_printf("Adding \'%s\' to playlist\n", 
183                                mpc_get_song_name(song));
184         }
185     }
186   else
187     {
188       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
189         {
190           int i;
191           mpd_Song *song = entry->entity->info.song;
192           
193           i = mpc_playlist_get_song_index(c, song->file);
194           if( i>=0 )
195             {
196               mpd_sendDeleteCommand(c->connection, i);
197               mpd_finishCommand(c->connection);
198               screen_status_printf("Removed \'%s\' from playlist\n", 
199                                    mpc_get_song_name(song));
201             }
202         }
203     }
204   
207 void
208 file_clear_highlights(mpd_client_t *c)
210   GList *list = g_list_first(c->filelist);
211   
212   while( list )
213     {
214       filelist_entry_t *entry = list->data;
216       entry->selected = 0;
217       list = list->next;
218     }
221 void
222 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
224   GList *list = g_list_first(c->filelist);
226   if( !song )
227     return;
229   while( list )
230     {
231       filelist_entry_t *entry = list->data;
232       mpd_InfoEntity *entity  = entry->entity;
234       if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
235         {
236           mpd_Song *song2 = entity->info.song;
238           if( strcmp(song->file, song2->file) == 0 )
239             {
240               entry->selected = 0;
241             }
242         }
243       list = list->next;
244     }
247 char *
248 file_get_header(mpd_client_t *c)
250   static char buf[64];
251   char *tmp;
253   tmp = utf8_to_locale(basename(c->cwd));
254   snprintf(buf, 64, 
255            TOP_HEADER_FILE ": %s                          ",
256            tmp
257            );
258   free(tmp);
260   return buf;
263 void 
264 file_open(screen_t *screen, mpd_client_t *c)
266   if( c->filelist == NULL )
267     {
268       mpc_update_filelist(c);
269     }
272 void 
273 file_close(screen_t *screen, mpd_client_t *c)
277 void 
278 file_paint(screen_t *screen, mpd_client_t *c)
280   list_window_t *w = screen->filelist;
281  
282   w->clear = 1;
283   
284   list_window_paint(screen->filelist, list_callback, (void *) c);
285   wrefresh(screen->filelist->w);
288 void 
289 file_update(screen_t *screen, mpd_client_t *c)
291   if( c->filelist_updated )
292     {
293       file_paint(screen, c);
294       c->filelist_updated = 0;
295       return;
296     }
297   list_window_paint(screen->filelist, list_callback, (void *) c);
298   wrefresh(screen->filelist->w);
302 int 
303 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
305   switch(cmd)
306     {
307     case CMD_PLAY:
308       change_directory(screen, c);
309       return 1;
310     case CMD_SELECT:
311       select_entry(screen, c);
312       /* continue and select next item... */
313       cmd = CMD_LIST_NEXT;
314       break;
315     case CMD_LIST_FIND:
316       if( screen->findbuf )
317         {
318           free(screen->findbuf);
319           screen->findbuf=NULL;
320         }
321       /* continue... */
322     case CMD_LIST_FIND_NEXT:
323       if( !screen->findbuf )
324         screen->findbuf=screen_readln(screen->status_window.w, "/");
325       if( list_window_find(screen->filelist,
326                            list_callback,
327                            c,
328                            screen->findbuf) == 0 )
329         {
330           screen->filelist->repaint  = 1;
331         }
332       else
333         {
334           screen_status_printf("Unable to find \'%s\'", screen->findbuf);
335           beep();
336         }
337       return 1;
338     default:
339       break;
340     }
341   return list_window_cmd(screen->filelist, c->filelist_length, cmd);