Code

809ae3faf81f16f67319d0a6f243c66052180d26
[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     }
51   return NULL;
52 }
54 static void
55 change_directory(screen_t *screen, mpd_client_t *c)
56 {
57   list_window_t *w = screen->filelist;
58   filelist_entry_t *entry;
59   mpd_InfoEntity *entity;
61   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
62   if( entry==NULL )
63     return;
65   entity = entry->entity;
66   if( entity==NULL )
67     {
68       char *parent = g_path_get_dirname(c->cwd);
70       if( strcmp(parent,".") == 0 )
71         {
72           parent[0] = '\0';
73         }
74       if( c->cwd )
75         free(c->cwd);
76       c->cwd = parent;
77     }
78   else
79     if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
80       {
81         mpd_Directory *dir = entity->info.directory;
82         if( c->cwd )
83           free(c->cwd);
84         c->cwd = strdup(dir->path);      
85       }
86     else
87       return;
88   
89   mpc_update_filelist(c);
90   list_window_reset(w);
91 }
94 static int
95 add_directory(mpd_client_t *c, char *dir)
96 {
97   mpd_InfoEntity *entity;
98   GList *subdir_list = NULL;
99   GList *list = NULL;
100   char *dirname;
102   dirname = utf8_to_locale(dir);
103   screen_status_printf("Adding directory %s...\n", dirname);
104   free(dirname);
105   dirname = NULL;
107   mpd_sendLsInfoCommand(c->connection, dir);
108   mpd_sendCommandListBegin(c->connection);
109   while( (entity=mpd_getNextInfoEntity(c->connection)) )
110     {
111       if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
112         {
113           mpd_Song *song = entity->info.song;
114           mpd_sendAddCommand(c->connection, song->file);
115           mpd_freeInfoEntity(entity);
116         }
117       else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
118         {
119           subdir_list = g_list_append(subdir_list, (gpointer) entity); 
120         }
121       else
122         mpd_freeInfoEntity(entity);
123     }
124   mpd_sendCommandListEnd(c->connection);
125   mpd_finishCommand(c->connection);
126   
127   list = g_list_first(subdir_list);
128   while( list!=NULL )
129     {
130       mpd_Directory *dir;
132       entity = list->data;
133       dir = entity->info.directory;
134       add_directory(c, dir->path);
135       mpd_freeInfoEntity(entity);
136       list->data=NULL;
137       list=list->next;
138     }
139   g_list_free(subdir_list);
140   return 0;
143 static void
144 select_entry(screen_t *screen, mpd_client_t *c)
146   list_window_t *w = screen->filelist;
147   filelist_entry_t *entry;
149   entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
150   if( entry==NULL || entry->entity==NULL)
151     return;
153   if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
154     {
155       mpd_Directory *dir = entry->entity->info.directory;
156       add_directory(c, dir->path);
157       return;
158     }
160   if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
161     return; /* No support for adding dirs... :( */
163   entry->selected = !entry->selected;
165   if( entry->selected )
166     {
167       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
168         {
169           mpd_Song *song = entry->entity->info.song;
171           mpd_sendAddCommand(c->connection, song->file);
172           mpd_finishCommand(c->connection);
174           screen_status_printf("Adding \'%s\' to playlist\n", 
175                                mpc_get_song_name(song));
176         }
177     }
178   else
179     {
180       if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
181         {
182           int i;
183           mpd_Song *song = entry->entity->info.song;
184           
185           i = mpc_playlist_get_song_index(c, song->file);
186           if( i>=0 )
187             {
188               mpd_sendDeleteCommand(c->connection, i);
189               mpd_finishCommand(c->connection);
190               screen_status_printf("Removed \'%s\' from playlist\n", 
191                                    mpc_get_song_name(song));
193             }
194         }
195     }
196   
199 void
200 file_clear_highlights(mpd_client_t *c)
202   GList *list = g_list_first(c->filelist);
203   
204   while( list )
205     {
206       filelist_entry_t *entry = list->data;
208       entry->selected = 0;
209       list = list->next;
210     }
213 void
214 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
216   GList *list = g_list_first(c->filelist);
218   if( !song )
219     return;
221   while( list )
222     {
223       filelist_entry_t *entry = list->data;
224       mpd_InfoEntity *entity  = entry->entity;
226       if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
227         {
228           mpd_Song *song2 = entity->info.song;
230           if( strcmp(song->file, song2->file) == 0 )
231             {
232               entry->selected = 0;
233             }
234         }
235       list = list->next;
236     }
239 char *
240 file_get_header(mpd_client_t *c)
242   static char buf[64];
243   char *tmp;
245   tmp = utf8_to_locale(basename(c->cwd));
246   snprintf(buf, 64, 
247            TOP_HEADER_FILE ": %s                          ",
248            tmp
249            );
250   free(tmp);
252   return buf;
255 void 
256 file_open(screen_t *screen, mpd_client_t *c)
258   if( c->filelist == NULL )
259     {
260       mpc_update_filelist(c);
261     }
264 void 
265 file_close(screen_t *screen, mpd_client_t *c)
269 void 
270 file_paint(screen_t *screen, mpd_client_t *c)
272   list_window_t *w = screen->filelist;
273  
274   w->clear = 1;
275   
276   list_window_paint(screen->filelist, list_callback, (void *) c);
277   wrefresh(screen->filelist->w);
280 void 
281 file_update(screen_t *screen, mpd_client_t *c)
283   if( c->filelist_updated )
284     {
285       file_paint(screen, c);
286       c->filelist_updated = 0;
287       return;
288     }
289   list_window_paint(screen->filelist, list_callback, (void *) c);
290   wrefresh(screen->filelist->w);
294 int 
295 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
297   switch(cmd)
298     {
299     case CMD_PLAY:
300       change_directory(screen, c);
301       return 1;
302     case CMD_SELECT:
303       select_entry(screen, c);
304       /* continue and select next item... */
305       cmd = CMD_LIST_NEXT;
306       break;
307     case CMD_LIST_FIND:
308       if( screen->findbuf )
309         {
310           free(screen->findbuf);
311           screen->findbuf=NULL;
312         }
313       /* continue... */
314     case CMD_LIST_FIND_NEXT:
315       if( !screen->findbuf )
316         screen->findbuf=screen_readln(screen->status_window.w, "/");
317       if( list_window_find(screen->filelist,
318                            list_callback,
319                            c,
320                            screen->findbuf) == 0 )
321         {
322           screen->filelist->repaint  = 1;
323         }
324       else
325         {
326           screen_status_printf("Unable to find \'%s\'", screen->findbuf);
327           beep();
328         }
329       return 1;
330     default:
331       break;
332     }
333   return list_window_cmd(screen->filelist, c->filelist_length, cmd);