X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fscreen_play.c;h=eb26893c1e5ace2e61fe1d26f2af1280fa381f86;hb=c28152a3ea02318c822247670576f8d6a7ec6e1c;hp=a1bb369e66cb93e5c3f59e7417126b2701fb6919;hpb=08c055113f2eacd42fde57b952b548ca45e29eb2;p=ncmpc.git diff --git a/src/screen_play.c b/src/screen_play.c index a1bb369..eb26893 100644 --- a/src/screen_play.c +++ b/src/screen_play.c @@ -1,27 +1,26 @@ -/* - * $Id$ - * - * (c) 2004 by Kalle Wallin - * +/* ncmpc (Ncurses MPD Client) + * (c) 2004-2009 The Music Player Daemon Project + * Project homepage: http://musicpd.org + * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ #include "config.h" -#include "ncmpc.h" +#include "i18n.h" +#include "charset.h" #include "options.h" -#include "support.h" #include "mpdclient.h" #include "utils.h" #include "strfsong.h" @@ -32,97 +31,140 @@ #include "screen_utils.h" #include "screen_play.h" +#ifndef NCMPC_MINI +#include "hscroll.h" +#endif + #include #include #include #include #include -#include #define MAX_SONG_LENGTH 512 +#ifndef NCMPC_MINI typedef struct { - GList **list; - GList **dir_list; - screen_t *screen; - mpdclient_t *c; + GList **list; + GList **dir_list; + mpdclient_t *c; } completion_callback_data_t; +#endif +static struct mpdclient_playlist *playlist; +static int current_song_id = -1; static list_window_t *lw = NULL; +static guint timer_hide_cursor_id; + +static void +play_paint(void); + +static void +playlist_repaint(void) +{ + play_paint(); + wrefresh(lw->w); +} + +static void +playlist_repaint_if_active(void) +{ + if (screen_is_visible(&screen_playlist)) + playlist_repaint(); +} static void playlist_changed_callback(mpdclient_t *c, int event, gpointer data) { - D("screen_play.c> playlist_callback() [%d]\n", event); - switch(event) { + switch (event) { case PLAYLIST_EVENT_DELETE: break; case PLAYLIST_EVENT_MOVE: - lw->selected = *((int *) data); - if( lw->selectedstart ) - lw->start--; + if(lw->visual_selection < 0) + { + lw->selected = *((int *) data); + if (lw->selected < lw->start) + lw->start--; + } break; default: break; } - /* make shure the playlist is repainted */ - lw->clear = 1; - lw->repaint = 1; - list_window_check_selected(lw, c->playlist.length); + + list_window_check_selected(lw, c->playlist.list->len); + playlist_repaint_if_active(); } static const char * -list_callback(int idx, int *highlight, void *data) +list_callback(unsigned idx, bool *highlight, G_GNUC_UNUSED void *data) { static char songname[MAX_SONG_LENGTH]; - mpdclient_t *c = (mpdclient_t *) data; +#ifndef NCMPC_MINI + static scroll_state_t st; +#endif mpd_Song *song; - *highlight = 0; - if( (song=playlist_get_song(c, idx)) == NULL ) { + if (playlist == NULL || idx >= playlist_length(playlist)) return NULL; - } - if( c->song && song->id==c->song->id && !IS_STOPPED(c->status->state) ) { - *highlight = 1; - } - strfsong(songname, MAX_SONG_LENGTH, LIST_FORMAT, song); + song = playlist_get(playlist, idx); + if (song->id == current_song_id) + *highlight = true; + + strfsong(songname, MAX_SONG_LENGTH, options.list_format, song); + +#ifndef NCMPC_MINI + if (options.scroll && (unsigned)song->pos == lw->selected && + utf8_width(songname) > (unsigned)COLS) { + static unsigned current_song; + char *tmp; + + if (current_song != lw->selected) { + st.offset = 0; + current_song = lw->selected; + } + + tmp = strscroll(songname, options.scroll_sep, + MAX_SONG_LENGTH, &st); + g_strlcpy(songname, tmp, MAX_SONG_LENGTH); + g_free(tmp); + } else if ((unsigned)song->pos == lw->selected) + st.offset = 0; +#endif + return songname; } -static int -center_playing_item(screen_t *screen, mpdclient_t *c) +static void +center_playing_item(mpdclient_t *c) { - int length = c->playlist.length; - int offset = lw->selected - lw->start; + unsigned length = c->playlist.list->len; + unsigned offset = lw->selected - lw->start; int idx; - if (!lw || !c->song || lengthrows || - IS_STOPPED(c->status->state)) - return 0; + if (!c->song || length < lw->rows || + c->status == NULL || IS_STOPPED(c->status->state)) + return; /* try to center the song that are playing */ idx = playlist_get_index(c, c->song); - D("Autocenter song id:%d pos:%d index:%d\n", c->song->id,c->song->pos,idx); - lw->start = idx - (lw->rows / 2); - if (lw->start + lw->rows > length) - lw->start = length - lw->rows; - if (lw->start < 0) - lw->start = 0; + if (idx < 0) + return; + + list_window_center(lw, length, idx); /* make sure the cursor is in the window */ lw->selected = lw->start+offset; + lw->selected_start = lw->selected; + lw->selected_end = lw->selected; list_window_check_selected(lw, length); - - lw->clear = 1; - lw->repaint = 1; - - return 0; } +#ifndef NCMPC_MINI static void -save_pre_completion_cb(GCompletion *gcmp, gchar *line, void *data) +save_pre_completion_cb(GCompletion *gcmp, G_GNUC_UNUSED gchar *line, + void *data) { completion_callback_data_t *tmp = (completion_callback_data_t *)data; GList **list = tmp->list; @@ -136,196 +178,225 @@ save_pre_completion_cb(GCompletion *gcmp, gchar *line, void *data) } static void -save_post_completion_cb(GCompletion *gcmp, gchar *line, GList *items, - void *data) +save_post_completion_cb(G_GNUC_UNUSED GCompletion *gcmp, + G_GNUC_UNUSED gchar *line, GList *items, + G_GNUC_UNUSED void *data) { - completion_callback_data_t *tmp = (completion_callback_data_t *)data; - screen_t *screen = tmp->screen; + if (g_list_length(items) >= 1) + screen_display_completion_list(items); +} +#endif - if( g_list_length(items)>=1 ) { - screen_display_completion_list(screen, items); - lw->clear = 1; - lw->repaint = 1; - } +#ifndef NCMPC_MINI +/** + * Wrapper for strncmp(). We are not allowed to pass &strncmp to + * g_completion_set_compare(), because strncmp() takes size_t where + * g_completion_set_compare passes a gsize value. + */ +static gint +completion_strncmp(const gchar *s1, const gchar *s2, gsize n) +{ + return strncmp(s1, s2, n); } +#endif int -playlist_save(screen_t *screen, mpdclient_t *c, char *name, char *defaultname) +playlist_save(mpdclient_t *c, char *name, char *defaultname) { - gchar *filename; - gint error; - GCompletion *gcmp; - GList *list = NULL; - completion_callback_data_t data; - - if( name==NULL ) - { - /* initialize completion support */ - gcmp = g_completion_new(NULL); - g_completion_set_compare(gcmp, strncmp); - data.list = &list; - data.dir_list = NULL; - data.screen = screen; - data.c = c; - wrln_completion_callback_data = &data; - wrln_pre_completion_callback = save_pre_completion_cb; - wrln_post_completion_callback = save_post_completion_cb; - - - /* query the user for a filename */ - filename = screen_readln(screen->status_window.w, - _("Save playlist as: "), - defaultname, - NULL, - gcmp); - - /* destroy completion support */ - wrln_completion_callback_data = NULL; - wrln_pre_completion_callback = NULL; - wrln_post_completion_callback = NULL; - g_completion_free(gcmp); - list = string_list_free(list); - if( filename ) - filename=g_strstrip(filename); - } - else - { - filename=g_strdup(name); - } - if( filename==NULL || filename[0]=='\0' ) - return -1; - /* send save command to mpd */ - D("Saving playlist as \'%s \'...\n", filename); - if( (error=mpdclient_cmd_save_playlist(c, filename)) ) - { - gint code = GET_ACK_ERROR_CODE(error); - - if( code == MPD_ACK_ERROR_EXIST ) - { - char *buf; - int key; - - buf=g_strdup_printf(_("Replace %s [%s/%s] ? "), filename, YES, NO); - key = tolower(screen_getch(screen->status_window.w, buf)); - g_free(buf); - if( key == YES[0] ) - { - if( mpdclient_cmd_delete_playlist(c, filename) ) - { - g_free(filename); - return -1; + gchar *filename, *filename_utf8; + gint error; +#ifndef NCMPC_MINI + GCompletion *gcmp; + GList *list = NULL; + completion_callback_data_t data; +#endif + +#ifdef NCMPC_MINI + (void)defaultname; +#endif + +#ifndef NCMPC_MINI + if (name == NULL) { + /* initialize completion support */ + gcmp = g_completion_new(NULL); + g_completion_set_compare(gcmp, completion_strncmp); + data.list = &list; + data.dir_list = NULL; + data.c = c; + wrln_completion_callback_data = &data; + wrln_pre_completion_callback = save_pre_completion_cb; + wrln_post_completion_callback = save_post_completion_cb; + + + /* query the user for a filename */ + filename = screen_readln(screen.status_window.w, + _("Save playlist as: "), + defaultname, + NULL, + gcmp); + + /* destroy completion support */ + wrln_completion_callback_data = NULL; + wrln_pre_completion_callback = NULL; + wrln_post_completion_callback = NULL; + g_completion_free(gcmp); + list = string_list_free(list); + if( filename ) + filename=g_strstrip(filename); + } else +#endif + filename=g_strdup(name); + + if (filename == NULL) + return -1; + + /* send save command to mpd */ + + filename_utf8 = locale_to_utf8(filename); + error = mpdclient_cmd_save_playlist(c, filename_utf8); + g_free(filename_utf8); + + if (error) { + gint code = GET_ACK_ERROR_CODE(error); + + if (code == MPD_ACK_ERROR_EXIST) { + char *buf; + int key; + + buf = g_strdup_printf(_("Replace %s [%s/%s] ? "), + filename, YES, NO); + key = tolower(screen_getch(screen.status_window.w, + buf)); + g_free(buf); + + if (key == YES[0]) { + filename_utf8 = locale_to_utf8(filename); + error = mpdclient_cmd_delete_playlist(c, filename_utf8); + g_free(filename_utf8); + + if (error) { + g_free(filename); + return -1; + } + + error = playlist_save(c, filename, NULL); + g_free(filename); + return error; + } + + screen_status_printf(_("Aborted")); } - error = playlist_save(screen, c, filename, NULL); - g_free(filename); - return error; - } - screen_status_printf(_("Aborted!")); + + g_free(filename); + return -1; } - g_free(filename); - return -1; - } - /* success */ - screen_status_printf(_("Saved %s"), filename); - g_free(filename); - return 0; + + /* success */ + screen_status_printf(_("Saved %s"), filename); + g_free(filename); + return 0; } +#ifndef NCMPC_MINI static void add_dir(GCompletion *gcmp, gchar *dir, GList **dir_list, - GList **list, mpdclient_t *c) + GList **list, mpdclient_t *c) { - g_completion_remove_items(gcmp, *list); - *list = string_list_remove(*list, dir); - *list = gcmp_list_from_path(c, dir, *list, GCMP_TYPE_RFILE); - g_completion_add_items(gcmp, *list); - *dir_list = g_list_append(*dir_list, g_strdup(dir)); + g_completion_remove_items(gcmp, *list); + *list = string_list_remove(*list, dir); + *list = gcmp_list_from_path(c, dir, *list, GCMP_TYPE_RFILE); + g_completion_add_items(gcmp, *list); + *dir_list = g_list_append(*dir_list, g_strdup(dir)); } static void add_pre_completion_cb(GCompletion *gcmp, gchar *line, void *data) { - completion_callback_data_t *tmp = (completion_callback_data_t *)data; - GList **dir_list = tmp->dir_list; - GList **list = tmp->list; - mpdclient_t *c = tmp->c; - - D("pre_completion()...\n"); - if( *list == NULL ) - { - /* create initial list */ - *list = gcmp_list_from_path(c, "", NULL, GCMP_TYPE_RFILE); - g_completion_add_items(gcmp, *list); - } - else if( line && line[0] && line[strlen(line)-1]=='/' && - string_list_find(*dir_list, line) == NULL ) - { - /* add directory content to list */ - add_dir(gcmp, line, dir_list, list, c); - } + completion_callback_data_t *tmp = (completion_callback_data_t *)data; + GList **dir_list = tmp->dir_list; + GList **list = tmp->list; + mpdclient_t *c = tmp->c; + + if (*list == NULL) { + /* create initial list */ + *list = gcmp_list_from_path(c, "", NULL, GCMP_TYPE_RFILE); + g_completion_add_items(gcmp, *list); + } else if (line && line[0] && line[strlen(line)-1]=='/' && + string_list_find(*dir_list, line) == NULL) { + /* add directory content to list */ + add_dir(gcmp, line, dir_list, list, c); + } } static void add_post_completion_cb(GCompletion *gcmp, gchar *line, - GList *items, void *data) + GList *items, void *data) { - completion_callback_data_t *tmp = (completion_callback_data_t *)data; - GList **dir_list = tmp->dir_list; - GList **list = tmp->list; - mpdclient_t *c = tmp->c; - screen_t *screen = tmp->screen; - - D("post_completion()...\n"); - if( g_list_length(items)>=1 ) - { - screen_display_completion_list(screen, items); - lw->clear = 1; - lw->repaint = 1; - } - - if( line && line[0] && line[strlen(line)-1]=='/' && - string_list_find(*dir_list, line) == NULL ) - { - /* add directory content to list */ - add_dir(gcmp, line, dir_list, list, c); - } + completion_callback_data_t *tmp = (completion_callback_data_t *)data; + GList **dir_list = tmp->dir_list; + GList **list = tmp->list; + mpdclient_t *c = tmp->c; + + if (g_list_length(items) >= 1) + screen_display_completion_list(items); + + if (line && line[0] && line[strlen(line) - 1] == '/' && + string_list_find(*dir_list, line) == NULL) { + /* add directory content to list */ + add_dir(gcmp, line, dir_list, list, c); + } } +#endif static int -handle_add_to_playlist(screen_t *screen, mpdclient_t *c) +handle_add_to_playlist(mpdclient_t *c) { - gchar *path; - GCompletion *gcmp; - GList *list = NULL; - GList *dir_list = NULL; - completion_callback_data_t data; - - /* initialize completion support */ - gcmp = g_completion_new(NULL); - g_completion_set_compare(gcmp, strncmp); - data.list = &list; - data.dir_list = &dir_list; - data.screen = screen; - data.c = c; - wrln_completion_callback_data = &data; - wrln_pre_completion_callback = add_pre_completion_cb; - wrln_post_completion_callback = add_post_completion_cb; - /* get path */ - path = screen_readln(screen->status_window.w, - _("Add: "), - NULL, - NULL, - gcmp); - - /* destroy completion data */ - wrln_completion_callback_data = NULL; - wrln_pre_completion_callback = NULL; - wrln_post_completion_callback = NULL; - g_completion_free(gcmp); - string_list_free(list); - string_list_free(dir_list); - - /* add the path to the playlist */ - if( path && path[0] ) - mpdclient_cmd_add_path(c, path); - - return 0; + gchar *path; +#ifndef NCMPC_MINI + GCompletion *gcmp; + GList *list = NULL; + GList *dir_list = NULL; + completion_callback_data_t data; + + /* initialize completion support */ + gcmp = g_completion_new(NULL); + g_completion_set_compare(gcmp, completion_strncmp); + data.list = &list; + data.dir_list = &dir_list; + data.c = c; + wrln_completion_callback_data = &data; + wrln_pre_completion_callback = add_pre_completion_cb; + wrln_post_completion_callback = add_post_completion_cb; +#endif + + /* get path */ + path = screen_readln(screen.status_window.w, + _("Add: "), + NULL, + NULL, +#ifdef NCMPC_MINI + NULL +#else + gcmp +#endif + ); + + /* destroy completion data */ +#ifndef NCMPC_MINI + wrln_completion_callback_data = NULL; + wrln_pre_completion_callback = NULL; + wrln_post_completion_callback = NULL; + g_completion_free(gcmp); + string_list_free(list); + string_list_free(dir_list); +#endif + + /* add the path to the playlist */ + if (path != NULL) { + char *path_utf8 = locale_to_utf8(path); + mpdclient_cmd_add_path(c, path_utf8); + g_free(path_utf8); + } + + g_free(path); + return 0; } static void @@ -334,17 +405,57 @@ play_init(WINDOW *w, int cols, int rows) lw = list_window_init(w, cols, rows); } +static gboolean +timer_hide_cursor(gpointer data) +{ + struct mpdclient *c = data; + + assert(options.hide_cursor > 0); + assert(timer_hide_cursor_id != 0); + + timer_hide_cursor_id = 0; + + /* hide the cursor when mpd is playing and the user is inactive */ + + if (c->status != NULL && c->status->state == MPD_STATUS_STATE_PLAY) { + lw->hide_cursor = true; + playlist_repaint(); + } else + timer_hide_cursor_id = g_timeout_add(options.hide_cursor * 1000, + timer_hide_cursor, c); + + return FALSE; +} + static void -play_open(screen_t *screen, mpdclient_t *c) +play_open(mpdclient_t *c) { static gboolean install_cb = TRUE; + playlist = &c->playlist; + + assert(timer_hide_cursor_id == 0); + if (options.hide_cursor > 0) { + lw->hide_cursor = false; + timer_hide_cursor_id = g_timeout_add(options.hide_cursor * 1000, + timer_hide_cursor, c); + } + if (install_cb) { mpdclient_install_playlist_callback(c, playlist_changed_callback); install_cb = FALSE; } } +static void +play_close(void) +{ + if (timer_hide_cursor_id != 0) { + g_source_remove(timer_hide_cursor_id); + timer_hide_cursor_id = 0; + } +} + static void play_resize(int cols, int rows) { @@ -370,72 +481,61 @@ play_title(char *str, size_t size) } static void -play_paint(screen_t *screen, mpdclient_t *c) +play_paint(void) { - lw->clear = 1; - - list_window_paint(lw, list_callback, (void *) c); - wnoutrefresh(lw->w); + list_window_paint(lw, list_callback, NULL); } static void -play_update(screen_t *screen, mpdclient_t *c) +play_update(mpdclient_t *c) { - /* hide the cursor when mpd are playing and the user are inactive */ - if( options.hide_cursor>0 && c->status->state == MPD_STATUS_STATE_PLAY && - time(NULL)-screen->input_timestamp >= options.hide_cursor ) { - lw->flags |= LW_HIDE_CURSOR; - } else { - lw->flags &= ~LW_HIDE_CURSOR; - } + static int prev_song_id = -1; - /* center the cursor */ - if( options.auto_center ) { - static int prev_song_id = 0; + current_song_id = c->song != NULL && c->status != NULL && + !IS_STOPPED(c->status->state) ? c->song->id : -1; - if( c->song && prev_song_id != c->song->id ) { - center_playing_item(screen, c); - prev_song_id = c->song->id; - } - } + if (current_song_id != prev_song_id) { + prev_song_id = current_song_id; + + /* center the cursor */ + if (options.auto_center && current_song_id != -1) + center_playing_item(c); - if( c->playlist.updated ) { - if( lw->selected >= c->playlist.length ) - lw->selected = c->playlist.length-1; - if( lw->start >= c->playlist.length ) - list_window_reset(lw); - - play_paint(screen, c); - c->playlist.updated = FALSE; - } else if( lw->repaint || 1) { - list_window_paint(lw, list_callback, (void *) c); - wnoutrefresh(lw->w); - lw->repaint = 0; + playlist_repaint(); +#ifndef NCMPC_MINI + } else if (options.scroll) { + /* always repaint if horizontal scrolling is + enabled */ + playlist_repaint(); +#endif } } #ifdef HAVE_GETMOUSE -static int -handle_mouse_event(screen_t *screen, mpdclient_t *c) +static bool +handle_mouse_event(struct mpdclient *c) { int row; - int selected; + unsigned selected; unsigned long bstate; - if (screen_get_mouse_event(c, lw, c->playlist.length, &bstate, &row)) - return 1; + if (screen_get_mouse_event(c, &bstate, &row) || + list_window_mouse(lw, playlist_length(playlist), bstate, row)) { + playlist_repaint(); + return true; + } if (bstate & BUTTON1_DOUBLE_CLICKED) { /* stop */ screen_cmd(c, CMD_STOP); - return 1; + return true; } selected = lw->start + row; if (bstate & BUTTON1_CLICKED) { /* play */ - if (lw->start + row < c->playlist.length) + if (lw->start + row < playlist_length(playlist)) mpdclient_cmd_play(c, lw->start + row); } else if (bstate & BUTTON3_CLICKED) { /* delete */ @@ -444,79 +544,166 @@ handle_mouse_event(screen_t *screen, mpdclient_t *c) } lw->selected = selected; - list_window_check_selected(lw, c->playlist.length); + list_window_check_selected(lw, playlist_length(playlist)); + playlist_repaint(); - return 1; + return true; } -#else -#define handle_mouse_event(s,c) (0) #endif -static int -play_cmd(screen_t *screen, mpdclient_t *c, command_t cmd) +static bool +play_cmd(mpdclient_t *c, command_t cmd) { + lw->hide_cursor = false; + + if (options.hide_cursor > 0) { + if (timer_hide_cursor_id != 0) + g_source_remove(timer_hide_cursor_id); + timer_hide_cursor_id = g_timeout_add(options.hide_cursor * 1000, + timer_hide_cursor, c); + } + + if (list_window_cmd(lw, playlist_length(&c->playlist), cmd)) { + playlist_repaint(); + return true; + } + switch(cmd) { case CMD_PLAY: mpdclient_cmd_play(c, lw->selected); - return 1; + return true; case CMD_DELETE: - mpdclient_cmd_delete(c, lw->selected); - return 1; + { + int i = lw->selected_end, start = lw->selected_start; + for(; i >= start; --i) + mpdclient_cmd_delete(c, i); + + i++; + if(i >= (int)playlist_length(&c->playlist)) + i--; + lw->selected = i; + lw->selected_start = i; + lw->selected_end = i; + lw->visual_selection = false; + + return true; + } case CMD_SAVE_PLAYLIST: - playlist_save(screen, c, NULL, NULL); - return 1; + playlist_save(c, NULL, NULL); + return true; case CMD_ADD: - handle_add_to_playlist(screen, c); - return 1; + handle_add_to_playlist(c); + return true; case CMD_SCREEN_UPDATE: - screen->painted = 0; - lw->clear = 1; - lw->repaint = 1; - center_playing_item(screen, c); - return 1; + center_playing_item(c); + playlist_repaint(); + return false; + case CMD_SHUFFLE: + { + unsigned i = lw->selected_start + 1; + unsigned last_selected = lw->selected; + if(!lw->visual_selection) + /* No visual selection, shuffle all list. */ + break; + for(; i <= lw->selected_end; ++i) + mpdclient_cmd_move(c, i, lw->selected_start + (rand() % ((i - lw->selected_start) + 1))); + + lw->selected = last_selected; + screen_status_printf(_("Shuffled selection!")); + + return true; + } case CMD_LIST_MOVE_UP: - mpdclient_cmd_move(c, lw->selected, lw->selected-1); - return 1; + if(lw->selected_start == 0) + return false; + if(lw->visual_selection) + { + unsigned i = lw->selected_start; + unsigned last_selected = lw->selected; + for(; i <= lw->selected_end; ++i) + mpdclient_cmd_move(c, i, i-1); + lw->selected_start--; + lw->selected_end--; + lw->selected = last_selected - 1; + lw->visual_base--; + } + else + mpdclient_cmd_move(c, lw->selected, lw->selected-1); + return true; case CMD_LIST_MOVE_DOWN: - mpdclient_cmd_move(c, lw->selected, lw->selected+1); - return 1; + if(lw->selected_end+1 >= playlist_length(&c->playlist)) + return false; + if(lw->visual_selection) + { + int i = lw->selected_end; + unsigned last_selected = lw->selected; + for(; i >= (int)lw->selected_start; --i) + mpdclient_cmd_move(c, i, i+1); + lw->selected_start++; + lw->selected_end++; + lw->selected = last_selected + 1; + lw->visual_base++; + } + else + mpdclient_cmd_move(c, lw->selected, lw->selected+1); + return true; case CMD_LIST_FIND: case CMD_LIST_RFIND: case CMD_LIST_FIND_NEXT: case CMD_LIST_RFIND_NEXT: - return screen_find(screen, - lw, c->playlist.length, - cmd, list_callback, (void *) c); + screen_find(lw, playlist_length(&c->playlist), + cmd, list_callback, NULL); + playlist_repaint(); + return true; + +#ifdef HAVE_GETMOUSE case CMD_MOUSE_EVENT: - return handle_mouse_event(screen,c); + return handle_mouse_event(c); +#endif + +#ifdef ENABLE_SONG_SCREEN + case CMD_VIEW: + if (lw->selected < playlist_length(&c->playlist)) { + screen_song_switch(c, playlist_get(&c->playlist, lw->selected)); + return true; + } + + break; +#endif + + case CMD_LOCATE: + if (lw->selected < playlist_length(&c->playlist)) { + screen_file_goto_song(c, playlist_get(&c->playlist, lw->selected)); + return true; + } + + break; + +#ifdef ENABLE_LYRICS_SCREEN + case CMD_SCREEN_LYRICS: + if (lw->selected < playlist_length(&c->playlist)) { + screen_lyrics_switch(c, playlist_get(&c->playlist, lw->selected)); + return true; + } + + break; +#endif + default: break; } - return list_window_cmd(lw, c->playlist.length, cmd) ; -} -static list_window_t * -play_lw(void) -{ - return lw; + return false; } -screen_functions_t * -get_screen_playlist(void) -{ - static screen_functions_t functions; - - memset(&functions, 0, sizeof(screen_functions_t)); - functions.init = play_init; - functions.exit = play_exit; - functions.open = play_open; - functions.close = NULL; - functions.resize = play_resize; - functions.paint = play_paint; - functions.update = play_update; - functions.cmd = play_cmd; - functions.get_lw = play_lw; - functions.get_title = play_title; - - return &functions; -} +const struct screen_functions screen_playlist = { + .init = play_init, + .exit = play_exit, + .open = play_open, + .close = play_close, + .resize = play_resize, + .paint = play_paint, + .update = play_update, + .cmd = play_cmd, + .get_title = play_title, +};