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 }
50 else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
51 {
52 mpd_PlaylistFile *plf = entity->info.playlistFile;
53 char *filename = utf8_to_locale(basename(plf->path));
55 snprintf(buf, BUFSIZE, "%s*", filename);
56 free(filename);
57 return buf;
58 }
59 return "Error: Unknow entry!";
60 }
62 static void
63 change_directory(screen_t *screen, mpd_client_t *c)
64 {
65 list_window_t *w = screen->filelist;
66 filelist_entry_t *entry;
67 mpd_InfoEntity *entity;
69 entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
70 if( entry==NULL )
71 return;
73 entity = entry->entity;
74 if( entity==NULL )
75 {
76 char *parent = g_path_get_dirname(c->cwd);
78 if( strcmp(parent,".") == 0 )
79 {
80 parent[0] = '\0';
81 }
82 if( c->cwd )
83 free(c->cwd);
84 c->cwd = parent;
85 }
86 else
87 if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
88 {
89 mpd_Directory *dir = entity->info.directory;
90 if( c->cwd )
91 free(c->cwd);
92 c->cwd = strdup(dir->path);
93 }
94 else
95 return;
97 mpc_update_filelist(c);
98 list_window_reset(w);
99 }
102 static int
103 add_directory(mpd_client_t *c, char *dir)
104 {
105 mpd_InfoEntity *entity;
106 GList *subdir_list = NULL;
107 GList *list = NULL;
108 char *dirname;
110 dirname = utf8_to_locale(dir);
111 screen_status_printf("Adding directory %s...\n", dirname);
112 free(dirname);
113 dirname = NULL;
115 mpd_sendLsInfoCommand(c->connection, dir);
116 mpd_sendCommandListBegin(c->connection);
117 while( (entity=mpd_getNextInfoEntity(c->connection)) )
118 {
119 if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
120 {
121 mpd_Song *song = entity->info.song;
122 mpd_sendAddCommand(c->connection, song->file);
123 mpd_freeInfoEntity(entity);
124 }
125 else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
126 {
127 subdir_list = g_list_append(subdir_list, (gpointer) entity);
128 }
129 else
130 mpd_freeInfoEntity(entity);
131 }
132 mpd_sendCommandListEnd(c->connection);
133 mpd_finishCommand(c->connection);
135 list = g_list_first(subdir_list);
136 while( list!=NULL )
137 {
138 mpd_Directory *dir;
140 entity = list->data;
141 dir = entity->info.directory;
142 add_directory(c, dir->path);
143 mpd_freeInfoEntity(entity);
144 list->data=NULL;
145 list=list->next;
146 }
147 g_list_free(subdir_list);
148 return 0;
149 }
151 static void
152 select_entry(screen_t *screen, mpd_client_t *c)
153 {
154 list_window_t *w = screen->filelist;
155 filelist_entry_t *entry;
157 entry = ( filelist_entry_t *) g_list_nth_data(c->filelist, w->selected);
158 if( entry==NULL || entry->entity==NULL)
159 return;
161 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
162 {
163 mpd_Directory *dir = entry->entity->info.directory;
164 add_directory(c, dir->path);
165 return;
166 }
168 if( entry->entity->type!=MPD_INFO_ENTITY_TYPE_SONG )
169 return; /* No support for adding dirs... :( */
171 entry->selected = !entry->selected;
173 if( entry->selected )
174 {
175 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
176 {
177 mpd_Song *song = entry->entity->info.song;
179 mpd_sendAddCommand(c->connection, song->file);
180 mpd_finishCommand(c->connection);
182 screen_status_printf("Adding \'%s\' to playlist\n",
183 mpc_get_song_name(song));
184 }
185 }
186 else
187 {
188 if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG )
189 {
190 int i;
191 mpd_Song *song = entry->entity->info.song;
193 i = mpc_playlist_get_song_index(c, song->file);
194 if( i>=0 )
195 {
196 mpd_sendDeleteCommand(c->connection, i);
197 mpd_finishCommand(c->connection);
198 screen_status_printf("Removed \'%s\' from playlist\n",
199 mpc_get_song_name(song));
201 }
202 }
203 }
205 }
207 void
208 file_clear_highlights(mpd_client_t *c)
209 {
210 GList *list = g_list_first(c->filelist);
212 while( list )
213 {
214 filelist_entry_t *entry = list->data;
216 entry->selected = 0;
217 list = list->next;
218 }
219 }
221 void
222 file_clear_highlight(mpd_client_t *c, mpd_Song *song)
223 {
224 GList *list = g_list_first(c->filelist);
226 if( !song )
227 return;
229 while( list )
230 {
231 filelist_entry_t *entry = list->data;
232 mpd_InfoEntity *entity = entry->entity;
234 if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG )
235 {
236 mpd_Song *song2 = entity->info.song;
238 if( strcmp(song->file, song2->file) == 0 )
239 {
240 entry->selected = 0;
241 }
242 }
243 list = list->next;
244 }
245 }
247 char *
248 file_get_header(mpd_client_t *c)
249 {
250 static char buf[64];
251 char *tmp;
253 tmp = utf8_to_locale(basename(c->cwd));
254 snprintf(buf, 64,
255 TOP_HEADER_FILE ": %s ",
256 tmp
257 );
258 free(tmp);
260 return buf;
261 }
263 void
264 file_open(screen_t *screen, mpd_client_t *c)
265 {
266 if( c->filelist == NULL )
267 {
268 mpc_update_filelist(c);
269 }
270 }
272 void
273 file_close(screen_t *screen, mpd_client_t *c)
274 {
275 }
277 void
278 file_paint(screen_t *screen, mpd_client_t *c)
279 {
280 list_window_t *w = screen->filelist;
282 w->clear = 1;
284 list_window_paint(screen->filelist, list_callback, (void *) c);
285 wrefresh(screen->filelist->w);
286 }
288 void
289 file_update(screen_t *screen, mpd_client_t *c)
290 {
291 if( c->filelist_updated )
292 {
293 file_paint(screen, c);
294 c->filelist_updated = 0;
295 return;
296 }
297 list_window_paint(screen->filelist, list_callback, (void *) c);
298 wrefresh(screen->filelist->w);
299 }
302 int
303 file_cmd(screen_t *screen, mpd_client_t *c, command_t cmd)
304 {
305 switch(cmd)
306 {
307 case CMD_PLAY:
308 change_directory(screen, c);
309 return 1;
310 case CMD_SELECT:
311 select_entry(screen, c);
312 /* continue and select next item... */
313 cmd = CMD_LIST_NEXT;
314 break;
315 case CMD_LIST_FIND:
316 if( screen->findbuf )
317 {
318 free(screen->findbuf);
319 screen->findbuf=NULL;
320 }
321 /* continue... */
322 case CMD_LIST_FIND_NEXT:
323 if( !screen->findbuf )
324 screen->findbuf=screen_readln(screen->status_window.w, "/");
325 if( list_window_find(screen->filelist,
326 list_callback,
327 c,
328 screen->findbuf) == 0 )
329 {
330 screen->filelist->repaint = 1;
331 }
332 else
333 {
334 screen_status_printf("Unable to find \'%s\'", screen->findbuf);
335 beep();
336 }
337 return 1;
338 default:
339 break;
340 }
341 return list_window_cmd(screen->filelist, c->filelist_length, cmd);
342 }