Code

Added strcasestr prototype.
[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   g_free(dirname);
214   dirname = NULL;
216   mpd_sendLsInfoCommand(c->connection, dir);
217   mpd_sendCommandListBegin(c->connection);
218   while( (entity=mpd_getNextInfoEntity(c->connection)) )
219     {
220       if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
221         {
222           mpd_Song *song = entity->info.song;
223           mpd_sendAddCommand(c->connection, song->file);
224           mpd_freeInfoEntity(entity);
225         }
226       else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
227         {
228           subdir_list = g_list_append(subdir_list, (gpointer) entity); 
229         }
230       else
231         mpd_freeInfoEntity(entity);
232     }
233   mpd_sendCommandListEnd(c->connection);
234   mpd_finishCommand(c->connection);
235   
236   list = g_list_first(subdir_list);
237   while( list!=NULL )
238     {
239       mpd_Directory *dir;
241       entity = list->data;
242       dir = entity->info.directory;
243       add_directory(c, dir->path);
244       mpd_freeInfoEntity(entity);
245       list->data=NULL;
246       list=list->next;
247     }
248   g_list_free(subdir_list);
249   return 0;
252 static int
253 handle_select(screen_t *screen, mpd_client_t *c)
255   list_window_t *w = screen->filelist;
256   filelist_entry_t *entry;
258   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
259   if( entry==NULL || entry->entity==NULL)
260     return -1;
262   if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
263     {
264       mpd_Directory *dir = entry->entity->info.directory;
265       add_directory(c, dir->path);
266       return 0;
267     }
269   if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
270     return -1; 
272   entry->selected = !entry->selected;
274   if( entry->selected )
275     {
276       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
277         {
278           mpd_Song *song = entry->entity->info.song;
280           mpd_sendAddCommand(c->connection, song->file);
281           mpd_finishCommand(c->connection);
283           screen_status_printf("Adding \'%s\' to playlist\n", 
284                                mpc_get_song_name(song));
285         }
286     }
287   else
288     {
289       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
290         {
291           int i;
292           mpd_Song *song = entry->entity->info.song;
293           
294           i = mpc_playlist_get_song_index(c, song->file);
295           if( i>=0 )
296             {
297               mpd_sendDeleteCommand(c->connection, i);
298               mpd_finishCommand(c->connection);
299               screen_status_printf("Removed \'%s\' from playlist\n", 
300                                    mpc_get_song_name(song));
302             }
303         }
304     }
305   return 0;
308 void
309 file_clear_highlights(mpd_client_t *c)
311   GList *list = g_list_first(c->filelist);
312   
313   while( list )
314     {
315       filelist_entry_t *entry = list->data;
317       entry->selected = 0;
318       list = list->next;
319     }
322 void
323 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
325   GList *list = g_list_first(c->filelist);
327   if( !song )
328     return;
330   while( list )
331     {
332       filelist_entry_t *entry = list->data;
333       mpd_InfoEntity *entity  = entry->entity;
335       if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
336         {
337           mpd_Song *song2 = entity->info.song;
339           if( strcmp(song->file, song2->file) == 0 )
340             {
341               entry->selected = 0;
342             }
343         }
344       list = list->next;
345     }
348 char *
349 file_get_header(mpd_client_t *c)
351   static char buf[BUFSIZE];
352   char *tmp;
354   tmp = utf8_to_locale(basename(c->cwd));
355   snprintf(buf, BUFSIZE, 
356            TOP_HEADER_FILE ": %s                          ",
357            tmp
358            );
359   g_free(tmp);
361   return buf;
364 void 
365 file_open(screen_t *screen, mpd_client_t *c)
367   if( c->filelist == NULL )
368     {
369       mpc_update_filelist(c);
370     }
373 void 
374 file_close(screen_t *screen, mpd_client_t *c)
378 void 
379 file_paint(screen_t *screen, mpd_client_t *c)
381   list_window_t *w = screen->filelist;
382  
383   w->clear = 1;
384   
385   list_window_paint(screen->filelist, list_callback, (void *) c);
386   wnoutrefresh(screen->filelist->w);
389 void 
390 file_update(screen_t *screen, mpd_client_t *c)
392   if( c->filelist_updated )
393     {
394       file_paint(screen, c);
395       c->filelist_updated = 0;
396       return;
397     }
398   list_window_paint(screen->filelist, list_callback, (void *) c);
399   wnoutrefresh(screen->filelist->w);
403 int 
404 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
406   switch(cmd)
407     {
408     case CMD_PLAY:
409       handle_play_cmd(screen, c);
410       return 1;
411     case CMD_SELECT:
412       if( handle_select(screen, c) == 0 )
413         {
414           /* continue and select next item... */
415           cmd = CMD_LIST_NEXT;
416         }
417       break;
418     case CMD_DELETE:
419       handle_delete(screen, c);
420       break;
421     case CMD_SCREEN_UPDATE:
422       mpc_update_filelist(c);
423       list_window_check_selected(screen->filelist, c->filelist_length);
424       screen_status_printf("Screen updated!");
425       return 1;
426     case CMD_LIST_FIND:
427     case CMD_LIST_RFIND:
428     case CMD_LIST_FIND_NEXT:
429     case CMD_LIST_RFIND_NEXT:
430       return screen_find(screen, c, 
431                          screen->filelist, c->filelist_length,
432                          cmd, list_callback);
433     default:
434       break;
435     }
436   return list_window_cmd(screen->filelist, c->filelist_length, cmd);