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 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);
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;
251 }
253 static int
254 handle_select(screen_t *screen, mpd_client_t *c)
255 {
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;
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;
307 }
309 void
310 file_clear_highlights(mpd_client_t *c)
311 {
312 GList *list = g_list_first(c->filelist);
314 while( list )
315 {
316 filelist_entry_t *entry = list->data;
318 entry->selected = 0;
319 list = list->next;
320 }
321 }
323 void
324 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
325 {
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 }
347 }
349 char *
350 file_get_header(mpd_client_t *c)
351 {
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;
363 }
365 void
366 file_open(screen_t *screen, mpd_client_t *c)
367 {
368 if( c->filelist == NULL )
369 {
370 mpc_update_filelist(c);
371 }
372 }
374 void
375 file_close(screen_t *screen, mpd_client_t *c)
376 {
377 }
379 void
380 file_paint(screen_t *screen, mpd_client_t *c)
381 {
382 list_window_t *w = screen->filelist;
384 w->clear = 1;
386 list_window_paint(screen->filelist, list_callback, (void *) c);
387 wnoutrefresh(screen->filelist->w);
388 }
390 void
391 file_update(screen_t *screen, mpd_client_t *c)
392 {
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);
401 }
404 int
405 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
406 {
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);
438 }