X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fscreen_browser.c;h=936bd1f26ac5d360c69d0c55ceab80b598c5f318;hb=d2247f1fa7e3dd2651b474a6f699abc136731ff3;hp=7658cf3cc4f0d08308f0b9ef41648378f1311d94;hpb=4e0e1a64f100879787dcb0f53f66124db9056f39;p=ncmpc.git diff --git a/src/screen_browser.c b/src/screen_browser.c index 7658cf3..936bd1f 100644 --- a/src/screen_browser.c +++ b/src/screen_browser.c @@ -1,31 +1,39 @@ /* 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 * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ + */ +#include "config.h" #include "screen_browser.h" #include "screen_file.h" +#include "screen_song.h" +#include "screen_lyrics.h" +#include "screen_status.h" +#include "screen_find.h" +#include "screen.h" #include "i18n.h" #include "options.h" #include "charset.h" #include "strfsong.h" -#include "screen_utils.h" #include "mpdclient.h" #include "filelist.h" +#include "colors.h" +#include "paint.h" +#include "song_paint.h" #include @@ -37,25 +45,24 @@ #define HIGHLIGHT (0x01) #endif -static const char playlist_format[] = "*%s*"; - #ifndef NCMPC_MINI /* sync highlight flags with playlist */ void -sync_highlights(struct mpdclient *c, struct filelist *fl) +screen_browser_sync_highlights(struct filelist *fl, + const struct mpdclient_playlist *playlist) { guint i; for (i = 0; i < filelist_length(fl); ++i) { struct filelist_entry *entry = filelist_get(fl, i); - struct mpd_entity *entity = entry->entity; + const struct mpd_entity *entity = entry->entity; if (entity != NULL && mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) { const struct mpd_song *song = mpd_entity_get_song(entity); - if (playlist_get_index_from_same_song(&c->playlist, + if (playlist_get_index_from_same_song(playlist, song) >= 0) entry->flags |= HIGHLIGHT; else @@ -67,36 +74,30 @@ sync_highlights(struct mpdclient *c, struct filelist *fl) #endif /* list_window callback */ -const char * -browser_lw_callback(unsigned idx, bool *highlight, G_GNUC_UNUSED char **second_column, void *data) +static const char * +browser_lw_callback(unsigned idx, void *data) { - struct filelist *fl = (struct filelist *) data; + const struct filelist *fl = (const struct filelist *) data; static char buf[BUFSIZE]; - struct filelist_entry *entry; - struct mpd_entity *entity; + const struct filelist_entry *entry; + const struct mpd_entity *entity; - if (fl == NULL || idx >= filelist_length(fl)) - return NULL; + assert(fl != NULL); + assert(idx < filelist_length(fl)); entry = filelist_get(fl, idx); assert(entry != NULL); entity = entry->entity; -#ifndef NCMPC_MINI - *highlight = (entry->flags & HIGHLIGHT) != 0; -#else - *highlight = false; -#endif if( entity == NULL ) - return "[..]"; + return ".."; if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_DIRECTORY) { const struct mpd_directory *dir = mpd_entity_get_directory(entity); char *directory = utf8_to_locale(g_basename(mpd_directory_get_path(dir))); - - g_snprintf(buf, BUFSIZE, "[%s]", directory); + g_strlcpy(buf, directory, sizeof(buf)); g_free(directory); return buf; } else if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) { @@ -109,7 +110,7 @@ browser_lw_callback(unsigned idx, bool *highlight, G_GNUC_UNUSED char **second_c mpd_entity_get_playlist(entity); char *filename = utf8_to_locale(g_basename(mpd_playlist_get_path(playlist))); - g_snprintf(buf, BUFSIZE, playlist_format, filename); + g_strlcpy(buf, filename, sizeof(buf)); g_free(filename); return buf; } @@ -120,18 +121,31 @@ browser_lw_callback(unsigned idx, bool *highlight, G_GNUC_UNUSED char **second_c static bool load_playlist(struct mpdclient *c, const struct mpd_playlist *playlist) { - char *filename = utf8_to_locale(mpd_playlist_get_path(playlist)); + struct mpd_connection *connection = mpdclient_get_connection(c); + + if (connection == NULL) + return false; - if (mpdclient_cmd_load_playlist(c, mpd_playlist_get_path(playlist)) == 0) + if (mpd_run_load(connection, mpd_playlist_get_path(playlist))) { + char *filename = utf8_to_locale(mpd_playlist_get_path(playlist)); screen_status_printf(_("Loading playlist %s..."), g_basename(filename)); - g_free(filename); + g_free(filename); + + c->events |= MPD_IDLE_QUEUE; + } else + mpdclient_handle_error(c); + return true; } static bool enqueue_and_play(struct mpdclient *c, struct filelist_entry *entry) { + struct mpd_connection *connection = mpdclient_get_connection(c); + if (connection == NULL) + return false; + const struct mpd_song *song = mpd_entity_get_song(entry->entity); int id; @@ -145,7 +159,7 @@ enqueue_and_play(struct mpdclient *c, struct filelist_entry *entry) if (id < 0) { char buf[BUFSIZE]; - id = mpd_run_add_id(c->connection, mpd_song_get_uri(song)); + id = mpd_run_add_id(connection, mpd_song_get_uri(song)); if (id < 0) { mpdclient_handle_error(c); return false; @@ -155,10 +169,10 @@ enqueue_and_play(struct mpdclient *c, struct filelist_entry *entry) entry->flags |= HIGHLIGHT; #endif strfsong(buf, BUFSIZE, options.list_format, song); - screen_status_printf(_("Adding \'%s\' to playlist"), buf); + screen_status_printf(_("Adding \'%s\' to queue"), buf); } - if (!mpd_run_play_id(c->connection, id)) { + if (!mpd_run_play_id(connection, id)) { mpdclient_handle_error(c); return false; } @@ -169,12 +183,17 @@ enqueue_and_play(struct mpdclient *c, struct filelist_entry *entry) struct filelist_entry * browser_get_selected_entry(const struct screen_browser *browser) { + struct list_window_range range; + + list_window_get_range(browser->lw, &range); + if (browser->filelist == NULL || - browser->lw->selected_start < browser->lw->selected_end || - browser->lw->selected >= filelist_length(browser->filelist)) + range.end <= range.start || + range.end > range.start + 1 || + range.start >= filelist_length(browser->filelist)) return NULL; - return filelist_get(browser->filelist, browser->lw->selected); + return filelist_get(browser->filelist, range.start); } static const struct mpd_entity * @@ -242,10 +261,10 @@ browser_select_entry(struct mpdclient *c, struct filelist_entry *entry, const struct mpd_directory *dir = mpd_entity_get_directory(entry->entity); - if (mpdclient_cmd_add_path(c, mpd_directory_get_path(dir)) == 0) { + if (mpdclient_cmd_add_path(c, mpd_directory_get_path(dir))) { char *tmp = utf8_to_locale(mpd_directory_get_path(dir)); - screen_status_printf(_("Adding \'%s\' to playlist"), tmp); + screen_status_printf(_("Adding \'%s\' to queue"), tmp); g_free(tmp); } @@ -266,11 +285,11 @@ browser_select_entry(struct mpdclient *c, struct filelist_entry *entry, entry->flags |= HIGHLIGHT; #endif - if (mpdclient_cmd_add(c, song) == 0) { + if (mpdclient_cmd_add(c, song)) { char buf[BUFSIZE]; strfsong(buf, BUFSIZE, options.list_format, song); - screen_status_printf(_("Adding \'%s\' to playlist"), buf); + screen_status_printf(_("Adding \'%s\' to queue"), buf); } #ifndef NCMPC_MINI } else { @@ -293,49 +312,38 @@ browser_select_entry(struct mpdclient *c, struct filelist_entry *entry, static bool browser_handle_select(struct screen_browser *browser, struct mpdclient *c) { + struct list_window_range range; struct filelist_entry *entry; + bool success = false; - if (browser->lw->range_selection) { - for (unsigned i = browser->lw->selected_start; - i <= browser->lw->selected_end; i++) { - entry = browser_get_index(browser, i); - - if (entry != NULL && entry->entity != NULL) - browser_select_entry(c, entry, TRUE); - } - return false; - } else { - entry = browser_get_selected_entry(browser); - - if (entry == NULL || entry->entity == NULL) - return false; + list_window_get_range(browser->lw, &range); + for (unsigned i = range.start; i < range.end; ++i) { + entry = browser_get_index(browser, i); - return browser_select_entry(c, entry, TRUE); + if (entry != NULL && entry->entity != NULL) + success = browser_select_entry(c, entry, TRUE); } + + return range.end == range.start + 1 && success; } static bool browser_handle_add(struct screen_browser *browser, struct mpdclient *c) { + struct list_window_range range; struct filelist_entry *entry; + bool success = false; - if (browser->lw->range_selection) { - for (unsigned i = browser->lw->selected_start; - i <= browser->lw->selected_end; i++) { - entry = browser_get_index(browser, i); - - if (entry != NULL && entry->entity != NULL) - browser_select_entry(c, entry, FALSE); - } - return false; - } else { - entry = browser_get_selected_entry(browser); - - if (entry == NULL || entry->entity == NULL) - return false; + list_window_get_range(browser->lw, &range); + for (unsigned i = range.start; i < range.end; ++i) { + entry = browser_get_index(browser, i); - return browser_select_entry(c, entry, FALSE); + if (entry != NULL && entry->entity != NULL) + success = browser_select_entry(c, entry, FALSE) || + success; } + + return range.end == range.start + 1 && success; } static void @@ -361,19 +369,12 @@ browser_handle_mouse_event(struct screen_browser *browser, struct mpdclient *c) int row; unsigned prev_selected = browser->lw->selected; unsigned long bstate; - int length; - - if (browser->filelist) - length = filelist_length(browser->filelist); - else - length = 0; if (screen_get_mouse_event(c, &bstate, &row) || - list_window_mouse(browser->lw, length, bstate, row)) + list_window_mouse(browser->lw, bstate, row)) return 1; - browser->lw->selected = browser->lw->start + row; - list_window_check_selected(browser->lw, length); + list_window_set_cursor(browser->lw, browser->lw->start + row); if( bstate & BUTTON1_CLICKED ) { if (prev_selected == browser->lw->selected) @@ -387,6 +388,10 @@ browser_handle_mouse_event(struct screen_browser *browser, struct mpdclient *c) } #endif +static void +screen_browser_paint_callback(WINDOW *w, unsigned i, unsigned y, + unsigned width, bool selected, void *data); + bool browser_cmd(struct screen_browser *browser, struct mpdclient *c, command_t cmd) @@ -396,41 +401,20 @@ browser_cmd(struct screen_browser *browser, if (browser->filelist == NULL) return false; - switch (cmd) { - case CMD_PLAY: - browser_handle_enter(browser, c); - return true; - - case CMD_SELECT: - if (browser_handle_select(browser, c)) - /* continue and select next item... */ - cmd = CMD_LIST_NEXT; - - /* call list_window_cmd to go to the next item */ - break; - - case CMD_ADD: - if (browser_handle_add(browser, c)) - /* continue and select next item... */ - cmd = CMD_LIST_NEXT; - - /* call list_window_cmd to go to the next item */ - break; - - case CMD_SELECT_ALL: - browser_handle_select_all(browser, c); + if (list_window_cmd(browser->lw, cmd)) return true; + switch (cmd) { case CMD_LIST_FIND: case CMD_LIST_RFIND: case CMD_LIST_FIND_NEXT: case CMD_LIST_RFIND_NEXT: - screen_find(browser->lw, filelist_length(browser->filelist), - cmd, browser_lw_callback, + screen_find(browser->lw, cmd, browser_lw_callback, browser->filelist); return true; case CMD_LIST_JUMP: - screen_jump(browser->lw, browser_lw_callback, browser->filelist); + screen_jump(browser->lw, browser_lw_callback, + screen_browser_paint_callback, browser->filelist); return true; #ifdef HAVE_GETMOUSE @@ -449,14 +433,6 @@ browser_cmd(struct screen_browser *browser, return true; #endif - case CMD_LOCATE: - song = browser_get_selected_song(browser); - if (song == NULL) - return false; - - screen_file_goto_song(c, song); - return true; - #ifdef ENABLE_LYRICS_SCREEN case CMD_SCREEN_LYRICS: song = browser_get_selected_song(browser); @@ -474,9 +450,124 @@ browser_cmd(struct screen_browser *browser, break; } - if (list_window_cmd(browser->lw, filelist_length(browser->filelist), - cmd)) + if (!mpdclient_is_connected(c)) + return false; + + switch (cmd) { + case CMD_PLAY: + browser_handle_enter(browser, c); return true; + case CMD_SELECT: + if (browser_handle_select(browser, c)) + list_window_cmd(browser->lw, CMD_LIST_NEXT); + return true; + + case CMD_ADD: + if (browser_handle_add(browser, c)) + list_window_cmd(browser->lw, CMD_LIST_NEXT); + return true; + + case CMD_SELECT_ALL: + browser_handle_select_all(browser, c); + return true; + + case CMD_LOCATE: + song = browser_get_selected_song(browser); + if (song == NULL) + return false; + + screen_file_goto_song(c, song); + return true; + + default: + break; + } + return false; } + +void +screen_browser_paint_directory(WINDOW *w, unsigned width, + bool selected, const char *name) +{ + row_color(w, COLOR_DIRECTORY, selected); + + waddch(w, '['); + waddstr(w, name); + waddch(w, ']'); + + /* erase the unused space after the text */ + row_clear_to_eol(w, width, selected); +} + +static void +screen_browser_paint_playlist(WINDOW *w, unsigned width, + bool selected, const char *name) +{ + row_paint_text(w, width, COLOR_PLAYLIST, selected, name); +} + +static void +screen_browser_paint_callback(WINDOW *w, unsigned i, + unsigned y, unsigned width, + bool selected, void *data) +{ + const struct filelist *fl = (const struct filelist *) data; + const struct filelist_entry *entry; + const struct mpd_entity *entity; + bool highlight; + const struct mpd_directory *directory; + const struct mpd_playlist *playlist; + char *p; + + assert(fl != NULL); + assert(i < filelist_length(fl)); + + entry = filelist_get(fl, i); + assert(entry != NULL); + + entity = entry->entity; + if (entity == NULL) { + screen_browser_paint_directory(w, width, selected, ".."); + return; + } + +#ifndef NCMPC_MINI + highlight = (entry->flags & HIGHLIGHT) != 0; +#else + highlight = false; +#endif + + switch (mpd_entity_get_type(entity)) { + case MPD_ENTITY_TYPE_DIRECTORY: + directory = mpd_entity_get_directory(entity); + p = utf8_to_locale(g_basename(mpd_directory_get_path(directory))); + screen_browser_paint_directory(w, width, selected, p); + g_free(p); + break; + + case MPD_ENTITY_TYPE_SONG: + paint_song_row(w, y, width, selected, highlight, + mpd_entity_get_song(entity), NULL); + break; + + case MPD_ENTITY_TYPE_PLAYLIST: + playlist = mpd_entity_get_playlist(entity); + p = utf8_to_locale(g_basename(mpd_playlist_get_path(playlist))); + screen_browser_paint_playlist(w, width, selected, p); + g_free(p); + break; + + default: + row_paint_text(w, width, highlight ? COLOR_LIST_BOLD : COLOR_LIST, + selected, ""); + } +} + +void +screen_browser_paint(const struct screen_browser *browser) +{ + list_window_paint2(browser->lw, screen_browser_paint_callback, + browser->filelist); +}