diff --git a/NEWS b/NEWS index 14f1b257..69ac8048 100644 --- a/NEWS +++ b/NEWS @@ -5,10 +5,14 @@ ncmpcpp-0.7 (????-??-??) * It is now possible to abort the current action using Ctrl-C or Ctrl-G in prompt mode. As a result, empty value is no longer a special value that aborts most of the actions. * Directories and playlists in browser can now be sorted by modification time. -ncmpcpp-0.6.1 (????-??-??) +ncmpcpp-0.6.1 (2014-11-06) * Comment tag is now properly written to mp3 files. * Only ID3v2.4 tags are now saved to mp3 files. +* Mouse scrolling with newer ncurses API now works properly. +* Adding songs from an album in media library now works properly with fetch delay. +* Adding songs from a playlist in playlist editor now works properly with fetch delay. +* Trying to fetch lyrics from an empty list doesn't crash the application anymore. ncmpcpp-0.6 (2014-10-25) diff --git a/src/actions.cpp b/src/actions.cpp index 5137a395..8d780eb6 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -326,15 +326,19 @@ void MouseEvent::run() m_old_mouse_event = m_mouse_event; getmouse(&m_mouse_event); + +# if NCURSES_MOUSE_VERSION == 1 // workaround shitty ncurses behavior introduced in >=5.8, when we mysteriously get // a few times after ncmpcpp startup 2^27 code instead of BUTTON{1,3}_RELEASED. since that // 2^27 thing shows constantly instead of BUTTON2_PRESSED, it was redefined to be recognized - // as BUTTON2_PRESSED. but clearly we don't want to trigger behavior bound to BUTTON2 + // as BUTTON5_PRESSED. but clearly we don't want to trigger behavior bound to BUTTON5 // after BUTTON{1,3} was pressed. so, here is the workaround: if last event was BUTTON{1,3}_PRESSED, - // we MUST get BUTTON{1,3}_RELEASED afterwards. if we get BUTTON2_PRESSED, erroneus behavior + // we MUST get BUTTON{1,3}_RELEASED afterwards. if we get BUTTON5_PRESSED, erroneus behavior // is about to occur and we need to prevent that. - if (m_old_mouse_event.bstate & (BUTTON1_PRESSED | BUTTON3_PRESSED) && m_mouse_event.bstate & BUTTON2_PRESSED) + if (m_old_mouse_event.bstate & (BUTTON1_PRESSED | BUTTON3_PRESSED) && m_mouse_event.bstate & BUTTON5_PRESSED) return; +# endif // NCURSES_MOUSE_VERSION == 1 + if (m_mouse_event.bstate & BUTTON1_PRESSED && m_mouse_event.y == LINES-(Config.statusbar_visibility ? 2 : 1) ) // progressbar @@ -353,17 +357,17 @@ void MouseEvent::run() { Mpd.Toggle(); } - else if ((m_mouse_event.bstate & BUTTON2_PRESSED || m_mouse_event.bstate & BUTTON4_PRESSED) + else if ((m_mouse_event.bstate & BUTTON5_PRESSED || m_mouse_event.bstate & BUTTON4_PRESSED) && (Config.header_visibility || Config.design == Design::Alternative) && m_mouse_event.y == 0 && size_t(m_mouse_event.x) > COLS-VolumeState.length() ) // volume { - if (m_mouse_event.bstate & BUTTON2_PRESSED) + if (m_mouse_event.bstate & BUTTON5_PRESSED) get(Type::VolumeDown).execute(); else get(Type::VolumeUp).execute(); } - else if (m_mouse_event.bstate & (BUTTON1_PRESSED | BUTTON2_PRESSED | BUTTON3_PRESSED | BUTTON4_PRESSED)) + else if (m_mouse_event.bstate & (BUTTON1_PRESSED | BUTTON3_PRESSED | BUTTON4_PRESSED | BUTTON5_PRESSED)) myScreen->mouseButtonPressed(m_mouse_event); } diff --git a/src/actions.h b/src/actions.h index 01e63652..d36b12d1 100644 --- a/src/actions.h +++ b/src/actions.h @@ -122,7 +122,11 @@ protected: struct MouseEvent : public BaseAction { - MouseEvent() : BaseAction(Type::MouseEvent, "mouse_event") { } + MouseEvent() : BaseAction(Type::MouseEvent, "mouse_event") + { + m_old_mouse_event.bstate = 0; + m_mouse_event.bstate = 0; + } protected: virtual bool canBeRun() const; diff --git a/src/helpers.h b/src/helpers.h index 2ea385ce..98db9510 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -87,7 +87,7 @@ inline MPD::Song *currentSong(BaseScreen *screen) { MPD::Song *ptr = 0; auto pl = proxySongList(screen); - if (pl) + if (pl && !pl.empty()) ptr = pl.currentSong(); return ptr; } diff --git a/src/lyrics.cpp b/src/lyrics.cpp index f4514a03..000c3c45 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -107,6 +107,9 @@ void Lyrics::switchTo() # endif // HAVE_CURL_CURL_H auto s = currentSong(myScreen); + if (!s) + return; + if (SetSong(*s)) { SwitchTo::execute(this); diff --git a/src/media_library.cpp b/src/media_library.cpp index c1f8d62b..0f3bc987 100644 --- a/src/media_library.cpp +++ b/src/media_library.cpp @@ -57,6 +57,18 @@ size_t itsRightColStartX; typedef MediaLibrary::AlbumEntry AlbumEntry; +MPD::SongIterator getSongsFromAlbum(const AlbumEntry &album) +{ + Mpd.StartSearch(true); + Mpd.AddSearch(Config.media_lib_primary_tag, album.entry().tag()); + if (!album.isAllTracksEntry()) + { + Mpd.AddSearch(MPD_TAG_ALBUM, album.entry().album()); + Mpd.AddSearch(MPD_TAG_DATE, album.entry().date()); + } + return Mpd.CommitSearchSongs(); +} + std::string AlbumToString(const AlbumEntry &ae); std::string SongToString(const MPD::Song &s); @@ -707,7 +719,15 @@ std::vector MediaLibrary::getSelectedSongs() } // if no item is selected, add songs from right column if (!any_selected && !Albums.empty()) - result.insert(result.end(), Songs.beginV(), Songs.endV()); + { + size_t begin = result.size(); + std::copy( + std::make_move_iterator(getSongsFromAlbum(Albums.current()->value().entry())), + std::make_move_iterator(MPD::SongIterator()), + std::back_inserter(result) + ); + std::sort(result.begin()+begin, result.end(), SortSongs(false)); + } } else if (isActiveWindow(Songs)) { @@ -979,7 +999,11 @@ void MediaLibrary::AddToPlaylist(bool add_n_play) } else if (isActiveWindow(Albums)) { - bool success = addSongsToPlaylist(Songs.beginV(), Songs.endV(), add_n_play, -1); + std::vector list( + std::make_move_iterator(getSongsFromAlbum(Albums.current()->value())), + std::make_move_iterator(MPD::SongIterator()) + ); + bool success = addSongsToPlaylist(list.begin(), list.end(), add_n_play, -1); Statusbar::printf("Songs from album \"%1%\" added%2%", Albums.current()->value().entry().album(), withErrors(success) ); diff --git a/src/playlist_editor.cpp b/src/playlist_editor.cpp index 08a21671..7b341625 100644 --- a/src/playlist_editor.cpp +++ b/src/playlist_editor.cpp @@ -220,11 +220,13 @@ ProxySongList PlaylistEditor::contentProxyList() void PlaylistEditor::AddToPlaylist(bool add_n_play) { - std::vector list; - if (isActiveWindow(Playlists) && !Playlists.empty()) { - bool success = addSongsToPlaylist(Content.beginV(), Content.endV(), add_n_play, -1); + std::vector list( + std::make_move_iterator(Mpd.GetPlaylistContent(Playlists.current()->value().path())), + std::make_move_iterator(MPD::SongIterator()) + ); + bool success = addSongsToPlaylist(list.begin(), list.end(), add_n_play, -1); Statusbar::printf("Playlist \"%1%\" loaded%2%", Playlists.current()->value().path(), withErrors(success) ); @@ -414,8 +416,14 @@ std::vector PlaylistEditor::getSelectedSongs() } } // if no item is selected, add songs from right column - if (!any_selected && !Content.empty()) - std::copy(Content.beginV(), Content.endV(), std::back_inserter(result)); + if (!any_selected && !Playlists.empty()) + { + std::copy( + std::make_move_iterator(Mpd.GetPlaylistContent(Playlists.current()->value().path())), + std::make_move_iterator(MPD::SongIterator()), + std::back_inserter(result) + ); + } } else if (isActiveWindow(Content)) { diff --git a/src/screen.cpp b/src/screen.cpp index 36c82930..f370d9e8 100644 --- a/src/screen.cpp +++ b/src/screen.cpp @@ -38,7 +38,7 @@ void drawSeparator(int x) void genericMouseButtonPressed(NC::Window &w, MEVENT me) { - if (me.bstate & BUTTON2_PRESSED) + if (me.bstate & BUTTON5_PRESSED) { if (Config.mouse_list_scroll_whole_page) w.scroll(NC::Scroll::PageDown); @@ -58,7 +58,7 @@ void genericMouseButtonPressed(NC::Window &w, MEVENT me) void scrollpadMouseButtonPressed(NC::Scrollpad &w, MEVENT me) { - if (me.bstate & BUTTON2_PRESSED) + if (me.bstate & BUTTON5_PRESSED) { for (size_t i = 0; i < Config.lines_scrolled; ++i) w.scroll(NC::Scroll::Down); diff --git a/src/window.h b/src/window.h index ba40e09c..87b753b4 100644 --- a/src/window.h +++ b/src/window.h @@ -95,13 +95,12 @@ // undefine scroll macro as it collides with Window::scroll #undef scroll -#ifndef USE_PDCURSES -// NOTICE: redefine BUTTON2_PRESSED as it doesn't always work, I noticed -// that it sometimes returns 134217728 (2^27) instead of expected mask, so the -// modified define does it right but is rather experimental. -# undef BUTTON2_PRESSED -# define BUTTON2_PRESSED (NCURSES_MOUSE_MASK(2, NCURSES_BUTTON_PRESSED) | (1U << 27)) -#endif // USE_PDCURSES +#if !defined(USE_PDCURSES) && NCURSES_MOUSE_VERSION == 1 +// NOTICE: define BUTTON5_PRESSED to be BUTTON2_PRESSED with additional mask +// (I noticed that it sometimes returns 134217728 (2^27) instead of expected +// mask, so the modified define does it right. +# define BUTTON5_PRESSED (BUTTON2_PRESSED | (1U << 27)) +#endif // !defined(USE_PDCURSES) && NCURSES_MOUSE_VERSION == 1 // workaraund for win32 #ifdef WIN32