1 /*
2 * $Id$
3 *
4 * (c) 2004 by Kalle Wallin <kaw@linux.se>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
21 #include "config.h"
22 #include "ncmpc.h"
23 #include "options.h"
24 #include "support.h"
25 #include "mpdclient.h"
26 #include "command.h"
27 #include "screen.h"
28 #include "screen_utils.h"
29 #include "screen_browser.h"
30 #include "screen_play.h"
31 #include "gcc.h"
33 #include <ctype.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <glib.h>
37 #include <ncurses.h>
39 static struct screen_browser browser;
41 /* the db have changed -> update the filelist */
42 static void
43 file_changed_callback(mpdclient_t *c, mpd_unused int event,
44 mpd_unused gpointer data)
45 {
46 D("screen_file.c> filelist_callback() [%d]\n", event);
47 browser.filelist = mpdclient_filelist_update(c, browser.filelist);
48 sync_highlights(c, browser.filelist);
49 list_window_check_selected(browser.lw, browser.filelist->length);
50 }
52 /* the playlist have been updated -> fix highlights */
53 static void
54 playlist_changed_callback(mpdclient_t *c, int event, gpointer data)
55 {
56 D("screen_file.c> playlist_callback() [%d]\n", event);
57 switch(event) {
58 case PLAYLIST_EVENT_CLEAR:
59 clear_highlights(browser.filelist);
60 break;
61 case PLAYLIST_EVENT_ADD:
62 set_highlight(browser.filelist, (mpd_Song *) data, 1);
63 break;
64 case PLAYLIST_EVENT_DELETE:
65 set_highlight(browser.filelist, (mpd_Song *) data, 0);
66 break;
67 case PLAYLIST_EVENT_MOVE:
68 break;
69 default:
70 sync_highlights(c, browser.filelist);
71 break;
72 }
73 }
75 static int
76 handle_save(screen_t *screen, mpdclient_t *c)
77 {
78 filelist_entry_t *entry;
79 char *defaultname = NULL;
81 entry = g_list_nth_data(browser.filelist->list, browser.lw->selected);
82 if( entry && entry->entity ) {
83 mpd_InfoEntity *entity = entry->entity;
84 if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE ) {
85 mpd_PlaylistFile *plf = entity->info.playlistFile;
86 defaultname = plf->path;
87 }
88 }
90 return playlist_save(screen, c, NULL, defaultname);
91 }
93 static int
94 handle_delete(screen_t *screen, mpdclient_t *c)
95 {
96 filelist_entry_t *entry;
97 mpd_InfoEntity *entity;
98 mpd_PlaylistFile *plf;
99 char *str, *buf;
100 int key;
102 entry = g_list_nth_data(browser.filelist->list,browser. lw->selected);
103 if( entry==NULL || entry->entity==NULL )
104 return -1;
106 entity = entry->entity;
108 if( entity->type!=MPD_INFO_ENTITY_TYPE_PLAYLISTFILE ) {
109 screen_status_printf(_("You can only delete playlists!"));
110 screen_bell();
111 return -1;
112 }
114 plf = entity->info.playlistFile;
115 str = utf8_to_locale(basename(plf->path));
116 buf = g_strdup_printf(_("Delete playlist %s [%s/%s] ? "), str, YES, NO);
117 g_free(str);
118 key = tolower(screen_getch(screen->status_window.w, buf));
119 g_free(buf);
120 if( key==KEY_RESIZE )
121 screen_resize();
122 if( key != YES[0] ) {
123 screen_status_printf(_("Aborted!"));
124 return 0;
125 }
127 if( mpdclient_cmd_delete_playlist_utf8(c, plf->path) )
128 return -1;
130 screen_status_printf(_("Playlist deleted!"));
131 return 0;
132 }
134 static void
135 browse_init(WINDOW *w, int cols, int rows)
136 {
137 browser.lw = list_window_init(w, cols, rows);
138 browser.lw_state = list_window_init_state();
139 }
141 static void
142 browse_resize(int cols, int rows)
143 {
144 browser.lw->cols = cols;
145 browser.lw->rows = rows;
146 }
148 static void
149 browse_exit(void)
150 {
151 if (browser.filelist)
152 mpdclient_filelist_free(browser.filelist);
153 list_window_free(browser.lw);
154 list_window_free_state(browser.lw_state);
155 }
157 static void
158 browse_open(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c)
159 {
160 if (browser.filelist == NULL) {
161 browser.filelist = mpdclient_filelist_get(c, "");
162 mpdclient_install_playlist_callback(c, playlist_changed_callback);
163 mpdclient_install_browse_callback(c, file_changed_callback);
164 }
165 }
167 static const char *
168 browse_title(char *str, size_t size)
169 {
170 char *pathcopy;
171 char *parentdir;
173 pathcopy = strdup(browser.filelist->path);
174 parentdir = dirname(pathcopy);
175 parentdir = basename(parentdir);
177 if( parentdir[0] == '.' && strlen(parentdir) == 1 ) {
178 parentdir = NULL;
179 }
181 g_snprintf(str, size, _("Browse: %s%s%s"),
182 parentdir ? parentdir : "",
183 parentdir ? "/" : "",
184 basename(browser.filelist->path));
185 free(pathcopy);
186 return str;
187 }
189 static void
190 browse_paint(mpd_unused screen_t *screen, mpd_unused mpdclient_t *c)
191 {
192 browser.lw->clear = 1;
194 list_window_paint(browser.lw, browser_lw_callback, browser.filelist);
195 wnoutrefresh(browser.lw->w);
196 }
198 static void
199 browse_update(screen_t *screen, mpdclient_t *c)
200 {
201 if (browser.filelist->updated) {
202 browse_paint(screen, c);
203 browser.filelist->updated = FALSE;
204 return;
205 }
207 list_window_paint(browser.lw, browser_lw_callback, browser.filelist);
208 wnoutrefresh(browser.lw->w);
209 }
211 static int
212 browse_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
213 {
214 switch(cmd) {
215 case CMD_PLAY:
216 browser_handle_enter(&browser, c);
217 return 1;
218 case CMD_GO_ROOT_DIRECTORY:
219 return browser_change_directory(&browser, c, NULL, "");
220 break;
221 case CMD_GO_PARENT_DIRECTORY:
222 return browser_change_directory(&browser, c, NULL, "..");
223 break;
224 case CMD_SELECT:
225 if (browser_handle_select(&browser, c) == 0) {
226 /* continue and select next item... */
227 cmd = CMD_LIST_NEXT;
228 }
229 break;
230 case CMD_DELETE:
231 handle_delete(screen, c);
232 break;
233 case CMD_SAVE_PLAYLIST:
234 handle_save(screen, c);
235 break;
236 case CMD_SCREEN_UPDATE:
237 screen->painted = 0;
238 browser.lw->clear = 1;
239 browser.lw->repaint = 1;
240 browser.filelist = mpdclient_filelist_update(c, browser.filelist);
241 list_window_check_selected(browser.lw,
242 browser.filelist->length);
243 screen_status_printf(_("Screen updated!"));
244 return 1;
245 case CMD_DB_UPDATE:
246 if (c->status == NULL)
247 return 1;
249 if (!c->status->updatingDb) {
250 if (mpdclient_cmd_db_update_utf8(c, browser.filelist->path) == 0) {
251 if (strcmp(browser.filelist->path, ""))
252 screen_status_printf(_("Database update of %s started!"),
253 browser.filelist->path);
254 else
255 screen_status_printf(_("Database update started!"));
257 /* set updatingDb to make shure the browse callback gets called
258 * even if the updated has finished before status is updated */
259 c->status->updatingDb = 1;
260 }
261 } else
262 screen_status_printf(_("Database update running..."));
263 return 1;
264 case CMD_LIST_FIND:
265 case CMD_LIST_RFIND:
266 case CMD_LIST_FIND_NEXT:
267 case CMD_LIST_RFIND_NEXT:
268 return screen_find(screen,
269 browser.lw, browser.filelist->length,
270 cmd, browser_lw_callback,
271 browser.filelist);
272 case CMD_MOUSE_EVENT:
273 return browser_handle_mouse_event(&browser, c);
274 default:
275 break;
276 }
278 return list_window_cmd(browser.lw, browser.filelist->length, cmd);
279 }
281 const struct screen_functions screen_browse = {
282 .init = browse_init,
283 .exit = browse_exit,
284 .open = browse_open,
285 .resize = browse_resize,
286 .paint = browse_paint,
287 .update = browse_update,
288 .cmd = browse_cmd,
289 .get_title = browse_title,
290 };