Code

screen_browser: moved code to screen_browser.c
[ncmpc.git] / src / screen_browser.c
1 /*
2  * $Id$
3  *
4  * (c) 2004 by Kalle Wallin <kaw@linux.se>
5  * Copyright (C) 2008 Max Kellermann <max@duempel.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
22 #include "screen_browser.h"
23 #include "ncmpc.h"
24 #include "options.h"
25 #include "support.h"
26 #include "strfsong.h"
27 #include "screen_utils.h"
28 #include "gcc.h"
30 #include <string.h>
32 #define USE_OLD_LAYOUT
33 #undef  USE_OLD_ADD
35 #define BUFSIZE 1024
37 #define HIGHLIGHT  (0x01)
39 /* clear the highlight flag for all items in the filelist */
40 void
41 clear_highlights(mpdclient_filelist_t *fl)
42 {
43         GList *list = g_list_first(fl->list);
45         while( list ) {
46                 filelist_entry_t *entry = list->data;
48                 entry->flags &= ~HIGHLIGHT;
49                 list = list->next;
50         }
51 }
53 /* change the highlight flag for a song */
54 void
55 set_highlight(mpdclient_filelist_t *fl, mpd_Song *song, int highlight)
56 {
57         GList *list = g_list_first(fl->list);
59         if( !song )
60                 return;
62         while( list ) {
63                 filelist_entry_t *entry = list->data;
64                 mpd_InfoEntity *entity  = entry->entity;
66                 if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG ) {
67                         mpd_Song *song2 = entity->info.song;
69                         if( strcmp(song->file, song2->file) == 0 ) {
70                                 if(highlight)
71                                         entry->flags |= HIGHLIGHT;
72                                 else
73                                         entry->flags &= ~HIGHLIGHT;
74                         }
75                 }
76                 list = list->next;
77         }
78 }
80 /* sync highlight flags with playlist */
81 void
82 sync_highlights(mpdclient_t *c, mpdclient_filelist_t *fl)
83 {
84         GList *list = g_list_first(fl->list);
86         while(list) {
87                 filelist_entry_t *entry = list->data;
88                 mpd_InfoEntity *entity = entry->entity;
90                 if( entity && entity->type==MPD_INFO_ENTITY_TYPE_SONG ) {
91                         mpd_Song *song = entity->info.song;
93                         if( playlist_get_index_from_file(c, song->file) >= 0 )
94                                 entry->flags |= HIGHLIGHT;
95                         else
96                                 entry->flags &= ~HIGHLIGHT;
97                 }
98                 list=list->next;
99         }
102 /* list_window callback */
103 const char *
104 browser_lw_callback(unsigned idx, int *highlight, void *data)
106         static char buf[BUFSIZE];
107         mpdclient_filelist_t *fl = (mpdclient_filelist_t *) data;
108         filelist_entry_t *entry;
109         mpd_InfoEntity *entity;
111         if( (entry=(filelist_entry_t *)g_list_nth_data(fl->list,idx))==NULL )
112                 return NULL;
114         entity = entry->entity;
115         *highlight = (entry->flags & HIGHLIGHT);
117         if( entity == NULL )
118                 return "[..]";
120         if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY ) {
121                 mpd_Directory *dir = entity->info.directory;
122                 char *directory = utf8_to_locale(basename(dir->path));
124                 g_snprintf(buf, BUFSIZE, "[%s]", directory);
125                 g_free(directory);
126                 return buf;
127         } else if( entity->type==MPD_INFO_ENTITY_TYPE_SONG ) {
128                 mpd_Song *song = entity->info.song;
130                 strfsong(buf, BUFSIZE, LIST_FORMAT, song);
131                 return buf;
132         } else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE ) {
133                 mpd_PlaylistFile *plf = entity->info.playlistFile;
134                 char *filename = utf8_to_locale(basename(plf->path));
136 #ifdef USE_OLD_LAYOUT
137                 g_snprintf(buf, BUFSIZE, "*%s*", filename);
138 #else
139                 g_snprintf(buf, BUFSIZE, "<Playlist> %s", filename);
140 #endif
141                 g_free(filename);
142                 return buf;
143         }
145         return "Error: Unknown entry!";
148 /* chdir */
149 int
150 browser_change_directory(struct screen_browser *browser, mpdclient_t *c,
151                          filelist_entry_t *entry, const char *new_path)
153         mpd_InfoEntity *entity = NULL;
154         gchar *path = NULL;
156         if( entry!=NULL )
157                 entity = entry->entity;
158         else if( new_path==NULL )
159                 return -1;
161         if( entity==NULL ) {
162                 if( entry || 0==strcmp(new_path, "..") ) {
163                         /* return to parent */
164                         char *parent = g_path_get_dirname(browser->filelist->path);
165                         if( strcmp(parent, ".") == 0 )
166                                 parent[0] = '\0';
167                         path = g_strdup(parent);
168                         list_window_reset(browser->lw);
169                         /* restore previous list window state */
170                         list_window_pop_state(browser->lw_state, browser->lw);
171                 } else {
172                         /* entry==NULL, then new_path ("" is root) */
173                         path = g_strdup(new_path);
174                         list_window_reset(browser->lw);
175                         /* restore first list window state (pop while returning true) */
176                         while(list_window_pop_state(browser->lw_state, browser->lw));
177                 }
178         } else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY) {
179                 /* enter sub */
180                 mpd_Directory *dir = entity->info.directory;
181                 path = utf8_to_locale(dir->path);
182                 /* save current list window state */
183                 list_window_push_state(browser->lw_state, browser->lw);
184         } else
185                 return -1;
187         mpdclient_filelist_free(browser->filelist);
188         browser->filelist = mpdclient_filelist_get(c, path);
189         sync_highlights(c, browser->filelist);
190         list_window_check_selected(browser->lw, browser->filelist->length);
191         g_free(path);
192         return 0;
195 static int
196 load_playlist(mpdclient_t *c, filelist_entry_t *entry)
198         mpd_InfoEntity *entity = entry->entity;
199         mpd_PlaylistFile *plf = entity->info.playlistFile;
200         char *filename = utf8_to_locale(plf->path);
202         if (mpdclient_cmd_load_playlist_utf8(c, plf->path) == 0)
203                 screen_status_printf(_("Loading playlist %s..."), basename(filename));
204         g_free(filename);
205         return 0;
208 static int
209 enqueue_and_play(mpdclient_t *c, filelist_entry_t *entry)
211         int idx;
212         mpd_InfoEntity *entity = entry->entity;
213         mpd_Song *song = entity->info.song;
215         if (!(entry->flags & HIGHLIGHT)) {
216                 if (mpdclient_cmd_add(c, song) == 0) {
217                         char buf[BUFSIZE];
219                         entry->flags |= HIGHLIGHT;
220                         strfsong(buf, BUFSIZE, LIST_FORMAT, song);
221                         screen_status_printf(_("Adding \'%s\' to playlist\n"), buf);
222                         mpdclient_update(c); /* get song id */
223                 } else
224                         return -1;
225         }
227         idx = playlist_get_index_from_file(c, song->file);
228         mpdclient_cmd_play(c, idx);
229         return 0;
232 int
233 browser_handle_enter(struct screen_browser *browser, mpdclient_t *c)
235         filelist_entry_t *entry;
236         mpd_InfoEntity *entity;
238         if (browser->filelist == NULL)
239                 return -1;
240         entry = (filelist_entry_t *) g_list_nth_data(browser->filelist->list,
241                                                      browser->lw->selected);
242         if( entry==NULL )
243                 return -1;
245         entity = entry->entity;
246         if (entity == NULL || entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
247                 return browser_change_directory(browser, c, entry, NULL);
248         else if (entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
249                 return load_playlist(c, entry);
250         else if (entity->type == MPD_INFO_ENTITY_TYPE_SONG)
251                 return enqueue_and_play(c, entry);
252         return -1;
256 #ifdef USE_OLD_ADD
257 /* NOTE - The add_directory functions should move to mpdclient.c */
258 extern gint mpdclient_finish_command(mpdclient_t *c);
260 static int
261 add_directory(mpdclient_t *c, char *dir)
263         mpd_InfoEntity *entity;
264         GList *subdir_list = NULL;
265         GList *list = NULL;
266         char *dirname;
268         dirname = utf8_to_locale(dir);
269         screen_status_printf(_("Adding directory %s...\n"), dirname);
270         doupdate();
271         g_free(dirname);
272         dirname = NULL;
274         mpd_sendLsInfoCommand(c->connection, dir);
275         mpd_sendCommandListBegin(c->connection);
276         while( (entity=mpd_getNextInfoEntity(c->connection)) ) {
277                 if( entity->type==MPD_INFO_ENTITY_TYPE_SONG ) {
278                         mpd_Song *song = entity->info.song;
279                         mpd_sendAddCommand(c->connection, song->file);
280                         mpd_freeInfoEntity(entity);
281                 } else if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY ) {
282                         subdir_list = g_list_append(subdir_list, (gpointer) entity);
283                 } else
284                         mpd_freeInfoEntity(entity);
285         }
286         mpd_sendCommandListEnd(c->connection);
287         mpdclient_finish_command(c);
288         c->need_update = TRUE;
290         list = g_list_first(subdir_list);
291         while( list!=NULL ) {
292                 mpd_Directory *dir;
294                 entity = list->data;
295                 dir = entity->info.directory;
296                 add_directory(c, dir->path);
297                 mpd_freeInfoEntity(entity);
298                 list->data=NULL;
299                 list=list->next;
300         }
301         g_list_free(subdir_list);
302         return 0;
304 #endif
306 int
307 browser_handle_select(struct screen_browser *browser, mpdclient_t *c)
309         filelist_entry_t *entry;
311         if (browser->filelist == NULL)
312                 return -1;
313         entry = g_list_nth_data(browser->filelist->list, browser->lw->selected);
314         if (entry == NULL || entry->entity == NULL)
315                 return -1;
317         if (entry->entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
318                 return load_playlist(c, entry);
320         if (entry->entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) {
321                 mpd_Directory *dir = entry->entity->info.directory;
322 #ifdef USE_OLD_ADD
323                 add_directory(c, tmp);
324 #else
325                 if (mpdclient_cmd_add_path_utf8(c, dir->path) == 0) {
326                         char *tmp = utf8_to_locale(dir->path);
328                         screen_status_printf(_("Adding \'%s\' to playlist\n"), tmp);
329                         g_free(tmp);
330                 }
331 #endif
332                 return 0;
333         }
335         if (entry->entity->type != MPD_INFO_ENTITY_TYPE_SONG)
336                 return -1;
338         if (entry->flags & HIGHLIGHT)
339                 entry->flags &= ~HIGHLIGHT;
340         else
341                 entry->flags |= HIGHLIGHT;
343         if (entry->flags & HIGHLIGHT) {
344                 if (entry->entity->type == MPD_INFO_ENTITY_TYPE_SONG) {
345                         mpd_Song *song = entry->entity->info.song;
347                         if (mpdclient_cmd_add(c, song) == 0) {
348                                 char buf[BUFSIZE];
350                                 strfsong(buf, BUFSIZE, LIST_FORMAT, song);
351                                 screen_status_printf(_("Adding \'%s\' to playlist\n"), buf);
352                         }
353                 }
354         } else {
355                 /* remove song from playlist */
356                 if (entry->entity->type == MPD_INFO_ENTITY_TYPE_SONG) {
357                         mpd_Song *song = entry->entity->info.song;
359                         if (song) {
360                                 int idx;
362                                 while ((idx = playlist_get_index_from_file(c, song->file)) >=0)
363                                         mpdclient_cmd_delete(c, idx);
364                         }
365                 }
366         }
368         return 0;
371 int
372 browser_handle_select_all(struct screen_browser *browser, mpdclient_t *c)
374         filelist_entry_t *entry;
375         GList *temp = browser->filelist->list;
377         if (browser->filelist == NULL)
378                 return -1;
380         for (browser->filelist->list = g_list_first(browser->filelist->list);
381              browser->filelist->list;
382              browser->filelist->list = g_list_next(browser->filelist->list)) {
383                 entry = browser->filelist->list->data;
384                 if (entry == NULL || entry->entity == NULL)
385                         return -1;
387                 if (entry->entity->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
388                         load_playlist(c, entry);
390                 if (entry->entity->type == MPD_INFO_ENTITY_TYPE_DIRECTORY) {
391                         mpd_Directory *dir = entry->entity->info.directory;
392 #ifdef USE_OLD_ADD
393                         add_directory(c, tmp);
394 #else
395                         if (mpdclient_cmd_add_path_utf8(c, dir->path) == 0) {
396                                 char *tmp = utf8_to_locale(dir->path);
398                                 screen_status_printf(_("Adding \'%s\' to playlist\n"), tmp);
399                                 g_free(tmp);
400                         }
401 #endif
402                 }
404                 if (entry->entity->type != MPD_INFO_ENTITY_TYPE_SONG)
405                         continue;
407                 entry->flags |= HIGHLIGHT;
409                 if (entry->flags & HIGHLIGHT) {
410                         if (entry->entity->type == MPD_INFO_ENTITY_TYPE_SONG) {
411                                 mpd_Song *song = entry->entity->info.song;
413                                 if (mpdclient_cmd_add(c, song) == 0) {
414                                         char buf[BUFSIZE];
416                                         strfsong(buf, BUFSIZE, LIST_FORMAT, song);
417                                         screen_status_printf(_("Adding \'%s\' to playlist\n"), buf);
418                                 }
419                         }
420                 }
421                 /*
422                 else {
423                         //remove song from playlist
424                         if( entry->entity->type==MPD_INFO_ENTITY_TYPE_SONG ) {
425                                 mpd_Song *song = entry->entity->info.song;
427                                 if( song ) {
428                                         int idx = playlist_get_index_from_file(c, song->file);
430                                         while( (idx=playlist_get_index_from_file(c, song->file))>=0 )
431                                                 mpdclient_cmd_delete(c, idx);
432                                 }
433                         }
434                 }
435                 */
436                 return 0;
437         }
439         browser->filelist->list = temp;
440         return 0;
443 #ifdef HAVE_GETMOUSE
444 int
445 browser_handle_mouse_event(struct screen_browser *browser, mpdclient_t *c)
447         int row;
448         unsigned prev_selected = browser->lw->selected;
449         unsigned long bstate;
450         int length;
452         if (browser->filelist)
453                 length = browser->filelist->length;
454         else
455                 length = 0;
457         if( screen_get_mouse_event(c, browser->lw, length, &bstate, &row) )
458                 return 1;
460         browser->lw->selected = browser->lw->start + row;
461         list_window_check_selected(browser->lw, length);
463         if( bstate & BUTTON1_CLICKED ) {
464                 if (prev_selected == browser->lw->selected)
465                         browser_handle_enter(browser, c);
466         } else if (bstate & BUTTON3_CLICKED) {
467                 if (prev_selected == browser->lw->selected)
468                         browser_handle_select(browser, c);
469         }
471         return 1;
473 #endif