diff --git a/src/screen_queue.c b/src/screen_queue.c
index 750e9409372643526037c973c93a7c783353d3e1..9b67592356bd89796d9922e47cbcddc81dfbaa83 100644 (file)
--- a/src/screen_queue.c
+++ b/src/screen_queue.c
/* ncmpc (Ncurses MPD Client)
- * (c) 2004-2009 The Music Player Daemon Project
+ * (c) 2004-2010 The Music Player Daemon Project
* Project homepage: http://musicpd.org
*
* This program is free software; you can redistribute it and/or modify
#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 "config.h"
#include "i18n.h"
#include "utils.h"
#include "strfsong.h"
#include "wreadln.h"
-#include "colors.h"
+#include "song_paint.h"
#include "screen.h"
#include "screen_utils.h"
#include "screen_song.h"
} completion_callback_data_t;
static struct hscroll hscroll;
-static guint scroll_source_id;
#endif
static struct mpdclient_playlist *playlist;
screen_queue_save_selection();
}
-#ifndef NCMPC_MINI
-static gboolean
-scroll_timer_callback(G_GNUC_UNUSED gpointer data)
-{
- scroll_source_id = 0;
-
- hscroll_step(&hscroll);
- screen_queue_repaint();
- return false;
-}
-#endif
-
static const char *
-screen_queue_lw_callback(unsigned idx, bool *highlight, char **second_column,
- G_GNUC_UNUSED void *data)
+screen_queue_lw_callback(unsigned idx, G_GNUC_UNUSED void *data)
{
static char songname[MAX_SONG_LENGTH];
struct mpd_song *song;
assert(idx < playlist_length(playlist));
song = playlist_get(playlist, idx);
- if ((int)mpd_song_get_id(song) == current_song_id)
- *highlight = true;
strfsong(songname, MAX_SONG_LENGTH, options.list_format, song);
-#ifndef NCMPC_MINI
- if (second_column != NULL && mpd_song_get_duration(song) > 0) {
- char duration[32];
- format_duration_short(duration, sizeof(duration),
- mpd_song_get_duration(song));
- *second_column = g_strdup(duration);
- }
-
- if (idx == lw->selected)
- {
- int second_column_len = 0;
- if (second_column != NULL && *second_column != NULL)
- second_column_len = strlen(*second_column);
- if (options.scroll && utf8_width(songname) > (unsigned)(COLS - second_column_len - 1) )
- {
- static unsigned current_song;
- char *tmp;
-
- if (current_song != lw->selected) {
- hscroll_reset(&hscroll);
- current_song = lw->selected;
- }
-
- tmp = strscroll(&hscroll, songname, options.scroll_sep,
- MAX_SONG_LENGTH);
- g_strlcpy(songname, tmp, MAX_SONG_LENGTH);
- g_free(tmp);
-
- if (scroll_source_id == 0)
- scroll_source_id =
- g_timeout_add(1000,
- scroll_timer_callback,
- NULL);
- } else {
- hscroll_reset(&hscroll);
-
- if (scroll_source_id != 0) {
- g_source_remove(scroll_source_id);
- scroll_source_id = 0;
- }
- }
- }
-#else
- (void)second_column;
-#endif
-
return songname;
}
static void
-center_playing_item(struct mpdclient *c, bool center_cursor)
+center_playing_item(const struct mpd_status *status, bool center_cursor)
{
- const struct mpd_song *song;
- unsigned length = c->playlist.list->len;
int idx;
- song = mpdclient_get_current_song(c);
- if (song == NULL)
+ 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);
+ 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) {
list_window_fetch_cursor(lw);
}
+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 bool
+screen_queue_song_change(const struct mpd_status *status)
+{
+ 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;
+}
+
#ifndef NCMPC_MINI
static void
save_pre_completion_cb(GCompletion *gcmp, G_GNUC_UNUSED gchar *line,
filename=g_strstrip(filename);
} else
#endif
- filename=g_strdup(name);
+ filename=g_strdup(name);
if (filename == NULL)
return -1;
/* send save command to mpd */
- filename_utf8 = locale_to_utf8(filename);
-
connection = mpdclient_get_connection(c);
+ if (connection == NULL) {
+ g_free(filename);
+ 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;
+ bool replace;
buf = g_strdup_printf(_("Replace %s [%s/%s] ? "),
filename, YES, NO);
- key = tolower(screen_getch(buf));
+ replace = screen_get_yesno(buf, false);
g_free(buf);
- if (key != YES[0]) {
+ if (!replace) {
g_free(filename_utf8);
g_free(filename);
screen_status_printf(_("Aborted"));
handle_add_to_playlist(struct mpdclient *c)
{
gchar *path;
-#ifndef NCMPC_MINI
GCompletion *gcmp;
+#ifndef NCMPC_MINI
GList *list = NULL;
GList *dir_list = NULL;
completion_callback_data_t data;
wrln_completion_callback_data = &data;
wrln_pre_completion_callback = add_pre_completion_cb;
wrln_post_completion_callback = add_post_completion_cb;
+#else
+ gcmp = NULL;
#endif
/* get path */
path = screen_readln(_("Add"),
NULL,
NULL,
-#ifdef NCMPC_MINI
- NULL
-#else
- gcmp
-#endif
- );
+ gcmp);
/* destroy completion data */
#ifndef NCMPC_MINI
screen_queue_init(WINDOW *w, int cols, int rows)
{
lw = list_window_init(w, cols, rows);
+
+#ifndef NCMPC_MINI
+ if (options.scroll)
+ hscroll_init(&hscroll, w, options.scroll_sep);
+#endif
}
static gboolean
}
screen_queue_restore_selection();
+ screen_queue_song_change(c->status);
}
static void
g_source_remove(timer_hide_cursor_id);
timer_hide_cursor_id = 0;
}
+
+#ifndef NCMPC_MINI
+ if (options.scroll)
+ hscroll_clear(&hscroll);
+#endif
}
static void
}
static void
-screen_queue_paint(void)
+screen_queue_paint_callback(WINDOW *w, unsigned i,
+ unsigned y, unsigned width,
+ bool selected, G_GNUC_UNUSED void *data)
{
- list_window_paint(lw, screen_queue_lw_callback, NULL);
+ const struct mpd_song *song;
+ struct hscroll *row_hscroll;
+
+ assert(playlist != NULL);
+ assert(i < playlist_length(playlist));
+
+ song = playlist_get(playlist, i);
+
+#ifdef NCMPC_MINI
+ row_hscroll = NULL;
+#else
+ 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);
}
-G_GNUC_PURE
-static int
-get_current_song_id(const struct mpd_status *status)
+static void
+screen_queue_paint(void)
{
- 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;
+#ifndef NCMPC_MINI
+ if (options.scroll)
+ hscroll_clear(&hscroll);
+#endif
+
+ list_window_paint2(lw, screen_queue_paint_callback, NULL);
}
static void
screen_queue_update(struct mpdclient *c)
{
- if (c->events & MPD_IDLE_PLAYLIST)
+ if (c->events & MPD_IDLE_QUEUE)
screen_queue_restore_selection();
-
- 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 */
+ 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 &&
+ 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_repaint();
- }
}
#ifdef HAVE_GETMOUSE
handle_mouse_event(struct mpdclient *c)
{
int row;
- unsigned selected;
unsigned long bstate;
+ unsigned old_selected;
if (screen_get_mouse_event(c, &bstate, &row) ||
list_window_mouse(lw, bstate, row)) {
return true;
}
- selected = lw->start + row;
+ old_selected = lw->selected;
+ list_window_set_cursor(lw, lw->start + row);
if (bstate & BUTTON1_CLICKED) {
/* play */
- if (lw->start + row < playlist_length(playlist))
- mpdclient_cmd_play(c, lw->start + row);
+ const struct mpd_song *song = screen_queue_selected_song();
+ if (song != NULL) {
+ struct mpd_connection *connection =
+ mpdclient_get_connection(c);
+
+ if (connection != NULL &&
+ !mpd_run_play_id(connection,
+ mpd_song_get_id(song)))
+ mpdclient_handle_error(c);
+ }
} else if (bstate & BUTTON3_CLICKED) {
/* delete */
- if (selected == lw->selected)
+ if (lw->selected == old_selected)
mpdclient_cmd_delete(c, lw->selected);
+
+ list_window_set_length(lw, playlist_length(playlist));
}
- list_window_set_cursor(lw, selected);
screen_queue_save_selection();
screen_queue_repaint();
static command_t cached_cmd = CMD_NONE;
command_t prev_cmd = cached_cmd;
struct list_window_range range;
+ const struct mpd_song *song;
cached_cmd = cmd;
switch(cmd) {
case CMD_SCREEN_UPDATE:
- center_playing_item(c, prev_cmd == CMD_SCREEN_UPDATE);
+ center_playing_item(c->status, prev_cmd == CMD_SCREEN_UPDATE);
screen_queue_repaint();
return false;
case CMD_SELECT_PLAYING:
switch(cmd) {
case CMD_PLAY:
- mpdclient_cmd_play(c, lw->selected);
+ song = screen_queue_selected_song();
+ if (song == NULL)
+ return false;
+
+ connection = mpdclient_get_connection(c);
+ if (connection != NULL &&
+ !mpd_run_play_id(connection, mpd_song_get_id(song)))
+ mpdclient_handle_error(c);
+
return true;
case CMD_DELETE:
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;
connection = mpdclient_get_connection(c);
+ if (connection == NULL)
+ return true;
+
if (mpd_run_shuffle_range(connection, range.start, range.end))
screen_status_message(_("Shuffled playlist"));
else
if (range.start == 0 || range.end <= range.start)
return false;
- for (unsigned i = range.start; i < range.end; ++i)
- mpdclient_cmd_move(c, i, i - 1);
+ if (!mpdclient_cmd_move(c, range.end - 1, range.start - 1))
+ return true;
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;
if (range.end >= playlist_length(&c->playlist))
return false;
- for (int i = range.end - 1; i >= (int)range.start; --i)
- mpdclient_cmd_move(c, i, i + 1);
+ if (!mpdclient_cmd_move(c, range.start, range.end))
+ return true;
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;