X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fscreen_queue.c;h=d98445ded49bc0a1a6b3f8e2406e191dcd69dc27;hb=aab54ebefbbb5e81e8feca6dfd08ea463df88e7c;hp=93b3cfe5498089967fee682ae998e5d3d6b675a7;hpb=275d9e8b34d33465c4cd88c6cf8bfba39ed86a16;p=ncmpc.git diff --git a/src/screen_queue.c b/src/screen_queue.c index 93b3cfe..d98445d 100644 --- a/src/screen_queue.c +++ b/src/screen_queue.c @@ -1,5 +1,5 @@ /* ncmpc (Ncurses MPD Client) - * (c) 2004-2009 The Music Player Daemon Project + * (c) 2004-2017 The Music Player Daemon Project * Project homepage: http://musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -20,8 +20,9 @@ #include "screen_queue.h" #include "screen_interface.h" #include "screen_file.h" -#include "screen_message.h" +#include "screen_status.h" #include "screen_find.h" +#include "save_playlist.h" #include "config.h" #include "i18n.h" #include "charset.h" @@ -35,6 +36,8 @@ #include "screen_utils.h" #include "screen_song.h" #include "screen_lyrics.h" +#include "db_completion.h" +#include "Compiler.h" #ifndef NCMPC_MINI #include "hscroll.h" @@ -95,22 +98,19 @@ screen_queue_save_selection(void) static void screen_queue_restore_selection(void) { - const struct mpd_song *song; - int pos; - list_window_set_length(lw, playlist_length(playlist)); if (selected_song_id < 0) /* there was no selection */ return; - song = screen_queue_selected_song(); + const struct mpd_song *song = screen_queue_selected_song(); if (song != NULL && mpd_song_get_id(song) == (unsigned)selected_song_id) /* selection is still valid */ return; - pos = playlist_get_index_from_id(playlist, selected_song_id); + int pos = playlist_get_index_from_id(playlist, selected_song_id); if (pos >= 0) list_window_set_cursor(lw, pos); @@ -118,15 +118,14 @@ screen_queue_restore_selection(void) } static const char * -screen_queue_lw_callback(unsigned idx, G_GNUC_UNUSED void *data) +screen_queue_lw_callback(unsigned idx, gcc_unused void *data) { static char songname[MAX_SONG_LENGTH]; - struct mpd_song *song; assert(playlist != NULL); assert(idx < playlist_length(playlist)); - song = playlist_get(playlist, idx); + struct mpd_song *song = playlist_get(playlist, idx); strfsong(songname, MAX_SONG_LENGTH, options.list_format, song); @@ -134,23 +133,18 @@ screen_queue_lw_callback(unsigned idx, G_GNUC_UNUSED void *data) } static void -center_playing_item(struct mpdclient *c, bool center_cursor) +center_playing_item(const struct mpd_status *status, bool center_cursor) { - unsigned length = c->playlist.list->len; - int idx; + if (status == NULL || + (mpd_status_get_state(status) != MPD_STATE_PLAY && + mpd_status_get_state(status) != MPD_STATE_PAUSE)) + return; /* try to center the song that are playing */ - idx = playlist_get_index(&c->playlist, c->song); + int idx = mpd_status_get_song_pos(status); if (idx < 0) return; - if (length < lw->rows) - { - if (center_cursor) - list_window_set_cursor(lw, idx); - return; - } - list_window_center(lw, idx); if (center_cursor) { @@ -162,31 +156,31 @@ center_playing_item(struct mpdclient *c, bool center_cursor) list_window_fetch_cursor(lw); } -#ifndef NCMPC_MINI -static void -save_pre_completion_cb(GCompletion *gcmp, G_GNUC_UNUSED gchar *line, - void *data) +gcc_pure +static int +get_current_song_id(const struct mpd_status *status) { - completion_callback_data_t *tmp = (completion_callback_data_t *)data; - GList **list = tmp->list; - struct mpdclient *c = tmp->c; - - if( *list == NULL ) { - /* create completion list */ - *list = gcmp_list_from_path(c, "", NULL, GCMP_TYPE_PLAYLIST); - g_completion_add_items(gcmp, *list); - } + return status != NULL && + (mpd_status_get_state(status) == MPD_STATE_PLAY || + mpd_status_get_state(status) == MPD_STATE_PAUSE) + ? (int)mpd_status_get_song_id(status) + : -1; } -static void -save_post_completion_cb(G_GNUC_UNUSED GCompletion *gcmp, - G_GNUC_UNUSED gchar *line, GList *items, - G_GNUC_UNUSED void *data) +static bool +screen_queue_song_change(const struct mpd_status *status) { - if (g_list_length(items) >= 1) - screen_display_completion_list(items); + if (get_current_song_id(status) == current_song_id) + return false; + + current_song_id = get_current_song_id(status); + + /* center the cursor */ + if (options.auto_center && !lw->range_selection) + center_playing_item(status, false); + + return true; } -#endif #ifndef NCMPC_MINI /** @@ -201,106 +195,6 @@ completion_strncmp(const gchar *s1, const gchar *s2, gsize n) } #endif -int -playlist_save(struct mpdclient *c, char *name, char *defaultname) -{ - struct mpd_connection *connection; - gchar *filename, *filename_utf8; -#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(_("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 */ - - connection = mpdclient_get_connection(c); - if (connection == NULL) - return -1; - - filename_utf8 = locale_to_utf8(filename); - if (!mpd_run_save(connection, filename_utf8)) { - if (mpd_connection_get_error(connection) == MPD_ERROR_SERVER && - mpd_connection_get_server_error(connection) == MPD_SERVER_ERROR_EXIST && - mpd_connection_clear_error(connection)) { - char *buf; - int key; - - buf = g_strdup_printf(_("Replace %s [%s/%s] ? "), - filename, YES, NO); - key = tolower(screen_getch(buf)); - g_free(buf); - - if (key != YES[0]) { - g_free(filename_utf8); - g_free(filename); - screen_status_printf(_("Aborted")); - return -1; - } - - if (!mpd_run_rm(connection, filename_utf8) || - !mpd_run_save(connection, filename_utf8)) { - mpdclient_handle_error(c); - g_free(filename_utf8); - g_free(filename); - return -1; - } - } else { - mpdclient_handle_error(c); - g_free(filename_utf8); - g_free(filename); - return -1; - } - } - - c->events |= MPD_IDLE_STORED_PLAYLIST; - - g_free(filename_utf8); - - /* 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, struct mpdclient *c) @@ -352,34 +246,31 @@ static void add_post_completion_cb(GCompletion *gcmp, gchar *line, static int handle_add_to_playlist(struct mpdclient *c) { - gchar *path; #ifndef NCMPC_MINI - GCompletion *gcmp; + /* initialize completion support */ + GCompletion *gcmp = g_completion_new(NULL); + g_completion_set_compare(gcmp, completion_strncmp); + GList *list = NULL; GList *dir_list = NULL; - completion_callback_data_t data; + completion_callback_data_t data = { + .list = &list, + .dir_list = &dir_list, + .c = c, + }; - /* 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; +#else + GCompletion *gcmp = NULL; #endif /* get path */ - path = screen_readln(_("Add"), - NULL, - NULL, -#ifdef NCMPC_MINI - NULL -#else - gcmp -#endif - ); + char *path = screen_readln(_("Add"), + NULL, + NULL, + gcmp); /* destroy completion data */ #ifndef NCMPC_MINI @@ -403,7 +294,7 @@ handle_add_to_playlist(struct mpdclient *c) } static void -screen_queue_init(WINDOW *w, int cols, int rows) +screen_queue_init(WINDOW *w, unsigned cols, unsigned rows) { lw = list_window_init(w, cols, rows); @@ -430,8 +321,8 @@ timer_hide_cursor(gpointer data) lw->hide_cursor = true; screen_queue_repaint(); } else - timer_hide_cursor_id = g_timeout_add(options.hide_cursor * 1000, - timer_hide_cursor, c); + timer_hide_cursor_id = g_timeout_add_seconds(options.hide_cursor, + timer_hide_cursor, c); return FALSE; } @@ -444,11 +335,12 @@ screen_queue_open(struct mpdclient *c) 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); + timer_hide_cursor_id = g_timeout_add_seconds(options.hide_cursor, + timer_hide_cursor, c); } screen_queue_restore_selection(); + screen_queue_song_change(c->status); } static void @@ -466,7 +358,7 @@ screen_queue_close(void) } static void -screen_queue_resize(int cols, int rows) +screen_queue_resize(unsigned cols, unsigned rows) { list_window_resize(lw, cols, rows); } @@ -482,35 +374,31 @@ static const char * screen_queue_title(char *str, size_t size) { if (options.host == NULL) - return _("Playlist"); + return _("Queue"); - g_snprintf(str, size, _("Playlist on %s"), options.host); + g_snprintf(str, size, _("Queue on %s"), options.host); return str; } static void screen_queue_paint_callback(WINDOW *w, unsigned i, unsigned y, unsigned width, - bool selected, G_GNUC_UNUSED void *data) + bool selected, gcc_unused const void *data) { - const struct mpd_song *song; - struct hscroll *row_hscroll; - assert(playlist != NULL); assert(i < playlist_length(playlist)); - song = playlist_get(playlist, i); + const struct mpd_song *song = playlist_get(playlist, i); -#ifdef NCMPC_MINI - row_hscroll = NULL; -#else + struct hscroll *row_hscroll = NULL; +#ifndef NCMPC_MINI row_hscroll = selected && options.scroll && lw->selected == i ? &hscroll : NULL; #endif paint_song_row(w, y, width, selected, (int)mpd_song_get_id(song) == current_song_id, - song, row_hscroll); + song, row_hscroll, options.list_format); } static void @@ -524,50 +412,33 @@ screen_queue_paint(void) list_window_paint2(lw, screen_queue_paint_callback, NULL); } -G_GNUC_PURE -static int -get_current_song_id(const struct mpd_status *status) -{ - return status != NULL && - (mpd_status_get_state(status) == MPD_STATE_PLAY || - mpd_status_get_state(status) == MPD_STATE_PAUSE) - ? (int)mpd_status_get_song_id(status) - : -1; -} - static void screen_queue_update(struct mpdclient *c) { - if (c->events & MPD_IDLE_PLAYLIST) + if (c->events & MPD_IDLE_QUEUE) screen_queue_restore_selection(); + else + /* the queue size may have changed, even if we havn't + received the QUEUE idle event yet */ + list_window_set_length(lw, playlist_length(playlist)); - if ((c->events & MPD_IDLE_PLAYER) != 0 && - get_current_song_id(c->status) != current_song_id) { - current_song_id = get_current_song_id(c->status); - - /* center the cursor */ - if (options.auto_center && current_song_id != -1 && ! lw->range_selection) - center_playing_item(c, false); - - screen_queue_repaint(); - } else if (c->events & MPD_IDLE_PLAYLIST) { - /* the playlist has changed, we must paint the new - version */ - screen_queue_repaint(); - } + if (((c->events & MPD_IDLE_PLAYER) != 0 && + screen_queue_song_change(c->status)) || + c->events & MPD_IDLE_QUEUE) + /* the queue or the current song has changed, we must + paint the new version */ + screen_queue_paint(); } #ifdef HAVE_GETMOUSE static bool handle_mouse_event(struct mpdclient *c) { - int row; unsigned long bstate; - unsigned old_selected; - + int row; if (screen_get_mouse_event(c, &bstate, &row) || list_window_mouse(lw, bstate, row)) { - screen_queue_repaint(); + screen_queue_paint(); return true; } @@ -577,7 +448,7 @@ handle_mouse_event(struct mpdclient *c) return true; } - old_selected = lw->selected; + const unsigned old_selected = lw->selected; list_window_set_cursor(lw, lw->start + row); if (bstate & BUTTON1_CLICKED) { @@ -601,7 +472,7 @@ handle_mouse_event(struct mpdclient *c) } screen_queue_save_selection(); - screen_queue_repaint(); + screen_queue_paint(); return true; } @@ -612,10 +483,8 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) { struct mpd_connection *connection; static command_t cached_cmd = CMD_NONE; - command_t prev_cmd = cached_cmd; - struct list_window_range range; - const struct mpd_song *song; + const command_t prev_cmd = cached_cmd; cached_cmd = cmd; lw->hide_cursor = false; @@ -623,26 +492,26 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) 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); + timer_hide_cursor_id = g_timeout_add_seconds(options.hide_cursor, + timer_hide_cursor, c); } if (list_window_cmd(lw, cmd)) { screen_queue_save_selection(); - screen_queue_repaint(); + screen_queue_paint(); return true; } switch(cmd) { case CMD_SCREEN_UPDATE: - center_playing_item(c, prev_cmd == CMD_SCREEN_UPDATE); - screen_queue_repaint(); + center_playing_item(c->status, prev_cmd == CMD_SCREEN_UPDATE); + screen_queue_paint(); return false; case CMD_SELECT_PLAYING: list_window_set_cursor(lw, playlist_get_index(&c->playlist, c->song)); screen_queue_save_selection(); - screen_queue_repaint(); + screen_queue_paint(); return true; case CMD_LIST_FIND: @@ -651,12 +520,12 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) case CMD_LIST_RFIND_NEXT: screen_find(lw, cmd, screen_queue_lw_callback, NULL); screen_queue_save_selection(); - screen_queue_repaint(); + screen_queue_paint(); return true; case CMD_LIST_JUMP: - screen_jump(lw, screen_queue_lw_callback, NULL, NULL); + screen_jump(lw, screen_queue_lw_callback, NULL, NULL, NULL); screen_queue_save_selection(); - screen_queue_repaint(); + screen_queue_paint(); return true; #ifdef HAVE_GETMOUSE @@ -692,7 +561,10 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) break; #endif case CMD_SCREEN_SWAP: - screen_swap(c, playlist_get(&c->playlist, lw->selected)); + if (playlist_length(&c->playlist) > 0) + screen_swap(c, playlist_get(&c->playlist, lw->selected)); + else + screen_swap(c, NULL); return true; default: @@ -703,6 +575,9 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) return false; switch(cmd) { + const struct mpd_song *song; + struct list_window_range range; + case CMD_PLAY: song = screen_queue_selected_song(); if (song == NULL) @@ -732,7 +607,7 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) case CMD_SHUFFLE: list_window_get_range(lw, &range); - if (range.end < range.start + 1) + if (range.end <= range.start + 1) /* No range selection, shuffle all list. */ break; @@ -741,7 +616,7 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) return true; if (mpd_run_shuffle_range(connection, range.start, range.end)) - screen_status_message(_("Shuffled playlist")); + screen_status_message(_("Shuffled queue")); else mpdclient_handle_error(c); return true; @@ -757,6 +632,10 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) lw->selected--; lw->range_base--; + if (lw->range_selection) + list_window_scroll_to(lw, lw->range_base); + list_window_scroll_to(lw, lw->selected); + screen_queue_save_selection(); return true; @@ -771,6 +650,10 @@ screen_queue_cmd(struct mpdclient *c, command_t cmd) lw->selected++; lw->range_base++; + if (lw->range_selection) + list_window_scroll_to(lw, lw->range_base); + list_window_scroll_to(lw, lw->selected); + screen_queue_save_selection(); return true;