Code

mpdclient: removed several functions
[ncmpc.git] / src / screen_file.c
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2009 The Music Player Daemon Project
3  * Project homepage: http://musicpd.org
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
20 #include "screen_file.h"
21 #include "screen_browser.h"
22 #include "screen_interface.h"
23 #include "screen_message.h"
24 #include "screen.h"
25 #include "config.h"
26 #include "i18n.h"
27 #include "charset.h"
28 #include "mpdclient.h"
29 #include "filelist.h"
30 #include "screen_utils.h"
31 #include "screen_play.h"
32 #include "screen_client.h"
34 #include <mpd/client.h>
36 #include <ctype.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <glib.h>
41 static struct screen_browser browser;
42 static char *current_path;
44 static void
45 screen_file_paint(void);
47 static void
48 screen_file_repaint(void)
49 {
50         screen_file_paint();
51         wrefresh(browser.lw->w);
52 }
54 static void
55 screen_file_reload(struct mpdclient *c)
56 {
57         if (browser.filelist != NULL)
58                 filelist_free(browser.filelist);
60         browser.filelist = mpdclient_filelist_get(c, current_path);
61         if (browser.filelist == NULL)
62                 browser.filelist = filelist_new();
64         if (*current_path != 0)
65                 /* add a dummy entry for ./.. */
66                 filelist_prepend(browser.filelist, NULL);
67 }
69 /**
70  * Change to the specified absolute directory.
71  */
72 static bool
73 change_directory(struct mpdclient *c, const char *new_path)
74 {
75         g_free(current_path);
76         current_path = g_strdup(new_path);
78         screen_file_reload(c);
80 #ifndef NCMPC_MINI
81         screen_browser_sync_highlights(browser.filelist, &c->playlist);
82 #endif
84         list_window_reset(browser.lw);
86         return browser.filelist != NULL;
87 }
89 /**
90  * Change to the parent directory of the current directory.
91  */
92 static bool
93 change_to_parent(struct mpdclient *c)
94 {
95         char *parent = g_path_get_dirname(current_path);
96         char *old_path;
97         int idx;
98         bool success;
100         if (strcmp(parent, ".") == 0)
101                 parent[0] = '\0';
103         old_path = current_path;
104         current_path = NULL;
106         success = change_directory(c, parent);
107         g_free(parent);
109         idx = success
110                 ? filelist_find_directory(browser.filelist, old_path)
111                 : -1;
112         g_free(old_path);
114         if (success && idx >= 0) {
115                 /* set the cursor on the previous working directory */
116                 list_window_set_selected(browser.lw, idx);
117                 list_window_center(browser.lw,
118                                    filelist_length(browser.filelist), idx);
119         }
121         return success;
124 /**
125  * Change to the directory referred by the specified #filelist_entry
126  * object.
127  */
128 static bool
129 change_to_entry(struct mpdclient *c, const struct filelist_entry *entry)
131         assert(entry != NULL);
133         if (entry->entity == NULL)
134                 return change_to_parent(c);
135         else if (mpd_entity_get_type(entry->entity) == MPD_ENTITY_TYPE_DIRECTORY)
136                 return change_directory(c, mpd_directory_get_path(mpd_entity_get_directory(entry->entity)));
137         else
138                 return false;
141 static bool
142 screen_file_handle_enter(struct mpdclient *c)
144         const struct filelist_entry *entry = browser_get_selected_entry(&browser);
146         if (entry == NULL)
147                 return false;
149         return change_to_entry(c, entry);
152 static int
153 handle_save(struct mpdclient *c)
155         struct filelist_entry *entry;
156         const char *defaultname = NULL;
157         char *defaultname_utf8 = NULL;
158         int ret;
159         unsigned selected;
161         if (browser.lw->selected >= filelist_length(browser.filelist))
162                 return -1;
164         for(selected = browser.lw->selected_start; selected <= browser.lw->selected_end; ++selected)
165         {
166                 entry = filelist_get(browser.filelist, selected);
167                 if( entry && entry->entity ) {
168                         struct mpd_entity *entity = entry->entity;
169                         if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_PLAYLIST) {
170                                 const struct mpd_playlist *playlist =
171                                         mpd_entity_get_playlist(entity);
172                                 defaultname = mpd_playlist_get_path(playlist);
173                         }
174                 }
175         }
177         if(defaultname)
178                 defaultname_utf8 = utf8_to_locale(defaultname);
179         ret = playlist_save(c, NULL, defaultname_utf8);
180         g_free(defaultname_utf8);
182         return ret;
185 static int
186 handle_delete(struct mpdclient *c)
188         struct filelist_entry *entry;
189         struct mpd_entity *entity;
190         const struct mpd_playlist *playlist;
191         char *str, *buf;
192         int key;
193         unsigned selected;
195         for(selected = browser.lw->selected_start; selected <= browser.lw->selected_end; ++selected)
196         {
197                 if (selected >= filelist_length(browser.filelist))
198                         return -1;
200                 entry = filelist_get(browser.filelist, selected);
201                 if( entry==NULL || entry->entity==NULL )
202                         continue;
204                 entity = entry->entity;
206                 if (mpd_entity_get_type(entity) != MPD_ENTITY_TYPE_PLAYLIST) {
207                         /* translators: the "delete" command is only possible
208                            for playlists; the user attempted to delete a song
209                            or a directory or something else */
210                         screen_status_printf(_("Deleting this item is not possible"));
211                         screen_bell();
212                         continue;
213                 }
215                 playlist = mpd_entity_get_playlist(entity);
216                 str = utf8_to_locale(g_basename(mpd_playlist_get_path(playlist)));
217                 buf = g_strdup_printf(_("Delete playlist %s [%s/%s] ? "), str, YES, NO);
218                 g_free(str);
219                 key = tolower(screen_getch(buf));
220                 g_free(buf);
221                 if( key != YES[0] ) {
222                         /* translators: a dialog was aborted by the user */
223                         screen_status_printf(_("Aborted"));
224                         return 0;
225                 }
227                 if (!mpd_run_rm(c->connection, mpd_playlist_get_path(playlist))) {
228                         mpdclient_handle_error(c);
229                         break;
230                 }
232                 c->events |= MPD_IDLE_STORED_PLAYLIST;
234                 /* translators: MPD deleted the playlist, as requested by the
235                    user */
236                 screen_status_printf(_("Playlist deleted"));
237         }
238         return 0;
241 static void
242 screen_file_init(WINDOW *w, int cols, int rows)
244         current_path = g_strdup("");
246         browser.lw = list_window_init(w, cols, rows);
249 static void
250 screen_file_resize(int cols, int rows)
252         browser.lw->cols = cols;
253         browser.lw->rows = rows;
256 static void
257 screen_file_exit(void)
259         if (browser.filelist)
260                 filelist_free(browser.filelist);
261         list_window_free(browser.lw);
263         g_free(current_path);
266 static void
267 screen_file_open(struct mpdclient *c)
269         screen_file_reload(c);
272 static const char *
273 screen_file_get_title(char *str, size_t size)
275         const char *path = NULL, *prev = NULL, *slash = current_path;
276         char *path_locale;
278         /* determine the last 2 parts of the path */
279         while ((slash = strchr(slash, '/')) != NULL) {
280                 path = prev;
281                 prev = ++slash;
282         }
284         if (path == NULL)
285                 /* fall back to full path */
286                 path = current_path;
288         path_locale = utf8_to_locale(path);
289         g_snprintf(str, size, "%s: %s",
290                    /* translators: caption of the browser screen */
291                    _("Browse"), path_locale);
292         g_free(path_locale);
293         return str;
296 static void
297 screen_file_paint(void)
299         list_window_paint(browser.lw, browser_lw_callback, browser.filelist);
302 static void
303 screen_file_update(struct mpdclient *c)
305         if (c->events & (MPD_IDLE_DATABASE | MPD_IDLE_STORED_PLAYLIST)) {
306                 /* the db has changed -> update the filelist */
307                 screen_file_reload(c);
308                 list_window_check_selected(browser.lw,
309                                            filelist_length(browser.filelist));
310         }
312 #ifndef NCMPC_MINI
313         if (c->events & (MPD_IDLE_DATABASE | MPD_IDLE_STORED_PLAYLIST |
314                          MPD_IDLE_PLAYLIST))
315                 screen_browser_sync_highlights(browser.filelist, &c->playlist);
316 #endif
318         if (c->events & (MPD_IDLE_DATABASE | MPD_IDLE_STORED_PLAYLIST
319 #ifndef NCMPC_MINI
320                          | MPD_IDLE_PLAYLIST
321 #endif
322                          ))
323                 screen_file_repaint();
326 static bool
327 screen_file_cmd(struct mpdclient *c, command_t cmd)
329         switch(cmd) {
330         case CMD_PLAY:
331                 if (screen_file_handle_enter(c)) {
332                         screen_file_repaint();
333                         return true;
334                 }
336                 break;
338         case CMD_GO_ROOT_DIRECTORY:
339                 change_directory(c, "");
340                 screen_file_repaint();
341                 return true;
342         case CMD_GO_PARENT_DIRECTORY:
343                 change_to_parent(c);
344                 screen_file_repaint();
345                 return true;
347         case CMD_LOCATE:
348                 /* don't let browser_cmd() evaluate the locate command
349                    - it's a no-op, and by the way, leads to a
350                    segmentation fault in the current implementation */
351                 return false;
353         case CMD_DELETE:
354                 handle_delete(c);
355                 screen_file_repaint();
356                 break;
357         case CMD_SAVE_PLAYLIST:
358                 handle_save(c);
359                 break;
360         case CMD_SCREEN_UPDATE:
361                 screen_file_reload(c);
362 #ifndef NCMPC_MINI
363                 screen_browser_sync_highlights(browser.filelist, &c->playlist);
364 #endif
365                 list_window_check_selected(browser.lw,
366                                            filelist_length(browser.filelist));
367                 screen_file_repaint();
368                 return false;
370         case CMD_DB_UPDATE:
371                 if (c->status == NULL)
372                         return true;
374                 screen_database_update(c, current_path);
375                 return true;
377         default:
378                 break;
379         }
381         if (browser_cmd(&browser, c, cmd)) {
382                 if (screen_is_visible(&screen_browse))
383                         screen_file_repaint();
384                 return true;
385         }
387         return false;
390 const struct screen_functions screen_browse = {
391         .init = screen_file_init,
392         .exit = screen_file_exit,
393         .open = screen_file_open,
394         .resize = screen_file_resize,
395         .paint = screen_file_paint,
396         .update = screen_file_update,
397         .cmd = screen_file_cmd,
398         .get_title = screen_file_get_title,
399 };
401 bool
402 screen_file_goto_song(struct mpdclient *c, const struct mpd_song *song)
404         const char *uri, *slash, *parent;
405         char *allocated = NULL;
406         bool ret;
407         int i;
409         assert(song != NULL);
411         uri = mpd_song_get_uri(song);
413         if (strstr(uri, "//") != NULL)
414                 /* an URL? */
415                 return false;
417         /* determine the song's parent directory and go there */
419         slash = strrchr(uri, '/');
420         if (slash != NULL)
421                 parent = allocated = g_strndup(uri, slash - uri);
422         else
423                 parent = "";
425         ret = change_directory(c, parent);
426         g_free(allocated);
427         if (!ret)
428                 return false;
430         /* select the specified song */
432         i = filelist_find_song(browser.filelist, song);
433         if (i < 0)
434                 i = 0;
436         list_window_set_selected(browser.lw, i);
438         /* finally, switch to the file screen */
439         screen_switch(&screen_browse, c);
440         return true;