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 buf[80];
106 snprintf(buf, 80, "Adding directory %s...\n", dir);
107 screen_status_message(c, buf);
109 mpd_sendLsInfoCommand(c->connection, dir);
110 mpd_sendCommandListBegin(c->connection);
111 while( (entity=mpd_getNextInfoEntity(c->connection)) )
112 {
113 if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
114 {
115 mpd_Song *song = entity->info.song;
116 mpd_sendAddCommand(c->connection, song->file);
117 mpd_freeInfoEntity(entity);
118 }
119 else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
120 {
121 subdir_list = g_list_append(subdir_list, (gpointer) entity);
122 }
123 else
124 mpd_freeInfoEntity(entity);
125 }
126 mpd_sendCommandListEnd(c->connection);
127 mpd_finishCommand(c->connection);
129 list = g_list_first(subdir_list);
130 while( list!=NULL )
131 {
132 mpd_Directory *dir;
134 entity = list->data;
135 dir = entity->info.directory;
136 add_directory(c, dir->path);
137 mpd_freeInfoEntity(entity);
138 list->data=NULL;
139 list=list->next;
140 }
141 g_list_free(subdir_list);
142 return 0;
143 }
145 static void
146 select_entry(screen_t *screen, mpd_client_t *c)
147 {
148 list_window_t *w = screen->filelist;
149 filelist_entry_t *entry;
151 entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
152 if( entry==NULL || entry->entity==NULL)
153 return;
155 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
156 {
157 mpd_Directory *dir = entry->entity->info.directory;
158 add_directory(c, dir->path);
159 return;
160 }
162 if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
163 return; /* No support for adding dirs... :( */
165 entry->selected = !entry->selected;
167 if( entry->selected )
168 {
169 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
170 {
171 char buf[80];
172 mpd_Song *song = entry->entity->info.song;
174 mpd_sendAddCommand(c->connection, song->file);
175 mpd_finishCommand(c->connection);
177 snprintf(buf, 80,
178 "Adding \'%s\' to playlist\n",
179 mpc_get_song_name(song));
180 screen_status_message(c, buf);
181 }
182 }
183 else
184 {
185 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
186 {
187 int i;
188 char buf[80];
189 mpd_Song *song = entry->entity->info.song;
191 i = mpc_playlist_get_song_index(c, song->file);
192 if( i>=0 )
193 {
194 mpd_sendDeleteCommand(c->connection, i);
195 mpd_finishCommand(c->connection);
196 snprintf(buf, 80,
197 "Removed \'%s\' from playlist\n",
198 mpc_get_song_name(song));
199 screen_status_message(c, buf);
200 }
201 }
202 }
204 }
206 void
207 file_clear_highlights(mpd_client_t *c)
208 {
209 GList *list = g_list_first(c->filelist);
211 while( list )
212 {
213 filelist_entry_t *entry = list->data;
215 entry->selected = 0;
216 list = list->next;
217 }
218 }
220 void
221 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
222 {
223 GList *list = g_list_first(c->filelist);
225 if( !song )
226 return;
228 while( list )
229 {
230 filelist_entry_t *entry = list->data;
231 mpd_InfoEntity *entity = entry->entity;
233 if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
234 {
235 mpd_Song *song2 = entity->info.song;
237 if( strcmp(song->file, song2->file) == 0 )
238 {
239 entry->selected = 0;
240 }
241 }
242 list = list->next;
243 }
244 }
246 char *
247 file_get_header(mpd_client_t *c)
248 {
249 static char buf[64];
250 char *tmp;
252 tmp = utf8_to_locale(basename(c->cwd));
253 snprintf(buf, 64,
254 TOP_HEADER_FILE ": %s ",
255 tmp
256 );
257 free(tmp);
259 return buf;
260 }
262 void
263 file_open(screen_t *screen, mpd_client_t *c)
264 {
265 if( c->filelist == NULL )
266 {
267 mpc_update_filelist(c);
268 }
269 }
271 void
272 file_close(screen_t *screen, mpd_client_t *c)
273 {
274 }
276 void
277 file_paint(screen_t *screen, mpd_client_t *c)
278 {
279 list_window_t *w = screen->filelist;
281 w->clear = 1;
283 list_window_paint(screen->filelist, list_callback, (void *) c);
284 wrefresh(screen->filelist->w);
285 }
287 void
288 file_update(screen_t *screen, mpd_client_t *c)
289 {
290 if( c->filelist_updated )
291 {
292 file_paint(screen, c);
293 c->filelist_updated = 0;
294 return;
295 }
296 list_window_paint(screen->filelist, list_callback, (void *) c);
297 wrefresh(screen->filelist->w);
298 }
301 int
302 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
303 {
304 switch(cmd)
305 {
306 case CMD_PLAY:
307 change_directory(screen, c);
308 break;
309 case CMD_LIST_PREVIOUS:
310 list_window_previous(screen->filelist);
311 screen->filelist->repaint=1;
312 break;
313 case CMD_SELECT:
314 select_entry(screen, c);
315 /* continue and select next item... */
316 case CMD_LIST_NEXT:
317 list_window_next(screen->filelist, c->filelist_length);
318 screen->filelist->repaint=1;
319 break;
320 case CMD_LIST_FIRST:
321 list_window_first(screen->filelist);
322 screen->filelist->repaint = 1;
323 break;
324 case CMD_LIST_LAST:
325 list_window_last(screen->filelist, c->filelist_length);
326 screen->filelist->repaint = 1;
327 break;
328 case CMD_LIST_NEXT_PAGE:
329 list_window_next_page(screen->filelist, c->filelist_length);
330 screen->filelist->repaint = 1;
331 break;
332 case CMD_LIST_PREVIOUS_PAGE:
333 list_window_previous_page(screen->filelist);
334 screen->filelist->repaint = 1;
335 break;
336 default:
337 return 0;
338 }
339 return 1;
340 }