Code

Renamed ncmpcrc.sample config.sample.
[ncmpc.git] / screen_file.c
1 #include <ctype.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <glib.h>
5 #include <ncurses.h>
7 #include "config.h"
8 #include "support.h"
9 #include "libmpdclient.h"
10 #include "mpc.h"
11 #include "command.h"
12 #include "screen.h"
13 #include "screen_utils.h"
14 #include "screen_file.h"
16 #define BUFSIZE 1024
18 #define USE_OLD_LAYOUT
20 static char *
21 list_callback(int index, int *highlight, void *data)
22 {
23   static char buf[BUFSIZE];
24   mpd_client_t *c = (mpd_client_t *) data;
25   filelist_entry_t *entry;
26   mpd_InfoEntity *entity;
28   *highlight = 0;
29   if( (entry=(filelist_entry_t *) g_list_nth_data(c->filelist, index))==NULL )
30     return NULL;
32   entity = entry->entity;
33   *highlight = entry->selected;
35   if( entity == NULL )
36     {
37 #ifdef USE_OLD_LAYOUT
38       return "[..]";
39 #else
40       return "d ..";
41 #endif
42     }
43   if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY ) 
44     {
45       mpd_Directory *dir = entity->info.directory;
46       char *dirname = utf8_to_locale(basename(dir->path));
48 #ifdef USE_OLD_LAYOUT
49       snprintf(buf, BUFSIZE, "[%s]", dirname);
50 #else
51       snprintf(buf, BUFSIZE, "d %s", dirname);
52 #endif
53       g_free(dirname);
54       return buf;
55     }
56   else if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
57     {
58       mpd_Song *song = entity->info.song;
60 #ifdef USE_OLD_LAYOUT      
61       return mpc_get_song_name(song);
62 #else
63       snprintf(buf, BUFSIZE, "m %s", mpc_get_song_name(song));
64       return buf;
65 #endif
67     }
68   else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
69     {
70       mpd_PlaylistFile *plf = entity->info.playlistFile;
71       char *filename = utf8_to_locale(basename(plf->path));
73 #ifdef USE_OLD_LAYOUT      
74       snprintf(buf, BUFSIZE, "*%s*", filename);
75 #else      
76       snprintf(buf, BUFSIZE, "p %s", filename);
77 #endif
78       g_free(filename);
79       return buf;
80     }
81   return "Error: Unknow entry!";
82 }
84 static int
85 change_directory(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
86 {
87   list_window_t *w = screen->filelist;
88   mpd_InfoEntity *entity = entry->entity;
90   if( entity==NULL )
91     {
92       char *parent = g_path_get_dirname(c->cwd);
94       if( strcmp(parent,".") == 0 )
95         {
96           parent[0] = '\0';
97         }
98       if( c->cwd )
99         g_free(c->cwd);
100       c->cwd = parent;
101     }
102   else
103     if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
104       {
105         mpd_Directory *dir = entity->info.directory;
106         if( c->cwd )
107           g_free(c->cwd);
108         c->cwd = g_strdup(dir->path);      
109       }
110     else
111       return -1;
112   
113   mpc_update_filelist(c);
114   list_window_reset(w);
115   return 0;
118 static int
119 load_playlist(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
121   mpd_InfoEntity *entity = entry->entity;
122   mpd_PlaylistFile *plf = entity->info.playlistFile;
123   char *filename = utf8_to_locale(basename(plf->path));
125   mpd_sendLoadCommand(c->connection, plf->path);
126   mpd_finishCommand(c->connection);
128   screen_status_printf("Loading playlist %s...", filename);
129   g_free(filename);
130   return 0;
133 static int 
134 handle_delete(screen_t *screen, mpd_client_t *c)
136   list_window_t *lw = screen->filelist;
137   filelist_entry_t *entry;
138   mpd_InfoEntity *entity;
139   mpd_PlaylistFile *plf;
140   char *str, buf[BUFSIZE];
141   int key;
143   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, lw->selected);
144   if( entry==NULL || entry->entity==NULL )
145     return -1;
147   entity = entry->entity;
149   if( entity->type!=MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
150     {
151       screen_status_printf("You can only delete playlists!");
152       beep();
153       return -1;
154     }
156   plf = entity->info.playlistFile;
157   str = utf8_to_locale(basename(plf->path));
158   snprintf(buf, BUFSIZE, "Delete playlist %s [y/n] ? ", str);
159   g_free(str);  
160   key = tolower(screen_getch(screen->status_window.w, buf));
161   if( key!='y' )
162     {
163       screen_status_printf("Aborted!");
164       return 0;
165     }
167   mpd_sendRmCommand(c->connection, plf->path);
168   mpd_finishCommand(c->connection);
169   if( mpc_error(c))
170     {
171       str = utf8_to_locale(mpc_error_str(c));
172       screen_status_printf("Error: %s", str);
173       g_free(str);
174       beep();
175       return -1;
176     }
177   screen_status_printf("Playlist deleted!");
178   mpc_update_filelist(c);
179   list_window_check_selected(lw, c->filelist_length);
180   return 0;
184 static int
185 handle_play_cmd(screen_t *screen, mpd_client_t *c)
187   list_window_t *w = screen->filelist;
188   filelist_entry_t *entry;
189   mpd_InfoEntity *entity;
190   
191   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
192   if( entry==NULL )
193     return -1;
195   entity = entry->entity;
196   if( entity==NULL || entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
197     return change_directory(screen, c, entry);
198   else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
199     return load_playlist(screen, c, entry);
200   return -1;
203 static int
204 add_directory(mpd_client_t *c, char *dir)
206   mpd_InfoEntity *entity;
207   GList *subdir_list = NULL;
208   GList *list = NULL;
209   char *dirname;
211   dirname = utf8_to_locale(dir);
212   screen_status_printf("Adding directory %s...\n", dirname);
213   doupdate(); 
214   g_free(dirname);
215   dirname = NULL;
217   mpd_sendLsInfoCommand(c->connection, dir);
218   mpd_sendCommandListBegin(c->connection);
219   while( (entity=mpd_getNextInfoEntity(c->connection)) )
220     {
221       if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
222         {
223           mpd_Song *song = entity->info.song;
224           mpd_sendAddCommand(c->connection, song->file);
225           mpd_freeInfoEntity(entity);
226         }
227       else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
228         {
229           subdir_list = g_list_append(subdir_list, (gpointer) entity); 
230         }
231       else
232         mpd_freeInfoEntity(entity);
233     }
234   mpd_sendCommandListEnd(c->connection);
235   mpd_finishCommand(c->connection);
236   
237   list = g_list_first(subdir_list);
238   while( list!=NULL )
239     {
240       mpd_Directory *dir;
242       entity = list->data;
243       dir = entity->info.directory;
244       add_directory(c, dir->path);
245       mpd_freeInfoEntity(entity);
246       list->data=NULL;
247       list=list->next;
248     }
249   g_list_free(subdir_list);
250   return 0;
253 static int
254 handle_select(screen_t *screen, mpd_client_t *c)
256   list_window_t *w = screen->filelist;
257   filelist_entry_t *entry;
259   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
260   if( entry==NULL || entry->entity==NULL)
261     return -1;
263   if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
264     {
265       mpd_Directory *dir = entry->entity->info.directory;
266       add_directory(c, dir->path);
267       return 0;
268     }
270   if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
271     return -1; 
273   entry->selected = !entry->selected;
275   if( entry->selected )
276     {
277       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
278         {
279           mpd_Song *song = entry->entity->info.song;
281           mpd_sendAddCommand(c->connection, song->file);
282           mpd_finishCommand(c->connection);
284           screen_status_printf("Adding \'%s\' to playlist\n", 
285                                mpc_get_song_name(song));
286         }
287     }
288   else
289     {
290       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
291         {
292           int i;
293           mpd_Song *song = entry->entity->info.song;
294           
295           i = mpc_playlist_get_song_index(c, song->file);
296           if( i>=0 )
297             {
298               mpd_sendDeleteCommand(c->connection, i);
299               mpd_finishCommand(c->connection);
300               screen_status_printf("Removed \'%s\' from playlist\n", 
301                                    mpc_get_song_name(song));
303             }
304         }
305     }
306   return 0;
309 void
310 file_clear_highlights(mpd_client_t *c)
312   GList *list = g_list_first(c->filelist);
313   
314   while( list )
315     {
316       filelist_entry_t *entry = list->data;
318       entry->selected = 0;
319       list = list->next;
320     }
323 void
324 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
326   GList *list = g_list_first(c->filelist);
328   if( !song )
329     return;
331   while( list )
332     {
333       filelist_entry_t *entry = list->data;
334       mpd_InfoEntity *entity  = entry->entity;
336       if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
337         {
338           mpd_Song *song2 = entity->info.song;
340           if( strcmp(song->file, song2->file) == 0 )
341             {
342               entry->selected = 0;
343             }
344         }
345       list = list->next;
346     }
349 char *
350 file_get_header(mpd_client_t *c)
352   static char buf[BUFSIZE];
353   char *tmp;
355   tmp = utf8_to_locale(basename(c->cwd));
356   snprintf(buf, BUFSIZE, 
357            TOP_HEADER_FILE ": %s                          ",
358            tmp
359            );
360   g_free(tmp);
362   return buf;
365 void 
366 file_open(screen_t *screen, mpd_client_t *c)
368   if( c->filelist == NULL )
369     {
370       mpc_update_filelist(c);
371     }
374 void 
375 file_close(screen_t *screen, mpd_client_t *c)
379 void 
380 file_paint(screen_t *screen, mpd_client_t *c)
382   list_window_t *w = screen->filelist;
383  
384   w->clear = 1;
385   
386   list_window_paint(screen->filelist, list_callback, (void *) c);
387   wnoutrefresh(screen->filelist->w);
390 void 
391 file_update(screen_t *screen, mpd_client_t *c)
393   if( c->filelist_updated )
394     {
395       file_paint(screen, c);
396       c->filelist_updated = 0;
397       return;
398     }
399   list_window_paint(screen->filelist, list_callback, (void *) c);
400   wnoutrefresh(screen->filelist->w);
404 int 
405 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
407   switch(cmd)
408     {
409     case CMD_PLAY:
410       handle_play_cmd(screen, c);
411       return 1;
412     case CMD_SELECT:
413       if( handle_select(screen, c) == 0 )
414         {
415           /* continue and select next item... */
416           cmd = CMD_LIST_NEXT;
417         }
418       break;
419     case CMD_DELETE:
420       handle_delete(screen, c);
421       break;
422     case CMD_SCREEN_UPDATE:
423       mpc_update_filelist(c);
424       list_window_check_selected(screen->filelist, c->filelist_length);
425       screen_status_printf("Screen updated!");
426       return 1;
427     case CMD_LIST_FIND:
428     case CMD_LIST_RFIND:
429     case CMD_LIST_FIND_NEXT:
430     case CMD_LIST_RFIND_NEXT:
431       return screen_find(screen, c, 
432                          screen->filelist, c->filelist_length,
433                          cmd, list_callback);
434     default:
435       break;
436     }
437   return list_window_cmd(screen->filelist, c->filelist_length, cmd);