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;
113 mpc_update_filelist(c);
114 list_window_reset(w);
115 return 0;
116 }
118 static int
119 load_playlist(screen_t *screen, mpd_client_t *c, filelist_entry_t *entry)
120 {
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;
131 }
133 static int
134 handle_delete(screen_t *screen, mpd_client_t *c)
135 {
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;
181 }
184 static int
185 handle_play_cmd(screen_t *screen, mpd_client_t *c)
186 {
187 list_window_t *w = screen->filelist;
188 filelist_entry_t *entry;
189 mpd_InfoEntity *entity;
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;
201 }
203 static int
204 add_directory(mpd_client_t *c, char *dir)
205 {
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);
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;
250 }
252 static int
253 handle_select(screen_t *screen, mpd_client_t *c)
254 {
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;
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;
306 }
308 void
309 file_clear_highlights(mpd_client_t *c)
310 {
311 GList *list = g_list_first(c->filelist);
313 while( list )
314 {
315 filelist_entry_t *entry = list->data;
317 entry->selected = 0;
318 list = list->next;
319 }
320 }
322 void
323 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
324 {
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 }
346 }
348 char *
349 file_get_header(mpd_client_t *c)
350 {
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;
362 }
364 void
365 file_open(screen_t *screen, mpd_client_t *c)
366 {
367 if( c->filelist == NULL )
368 {
369 mpc_update_filelist(c);
370 }
371 }
373 void
374 file_close(screen_t *screen, mpd_client_t *c)
375 {
376 }
378 void
379 file_paint(screen_t *screen, mpd_client_t *c)
380 {
381 list_window_t *w = screen->filelist;
383 w->clear = 1;
385 list_window_paint(screen->filelist, list_callback, (void *) c);
386 wnoutrefresh(screen->filelist->w);
387 }
389 void
390 file_update(screen_t *screen, mpd_client_t *c)
391 {
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);
400 }
403 int
404 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
405 {
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);
437 }