1 /*
2 * $Id: screen_file.c,v 1.9 2004/03/18 09:33:07 kalle Exp $
3 *
4 */
6 #include <stdlib.h>
7 #include <string.h>
8 #include <glib.h>
9 #include <ncurses.h>
11 #include "config.h"
12 #include "support.h"
13 #include "libmpdclient.h"
14 #include "mpc.h"
15 #include "command.h"
16 #include "screen.h"
17 #include "screen_file.h"
19 #define BUFSIZE 1024
21 static char *
22 list_callback(int index, int *highlight, void *data)
23 {
24 static char buf[BUFSIZE];
25 mpd_client_t *c = (mpd_client_t *) data;
26 filelist_entry_t *entry;
27 mpd_InfoEntity *entity;
29 *highlight = 0;
30 if( (entry=(filelist_entry_t *) g_list_nth_data(c->filelist, index))==NULL )
31 return NULL;
33 entity = entry->entity;
34 *highlight = entry->selected;
36 if( entity == NULL )
37 {
38 return "[Back]";
39 }
40 if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
41 {
42 mpd_Directory *dir = entity->info.directory;
43 char *dirname = utf8_to_locale(basename(dir->path));
45 strncpy(buf, dirname, BUFSIZE);
46 free(dirname);
47 return buf;
48 }
49 else if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
50 {
51 mpd_Song *song = entity->info.song;
52 return mpc_get_song_name(song);
53 }
55 return NULL;
56 }
58 static void
59 change_directory(screen_t *screen, mpd_client_t *c)
60 {
61 list_window_t *w = screen->filelist;
62 filelist_entry_t *entry;
63 mpd_InfoEntity *entity;
65 entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
66 if( entry==NULL )
67 return;
69 entity = entry->entity;
70 if( entity==NULL )
71 {
72 char *parent = g_path_get_dirname(c->cwd);
74 if( strcmp(parent,".") == 0 )
75 {
76 parent[0] = '\0';
77 }
78 if( c->cwd )
79 free(c->cwd);
80 c->cwd = parent;
81 }
82 else
83 if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
84 {
85 mpd_Directory *dir = entity->info.directory;
86 if( c->cwd )
87 free(c->cwd);
88 c->cwd = strdup(dir->path);
89 }
90 else
91 return;
93 mpc_update_filelist(c);
94 list_window_reset(w);
95 }
98 static int
99 add_directory(mpd_client_t *c, char *dir)
100 {
101 mpd_InfoEntity *entity;
102 GList *subdir_list = NULL;
103 GList *list = NULL;
104 char *dirname;
106 dirname = utf8_to_locale(dir);
107 screen_status_printf("Adding directory %s...\n", dirname);
108 free(dirname);
109 dirname = NULL;
111 mpd_sendLsInfoCommand(c->connection, dir);
112 mpd_sendCommandListBegin(c->connection);
113 while( (entity=mpd_getNextInfoEntity(c->connection)) )
114 {
115 if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
116 {
117 mpd_Song *song = entity->info.song;
118 mpd_sendAddCommand(c->connection, song->file);
119 mpd_freeInfoEntity(entity);
120 }
121 else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
122 {
123 subdir_list = g_list_append(subdir_list, (gpointer) entity);
124 }
125 else
126 mpd_freeInfoEntity(entity);
127 }
128 mpd_sendCommandListEnd(c->connection);
129 mpd_finishCommand(c->connection);
131 list = g_list_first(subdir_list);
132 while( list!=NULL )
133 {
134 mpd_Directory *dir;
136 entity = list->data;
137 dir = entity->info.directory;
138 add_directory(c, dir->path);
139 mpd_freeInfoEntity(entity);
140 list->data=NULL;
141 list=list->next;
142 }
143 g_list_free(subdir_list);
144 return 0;
145 }
147 static void
148 select_entry(screen_t *screen, mpd_client_t *c)
149 {
150 list_window_t *w = screen->filelist;
151 filelist_entry_t *entry;
153 entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
154 if( entry==NULL || entry->entity==NULL)
155 return;
157 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
158 {
159 mpd_Directory *dir = entry->entity->info.directory;
160 add_directory(c, dir->path);
161 return;
162 }
164 if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
165 return; /* No support for adding dirs... :( */
167 entry->selected = !entry->selected;
169 if( entry->selected )
170 {
171 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
172 {
173 mpd_Song *song = entry->entity->info.song;
175 mpd_sendAddCommand(c->connection, song->file);
176 mpd_finishCommand(c->connection);
178 screen_status_printf("Adding \'%s\' to playlist\n",
179 mpc_get_song_name(song));
180 }
181 }
182 else
183 {
184 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
185 {
186 int i;
187 mpd_Song *song = entry->entity->info.song;
189 i = mpc_playlist_get_song_index(c, song->file);
190 if( i>=0 )
191 {
192 mpd_sendDeleteCommand(c->connection, i);
193 mpd_finishCommand(c->connection);
194 screen_status_printf("Removed \'%s\' from playlist\n",
195 mpc_get_song_name(song));
197 }
198 }
199 }
201 }
203 void
204 file_clear_highlights(mpd_client_t *c)
205 {
206 GList *list = g_list_first(c->filelist);
208 while( list )
209 {
210 filelist_entry_t *entry = list->data;
212 entry->selected = 0;
213 list = list->next;
214 }
215 }
217 void
218 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
219 {
220 GList *list = g_list_first(c->filelist);
222 if( !song )
223 return;
225 while( list )
226 {
227 filelist_entry_t *entry = list->data;
228 mpd_InfoEntity *entity = entry->entity;
230 if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
231 {
232 mpd_Song *song2 = entity->info.song;
234 if( strcmp(song->file, song2->file) == 0 )
235 {
236 entry->selected = 0;
237 }
238 }
239 list = list->next;
240 }
241 }
243 char *
244 file_get_header(mpd_client_t *c)
245 {
246 static char buf[64];
247 char *tmp;
249 tmp = utf8_to_locale(basename(c->cwd));
250 snprintf(buf, 64,
251 TOP_HEADER_FILE ": %s ",
252 tmp
253 );
254 free(tmp);
256 return buf;
257 }
259 void
260 file_open(screen_t *screen, mpd_client_t *c)
261 {
262 if( c->filelist == NULL )
263 {
264 mpc_update_filelist(c);
265 }
266 }
268 void
269 file_close(screen_t *screen, mpd_client_t *c)
270 {
271 }
273 void
274 file_paint(screen_t *screen, mpd_client_t *c)
275 {
276 list_window_t *w = screen->filelist;
278 w->clear = 1;
280 list_window_paint(screen->filelist, list_callback, (void *) c);
281 wrefresh(screen->filelist->w);
282 }
284 void
285 file_update(screen_t *screen, mpd_client_t *c)
286 {
287 if( c->filelist_updated )
288 {
289 file_paint(screen, c);
290 c->filelist_updated = 0;
291 return;
292 }
293 list_window_paint(screen->filelist, list_callback, (void *) c);
294 wrefresh(screen->filelist->w);
295 }
298 int
299 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
300 {
301 switch(cmd)
302 {
303 case CMD_PLAY:
304 change_directory(screen, c);
305 break;
306 case CMD_LIST_PREVIOUS:
307 list_window_previous(screen->filelist);
308 screen->filelist->repaint=1;
309 break;
310 case CMD_SELECT:
311 select_entry(screen, c);
312 /* continue and select next item... */
313 case CMD_LIST_NEXT:
314 list_window_next(screen->filelist, c->filelist_length);
315 screen->filelist->repaint=1;
316 break;
317 case CMD_LIST_FIRST:
318 list_window_first(screen->filelist);
319 screen->filelist->repaint = 1;
320 break;
321 case CMD_LIST_LAST:
322 list_window_last(screen->filelist, c->filelist_length);
323 screen->filelist->repaint = 1;
324 break;
325 case CMD_LIST_NEXT_PAGE:
326 list_window_next_page(screen->filelist, c->filelist_length);
327 screen->filelist->repaint = 1;
328 break;
329 case CMD_LIST_PREVIOUS_PAGE:
330 list_window_previous_page(screen->filelist);
331 screen->filelist->repaint = 1;
332 break;
333 case CMD_LIST_FIND:
334 if( screen->findbuf )
335 {
336 free(screen->findbuf);
337 screen->findbuf=NULL;
338 }
339 /* fall throw... */
340 case CMD_LIST_FIND_NEXT:
341 if( !screen->findbuf )
342 screen->findbuf=screen_readln(screen->status_window.w, "/");
343 if( list_window_find(screen->filelist,
344 list_callback,
345 c,
346 screen->findbuf) == 0 )
347 {
348 screen->filelist->repaint = 1;
349 }
350 else
351 {
352 screen_status_printf("Unable to find \'%s\'", screen->findbuf);
353 beep();
354 }
355 break;
356 default:
357 return 0;
358 }
359 return 1;
360 }