Files
ncmpcpp/src/ncmpcpp.cpp

3515 lines
104 KiB
C++

/***************************************************************************
* Copyright (C) 2008 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* 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. *
***************************************************************************/
#include <iostream>
#include "mpdpp.h"
#include "ncmpcpp.h"
#include "help.h"
#include "helpers.h"
#include "lyrics.h"
#include "search_engine.h"
#include "settings.h"
#include "song.h"
#include "status_checker.h"
#include "tag_editor.h"
#define REFRESH_MEDIA_LIBRARY_SCREEN \
mLibArtists->Display(redraw_screen); \
mvvline(main_start_y, middle_col_startx-1, 0, main_height); \
mLibAlbums->Display(redraw_screen); \
mvvline(main_start_y, right_col_startx-1, 0, main_height); \
mLibSongs->Display(redraw_screen); \
if (mLibAlbums->Empty()) \
mLibAlbums->WriteXY(0, 0, "No albums found.")
#define REFRESH_PLAYLIST_EDITOR_SCREEN \
mPlaylistList->Display(redraw_screen); \
mvvline(main_start_y, middle_col_startx-1, 0, main_height); \
mPlaylistEditor->Display(redraw_screen)
#ifdef HAVE_TAGLIB_H
# define REFRESH_TAG_EDITOR_SCREEN \
mEditorLeftCol->Display(redraw_screen); \
mvvline(main_start_y, middle_col_startx-1, 0, main_height); \
mEditorTagTypes->Display(redraw_screen); \
mvvline(main_start_y, right_col_startx-1, 0, main_height); \
mEditorTags->Display(redraw_screen)
#endif // HAVE_TAGLIB_H
ncmpcpp_config Config;
ncmpcpp_keys Key;
vector<int> vFoundPositions;
int found_pos = 0;
Window *wCurrent = 0;
Window *wPrev = 0;
Menu<Song> *mPlaylist;
Menu<Item> *mBrowser;
Menu< std::pair<string, Song> > *mSearcher;
Menu<string> *mLibArtists;
Menu<StringPair> *mLibAlbums;
Menu<Song> *mLibSongs;
#ifdef HAVE_TAGLIB_H
Menu<string> *mTagEditor;
Menu<StringPair> *mEditorAlbums;
Menu<StringPair> *mEditorDirs;
Menu<string> *mEditorTagTypes;
#endif // HAVE_TAGLIB_H
// blah, I use them in conditionals, so just let them be.
Menu<StringPair> *mEditorLeftCol = 0;
Menu<Song> *mEditorTags = 0;
Menu<string> *mPlaylistList;
Menu<Song> *mPlaylistEditor;
Scrollpad *sHelp;
Scrollpad *sLyrics;
Scrollpad *sInfo;
Window *wHeader;
Window *wFooter;
MPDConnection *Mpd;
time_t timer;
int now_playing = -1;
int playing_song_scroll_begin = 0;
int browsed_dir_scroll_begin = 0;
int stats_scroll_begin = 0;
int lock_statusbar_delay = -1;
string browsed_dir = "/";
string editor_browsed_dir = "/";
string editor_highlighted_dir;
NcmpcppScreen current_screen;
NcmpcppScreen prev_screen;
#ifdef HAVE_CURL_CURL_H
pthread_t lyrics_downloader;
pthread_t artist_info_downloader;
extern bool artist_info_ready;
extern bool lyrics_ready;
#endif
bool dont_change_now_playing = 0;
bool block_progressbar_update = 0;
bool block_statusbar_update = 0;
bool allow_statusbar_unlock = 1;
bool block_playlist_update = 0;
bool block_item_list_update = 0;
bool messages_allowed = 0;
bool redraw_screen = 0;
bool redraw_header = 1;
bool reload_lyrics = 0;
extern bool header_update_status;
extern bool search_case_sensitive;
extern bool search_match_to_pattern;
extern string EMPTY_TAG;
extern string UNKNOWN_ARTIST;
extern string UNKNOWN_TITLE;
extern string UNKNOWN_ALBUM;
extern string playlist_stats;
extern string volume_state;
const string message_part_of_songs_added = "Only part of requested songs' list added to playlist!";
int main(int argc, char *argv[])
{
CreateConfigDir();
DefaultConfiguration(Config);
DefaultKeys(Key);
ReadConfiguration(Config);
ReadKeys(Key);
DefineEmptyTags();
Mpd = new MPDConnection;
if (getenv("MPD_HOST"))
Mpd->SetHostname(getenv("MPD_HOST"));
if (getenv("MPD_PORT"))
Mpd->SetPort(atoi(getenv("MPD_PORT")));
if (getenv("MPD_PASSWORD"))
Mpd->SetPassword(getenv("MPD_PASSWORD"));
Mpd->SetTimeout(Config.mpd_connection_timeout);
if (argc > 1)
{
vector<string> args;
args.reserve(argc-1);
for (int i = 1; i < argc; i++)
args.push_back(argv[i]);
if (ParseArgv(args))
{
Mpd->Disconnect();
return 0;
}
}
if (!ConnectToMPD())
return -1;
setlocale(LC_ALL,"");
initscr();
noecho();
cbreak();
curs_set(0);
if (Config.colors_enabled)
Window::EnableColors();
int main_start_y = 2;
int main_height = LINES-4;
if (!Config.header_visibility)
{
main_start_y -= 2;
main_height += 2;
}
if (!Config.statusbar_visibility)
main_height++;
mPlaylist = new Menu<Song>(0, main_start_y, COLS, main_height, Config.columns_in_playlist ? DisplayColumns(Config.song_columns_list_format) : "", Config.main_color, brNone);
mPlaylist->AutoRefresh(0);
mPlaylist->SetTimeout(ncmpcpp_window_timeout);
mPlaylist->HighlightColor(Config.main_highlight_color);
mPlaylist->SetSelectPrefix(Config.selected_item_prefix);
mPlaylist->SetSelectSuffix(Config.selected_item_suffix);
mPlaylist->SetItemDisplayer(Config.columns_in_playlist ? DisplaySongInColumns : DisplaySong);
mPlaylist->SetItemDisplayerUserData(Config.columns_in_playlist ? &Config.song_columns_list_format : &Config.song_list_format);
mBrowser = new Menu<Item>(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
mBrowser->HighlightColor(Config.main_highlight_color);
mBrowser->SetTimeout(ncmpcpp_window_timeout);
mBrowser->SetSelectPrefix(Config.selected_item_prefix);
mBrowser->SetSelectSuffix(Config.selected_item_suffix);
mBrowser->SetItemDisplayer(DisplayItem);
mSearcher = new Menu< std::pair<string, Song> >(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
mSearcher->HighlightColor(Config.main_highlight_color);
mSearcher->SetTimeout(ncmpcpp_window_timeout);
mSearcher->SetItemDisplayer(SearchEngineDisplayer);
mSearcher->SetSelectPrefix(Config.selected_item_prefix);
mSearcher->SetSelectSuffix(Config.selected_item_suffix);
int left_col_width = COLS/3-1;
int middle_col_width = COLS/3;
int middle_col_startx = left_col_width+1;
int right_col_width = COLS-COLS/3*2-1;
int right_col_startx = left_col_width+middle_col_width+2;
mLibArtists = new Menu<string>(0, main_start_y, left_col_width, main_height, IntoStr(Config.media_lib_primary_tag) + "s", Config.main_color, brNone);
mLibArtists->HighlightColor(Config.main_highlight_color);
mLibArtists->SetTimeout(ncmpcpp_window_timeout);
mLibAlbums = new Menu<StringPair>(middle_col_startx, main_start_y, middle_col_width, main_height, "Albums", Config.main_color, brNone);
mLibAlbums->HighlightColor(Config.main_highlight_color);
mLibAlbums->SetTimeout(ncmpcpp_window_timeout);
mLibAlbums->SetItemDisplayer(DisplayStringPair);
mLibSongs = new Menu<Song>(right_col_startx, main_start_y, right_col_width, main_height, "Songs", Config.main_color, brNone);
mLibSongs->HighlightColor(Config.main_highlight_color);
mLibSongs->SetTimeout(ncmpcpp_window_timeout);
mLibSongs->SetSelectPrefix(Config.selected_item_prefix);
mLibSongs->SetSelectSuffix(Config.selected_item_suffix);
mLibSongs->SetItemDisplayer(DisplaySong);
mLibSongs->SetItemDisplayerUserData(&Config.song_library_format);
# ifdef HAVE_TAGLIB_H
mTagEditor = new Menu<string>(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
mTagEditor->HighlightColor(Config.main_highlight_color);
mTagEditor->SetTimeout(ncmpcpp_window_timeout);
mEditorAlbums = new Menu<StringPair>(0, main_start_y, left_col_width, main_height, "Albums", Config.main_color, brNone);
mEditorAlbums->HighlightColor(Config.main_highlight_color);
mEditorAlbums->SetTimeout(ncmpcpp_window_timeout);
mEditorAlbums->SetItemDisplayer(DisplayStringPair);
mEditorDirs = new Menu<StringPair>(0, main_start_y, left_col_width, main_height, "Directories", Config.main_color, brNone);
mEditorDirs->HighlightColor(Config.main_highlight_color);
mEditorDirs->SetTimeout(ncmpcpp_window_timeout);
mEditorDirs->SetItemDisplayer(DisplayStringPair);
mEditorLeftCol = Config.albums_in_tag_editor ? mEditorAlbums : mEditorDirs;
mEditorTagTypes = new Menu<string>(middle_col_startx, main_start_y, middle_col_width, main_height, "Tag types", Config.main_color, brNone);
mEditorTagTypes->HighlightColor(Config.main_highlight_color);
mEditorTagTypes->SetTimeout(ncmpcpp_window_timeout);
mEditorTags = new Menu<Song>(right_col_startx, main_start_y, right_col_width, main_height, "Tags", Config.main_color, brNone);
mEditorTags->HighlightColor(Config.main_highlight_color);
mEditorTags->SetTimeout(ncmpcpp_window_timeout);
mEditorTags->SetSelectPrefix(Config.selected_item_prefix);
mEditorTags->SetSelectSuffix(Config.selected_item_suffix);
mEditorTags->SetItemDisplayer(DisplayTag);
mEditorTags->SetItemDisplayerUserData(mEditorTagTypes);
# endif // HAVE_TAGLIB_H
mPlaylistList = new Menu<string>(0, main_start_y, left_col_width, main_height, "Playlists", Config.main_color, brNone);
mPlaylistList->HighlightColor(Config.main_highlight_color);
mPlaylistList->SetTimeout(ncmpcpp_window_timeout);
mPlaylistEditor = new Menu<Song>(middle_col_startx, main_start_y, middle_col_width+right_col_width+1, main_height, "Playlist's content", Config.main_color, brNone);
mPlaylistEditor->HighlightColor(Config.main_highlight_color);
mPlaylistEditor->SetTimeout(ncmpcpp_window_timeout);
mPlaylistEditor->SetSelectPrefix(Config.selected_item_prefix);
mPlaylistEditor->SetSelectSuffix(Config.selected_item_suffix);
mPlaylistEditor->SetItemDisplayer(DisplaySong);
mPlaylistEditor->SetItemDisplayerUserData(&Config.song_list_format);
sHelp = new Scrollpad(0, main_start_y, COLS, main_height, "", Config.main_color, brNone);
sHelp->SetTimeout(ncmpcpp_window_timeout);
sHelp->Add(GetKeybindings());
sLyrics = static_cast<Scrollpad *>(sHelp->EmptyClone());
sLyrics->SetTimeout(ncmpcpp_window_timeout);
sInfo = static_cast<Scrollpad *>(sHelp->EmptyClone());
sInfo->SetTimeout(ncmpcpp_window_timeout);
if (Config.header_visibility)
{
wHeader = new Window(0, 0, COLS, 2, "", Config.header_color, brNone);
wHeader->Display();
}
int footer_start_y = LINES-(Config.statusbar_visibility ? 2 : 1);
int footer_height = Config.statusbar_visibility ? 2 : 1;
wFooter = new Window(0, footer_start_y, COLS, footer_height, "", Config.statusbar_color, brNone);
wFooter->SetTimeout(ncmpcpp_window_timeout);
wFooter->SetGetStringHelper(TraceMpdStatus);
wFooter->Display();
wCurrent = mPlaylist;
current_screen = csPlaylist;
timer = time(NULL);
Mpd->SetStatusUpdater(NcmpcppStatusChanged, NULL);
Mpd->SetErrorHandler(NcmpcppErrorCallback, NULL);
// local variables
int input;
Song edited_song;
Song sought_pattern;
bool main_exit = 0;
bool title_allowed = 0;
string lyrics_title;
string info_title;
// local variables end
while (!main_exit)
{
if (!Mpd->Connected())
{
ShowMessage("Attempting to reconnect...");
Mpd->Disconnect();
if (Mpd->Connect())
ShowMessage("Connected!");
messages_allowed = 0;
}
TraceMpdStatus();
block_item_list_update = 0;
block_playlist_update = 0;
messages_allowed = 1;
// header stuff
const int max_allowed_title_length = wHeader->GetWidth()-volume_state.length();
if (current_screen == csBrowser && input == ERR && browsed_dir.length() > max_allowed_title_length)
redraw_header = 1;
if (Config.header_visibility && redraw_header)
{
string title;
switch (current_screen)
{
case csHelp:
title = "Help";
break;
case csPlaylist:
title = "Playlist ";
break;
case csBrowser:
title = "Browse: ";
break;
case csTinyTagEditor:
case csTagEditor:
title = "Tag editor";
break;
case csInfo:
title = info_title;
break;
case csSearcher:
title = "Search engine";
break;
case csLibrary:
title = "Media library";
break;
case csLyrics:
title = lyrics_title;
break;
case csPlaylistEditor:
title = "Playlist editor";
break;
default:
break;
}
if (title_allowed)
{
wHeader->Bold(1);
wHeader->WriteXY(0, 0, max_allowed_title_length, title, 1);
wHeader->Bold(0);
if (current_screen == csPlaylist && !playlist_stats.empty())
wHeader->WriteXY(title.length(), 0, max_allowed_title_length-title.length(), playlist_stats);
else if (current_screen == csBrowser)
{
int max_length_without_scroll = wHeader->GetWidth()-volume_state.length()-title.length();
my_string_t wbrowseddir = TO_WSTRING(browsed_dir);
wHeader->Bold(1);
if (browsed_dir.length() > max_length_without_scroll)
{
# ifdef UTF8_ENABLED
wbrowseddir += L" ** ";
# else
wbrowseddir += " ** ";
# endif
const int scrollsize = max_length_without_scroll;
my_string_t part = wbrowseddir.substr(browsed_dir_scroll_begin++, scrollsize);
if (part.length() < scrollsize)
part += wbrowseddir.substr(0, scrollsize-part.length());
wHeader->WriteXY(title.length(), 0, part);
if (browsed_dir_scroll_begin >= wbrowseddir.length())
browsed_dir_scroll_begin = 0;
}
else
wHeader->WriteXY(title.length(), 0, browsed_dir);
wHeader->Bold(0);
}
}
else
{
string screens = "[.b]1:[/b]Help [.b]2:[/b]Playlist [.b]3:[/b]Browse [.b]4:[/b]Search [.b]5:[/b]Library [.b]6:[/b]Playlist editor";
# ifdef HAVE_TAGLIB_H
screens += " [.b]7:[/b]Tag editor";
# endif // HAVE_TAGLIB_H
wHeader->WriteXY(0, 0, max_allowed_title_length, screens, 1);
}
wHeader->SetColor(Config.volume_color);
wHeader->WriteXY(max_allowed_title_length, 0, volume_state);
wHeader->SetColor(Config.header_color);
redraw_header = 0;
}
// header stuff end
// media library stuff
if (current_screen == csLibrary)
{
if (mLibArtists->Empty())
{
found_pos = 0;
vFoundPositions.clear();
TagList list;
mLibAlbums->Clear(0);
mLibSongs->Clear(0);
Mpd->GetList(list, Config.media_lib_primary_tag);
sort(list.begin(), list.end(), CaseInsensitiveSorting());
for (TagList::const_iterator it = list.begin(); it != list.end(); it++)
{
if ((mLibArtists->Empty() || mLibArtists->Back() != *it) && !it->empty())
mLibArtists->AddOption(*it);
}
mLibArtists->Window::Clear();
mLibArtists->Refresh();
}
if (!mLibArtists->Empty() && mLibAlbums->Empty() && mLibSongs->Empty())
{
mLibAlbums->Reset();
TagList list;
std::map<string, string, CaseInsensitiveSorting> maplist;
if (Config.media_lib_primary_tag == MPD_TAG_ITEM_ARTIST)
Mpd->GetAlbums(mLibArtists->GetOption(), list);
else
{
Mpd->StartSearch(1);
Mpd->AddSearch(Config.media_lib_primary_tag, mLibArtists->GetOption());
Mpd->StartFieldSearch(MPD_TAG_ITEM_ALBUM);
Mpd->CommitSearch(list);
//sort(list.begin(), list.end());
}
for (TagList::const_iterator it = list.begin(); it != list.end(); it++)
{
SongList l;
Mpd->StartSearch(1);
Mpd->AddSearch(Config.media_lib_primary_tag, mLibArtists->GetOption());
Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, *it);
Mpd->CommitSearch(l);
if (!l.empty() && l[0]->GetAlbum() != UNKNOWN_ALBUM)
maplist[DisplaySong(*l[0], &Config.media_lib_album_format)] = *it;
FreeSongList(l);
}
for (std::map<string, string>::const_iterator it = maplist.begin(); it != maplist.end(); it++)
mLibAlbums->AddOption(make_pair(it->first, it->second));
mLibAlbums->Window::Clear();
mLibAlbums->Refresh();
}
if (!mLibArtists->Empty() && wCurrent == mLibAlbums && mLibAlbums->Empty())
{
mLibAlbums->HighlightColor(Config.main_highlight_color);
mLibArtists->HighlightColor(Config.active_column_color);
wCurrent = mLibArtists;
}
if (!mLibArtists->Empty() && mLibSongs->Empty())
{
mLibSongs->Reset();
SongList list;
if (mLibAlbums->Empty())
{
mLibAlbums->WriteXY(0, 0, "No albums found.");
mLibSongs->Clear(0);
Mpd->StartSearch(1);
Mpd->AddSearch(Config.media_lib_primary_tag, mLibArtists->GetOption());
Mpd->CommitSearch(list);
}
else
{
mLibSongs->Clear(0);
Mpd->StartSearch(1);
Mpd->AddSearch(Config.media_lib_primary_tag, mLibArtists->GetOption());
Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, mLibAlbums->Current().second);
Mpd->CommitSearch(list);
}
sort(list.begin(), list.end(), SortSongsByTrack);
bool bold = 0;
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
{
for (int j = 0; j < mPlaylist->Size(); j++)
{
if ((*it)->GetHash() == mPlaylist->at(j).GetHash())
{
bold = 1;
break;
}
}
mLibSongs->AddOption(**it, bold);
bold = 0;
}
FreeSongList(list);
mLibSongs->Window::Clear();
mLibSongs->Refresh();
}
}
// media library end
else
// playlist editor stuff
if (current_screen == csPlaylistEditor)
{
if (mPlaylistList->Empty())
{
mPlaylistEditor->Clear(0);
TagList list;
Mpd->GetPlaylists(list);
for (TagList::const_iterator it = list.begin(); it != list.end(); it++)
mPlaylistList->AddOption(*it);
mPlaylistList->Window::Clear();
mPlaylistList->Refresh();
}
if (mPlaylistEditor->Empty())
{
mPlaylistEditor->Reset();
SongList list;
Mpd->GetPlaylistContent(mPlaylistList->GetOption(), list);
if (!list.empty())
mPlaylistEditor->SetTitle("Playlist's content (" + IntoStr(list.size()) + " item" + (list.size() == 1 ? ")" : "s)"));
else
mPlaylistEditor->SetTitle("Playlist's content");
bool bold = 0;
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
{
for (int j = 0; j < mPlaylist->Size(); j++)
{
if ((*it)->GetHash() == mPlaylist->at(j).GetHash())
{
bold = 1;
break;
}
}
mPlaylistEditor->AddOption(**it, bold);
bold = 0;
}
FreeSongList(list);
mPlaylistEditor->Window::Clear();
mPlaylistEditor->Display();
}
if (wCurrent == mPlaylistEditor && mPlaylistEditor->Empty())
{
mPlaylistEditor->HighlightColor(Config.main_highlight_color);
mPlaylistList->HighlightColor(Config.active_column_color);
wCurrent = mPlaylistList;
}
if (mPlaylistEditor->Empty())
mPlaylistEditor->WriteXY(0, 0, "Playlist is empty.");
}
// playlist editor end
else
# ifdef HAVE_TAGLIB_H
// album editor stuff
if (current_screen == csTagEditor)
{
if (mEditorLeftCol->Empty())
{
found_pos = 0;
vFoundPositions.clear();
mEditorLeftCol->Window::Clear();
mEditorTags->Clear();
TagList list;
if (Config.albums_in_tag_editor)
{
std::map<string, string, CaseInsensitiveSorting> maplist;
mEditorAlbums->WriteXY(0, 0, "Fetching albums' list...");
Mpd->GetAlbums("", list);
for (TagList::const_iterator it = list.begin(); it != list.end(); it++)
{
SongList l;
Mpd->StartSearch(1);
Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, *it);
Mpd->CommitSearch(l);
if (!l.empty())
maplist[DisplaySong(*l[0], &Config.tag_editor_album_format)] = *it;
FreeSongList(l);
}
for (std::map<string, string>::const_iterator it = maplist.begin(); it != maplist.end(); it++)
mEditorAlbums->AddOption(make_pair(it->first, it->second));
}
else
{
int highlightme = -1;
Mpd->GetDirectories(editor_browsed_dir, list);
sort(list.begin(), list.end(), CaseInsensitiveSorting());
if (editor_browsed_dir != "/")
{
int slash = editor_browsed_dir.find_last_of("/");
string parent = slash != string::npos ? editor_browsed_dir.substr(0, slash) : "/";
mEditorDirs->AddOption(make_pair("[..]", parent));
}
for (TagList::const_iterator it = list.begin(); it != list.end(); it++)
{
int slash = it->find_last_of("/");
string to_display = slash != string::npos ? it->substr(slash+1) : *it;
mEditorDirs->AddOption(make_pair(to_display, *it));
if (*it == editor_highlighted_dir)
highlightme = mEditorDirs->Size()-1;
}
if (highlightme != -1)
mEditorDirs->Highlight(highlightme);
}
mEditorLeftCol->Display();
mEditorTagTypes->Refresh();
}
if (mEditorTags->Empty())
{
mEditorTags->Reset();
SongList list;
if (Config.albums_in_tag_editor)
{
Mpd->StartSearch(1);
Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, mEditorAlbums->Current().second);
Mpd->CommitSearch(list);
sort(list.begin(), list.end(), CaseInsensitiveSorting());
for (SongList::iterator it = list.begin(); it != list.end(); it++)
mEditorTags->AddOption(**it);
}
else
{
Mpd->GetSongs(mEditorDirs->Current().second, list);
sort(list.begin(), list.end(), CaseInsensitiveSorting());
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
mEditorTags->AddOption(**it);
}
FreeSongList(list);
mEditorTags->Window::Clear();
mEditorTags->Refresh();
}
if (redraw_screen && wCurrent == mEditorTagTypes && mEditorTagTypes->GetChoice() < 13)
{
mEditorTags->Refresh(1);
redraw_screen = 0;
}
else if (mEditorTagTypes->GetChoice() >= 13)
mEditorTags->Window::Clear();
}
// album editor end
else
# endif // HAVE_TAGLIB_H
// lyrics stuff
if (current_screen == csLyrics && reload_lyrics)
{
const Song &s = mPlaylist->at(now_playing);
if (s.GetArtist() != UNKNOWN_ARTIST && s.GetTitle() != UNKNOWN_TITLE)
goto LOAD_LYRICS;
else
reload_lyrics = 0;
}
# ifdef HAVE_CURL_CURL_H
if (artist_info_ready)
{
void *result;
string *str_result = 0;
pthread_join(artist_info_downloader, &result);
str_result = static_cast<string *>(result);
sInfo->Add(*str_result);
delete str_result;
artist_info_downloader = 0;
artist_info_ready = 0;
}
else if (lyrics_ready)
{
void *result;
string *str_result = 0;
pthread_join(lyrics_downloader, &result);
str_result = static_cast<string *>(result);
sLyrics->Add(*str_result);
delete str_result;
lyrics_downloader = 0;
lyrics_ready = 0;
}
# endif
// lyrics end
if (Config.columns_in_playlist && wCurrent == mPlaylist)
wCurrent->Display(redraw_screen);
else
wCurrent->Refresh(redraw_screen);
redraw_screen = 0;
wCurrent->ReadKey(input);
if (input == ERR)
continue;
if (!title_allowed)
redraw_header = 1;
title_allowed = 1;
timer = time(NULL);
switch (current_screen)
{
case csPlaylist:
mPlaylist->Highlighting(1);
break;
case csLibrary:
case csPlaylistEditor:
case csTagEditor:
{
if (Keypressed(input, Key.Up) || Keypressed(input, Key.Down) || Keypressed(input, Key.PageUp) || Keypressed(input, Key.PageDown) || Keypressed(input, Key.Home) || Keypressed(input, Key.End) || Keypressed(input, Key.FindForward) || Keypressed(input, Key.FindBackward) || Keypressed(input, Key.NextFoundPosition) || Keypressed(input, Key.PrevFoundPosition))
{
if (wCurrent == mLibArtists)
{
mLibAlbums->Clear(0);
mLibSongs->Clear(0);
}
else if (wCurrent == mLibAlbums)
{
mLibSongs->Clear(0);
}
else if (wCurrent == mPlaylistList)
{
mPlaylistEditor->Clear(0);
}
# ifdef HAVE_TAGLIB_H
else if (wCurrent == mEditorLeftCol)
{
mEditorTags->Clear(0);
mEditorTagTypes->Refresh();
}
else if (wCurrent == mEditorTagTypes)
redraw_screen = 1;
# endif // HAVE_TAGLIB_H
}
}
default:
break;
}
// key mapping beginning
if (Keypressed(input, Key.Up))
{
if (!Config.fancy_scrolling && (wCurrent == mLibArtists || wCurrent == mPlaylistList || wCurrent == mEditorLeftCol))
{
wCurrent->SetTimeout(50);
while (Keypressed(input, Key.Up))
{
wCurrent->Go(wUp);
wCurrent->Refresh();
wCurrent->ReadKey(input);
}
wCurrent->SetTimeout(ncmpcpp_window_timeout);
}
else
wCurrent->Go(wUp);
}
else if (Keypressed(input, Key.Down))
{
if (!Config.fancy_scrolling && (wCurrent == mLibArtists || wCurrent == mPlaylistList || wCurrent == mEditorLeftCol))
{
wCurrent->SetTimeout(50);
while (Keypressed(input, Key.Down))
{
wCurrent->Go(wDown);
wCurrent->Refresh();
wCurrent->ReadKey(input);
}
wCurrent->SetTimeout(ncmpcpp_window_timeout);
}
else
wCurrent->Go(wDown);
}
else if (Keypressed(input, Key.PageUp))
{
wCurrent->Go(wPageUp);
}
else if (Keypressed(input, Key.PageDown))
{
wCurrent->Go(wPageDown);
}
else if (Keypressed(input, Key.Home))
{
wCurrent->Go(wHome);
}
else if (Keypressed(input, Key.End))
{
wCurrent->Go(wEnd);
}
else if (input == KEY_RESIZE)
{
redraw_screen = 1;
redraw_header = 1;
if (COLS < 20 || LINES < 5)
{
endwin();
std::cout << "Screen too small!\n";
return 1;
}
main_height = LINES-4;
if (!Config.header_visibility)
main_height += 2;
if (!Config.statusbar_visibility)
main_height++;
sHelp->Resize(COLS, main_height);
mPlaylist->Resize(COLS, main_height);
mPlaylist->SetTitle(Config.columns_in_playlist ? DisplayColumns(Config.song_columns_list_format) : "");
mBrowser->Resize(COLS, main_height);
mSearcher->Resize(COLS, main_height);
sInfo->Resize(COLS, main_height);
sLyrics->Resize(COLS, main_height);
left_col_width = COLS/3-1;
middle_col_startx = left_col_width+1;
middle_col_width = COLS/3;
right_col_startx = left_col_width+middle_col_width+2;
right_col_width = COLS-COLS/3*2-1;
mLibArtists->Resize(left_col_width, main_height);
mLibAlbums->Resize(middle_col_width, main_height);
mLibSongs->Resize(right_col_width, main_height);
mLibAlbums->MoveTo(middle_col_startx, main_start_y);
mLibSongs->MoveTo(right_col_startx, main_start_y);
# ifdef HAVE_TAGLIB_H
mTagEditor->Resize(COLS, main_height);
mEditorAlbums->Resize(left_col_width, main_height);
mEditorDirs->Resize(left_col_width, main_height);
mEditorTagTypes->Resize(middle_col_width, main_height);
mEditorTags->Resize(right_col_width, main_height);
mEditorTagTypes->MoveTo(middle_col_startx, main_start_y);
mEditorTags->MoveTo(right_col_startx, main_start_y);
mPlaylistList->Resize(left_col_width, main_height);
mPlaylistEditor->Resize(middle_col_width+right_col_width+1, main_height);
mPlaylistEditor->MoveTo(middle_col_startx, main_start_y);
# endif // HAVE_TAGLIB_H
if (Config.header_visibility)
wHeader->Resize(COLS, wHeader->GetHeight());
footer_start_y = LINES-(Config.statusbar_visibility ? 2 : 1);
wFooter->MoveTo(0, footer_start_y);
wFooter->Resize(COLS, wFooter->GetHeight());
wCurrent->Hide();
# ifdef HAVE_TAGLIB_H
if (current_screen == csLibrary)
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csTagEditor)
{
REFRESH_TAG_EDITOR_SCREEN;
}
else
# endif // HAVE_TAGLIB_H
if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
header_update_status = 1;
PlayerState mpd_state = Mpd->GetState();
MPDStatusChanges changes;
if (mpd_state == psPlay || mpd_state == psPause)
changes.ElapsedTime = 1; // restore status
else
changes.PlayerState = 1;
NcmpcppStatusChanged(Mpd, changes, NULL);
}
else if (Keypressed(input, Key.GoToParentDir))
{
if (wCurrent == mBrowser && browsed_dir != "/")
{
mBrowser->Reset();
goto GO_TO_PARENT_DIR;
}
}
else if (Keypressed(input, Key.Enter))
{
switch (current_screen)
{
case csPlaylist:
{
if (!mPlaylist->Empty())
Mpd->PlayID(mPlaylist->Current().GetID());
break;
}
case csBrowser:
{
GO_TO_PARENT_DIR:
const Item &item = mBrowser->Current();
switch (item.type)
{
case itDirectory:
{
found_pos = 0;
vFoundPositions.clear();
GetDirectory(item.name, browsed_dir);
redraw_header = 1;
break;
}
case itSong:
{
block_item_list_update = 1;
if (Config.ncmpc_like_songs_adding && mBrowser->IsBold())
{
bool found = 0;
long long hash = mBrowser->Current().song->GetHash();
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->Play(i);
found = 1;
break;
}
}
if (found)
break;
}
Song &s = *item.song;
int id = Mpd->AddSong(s);
if (id >= 0)
{
Mpd->PlayID(id);
ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format));
mBrowser->BoldOption(mBrowser->GetChoice(), 1);
}
break;
}
case itPlaylist:
{
SongList list;
Mpd->GetPlaylistContent(item.name, list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
ShowMessage("Loading and playing playlist " + item.name + "...");
Song *s = &mPlaylist->at(mPlaylist->Size()-list.size());
if (s->GetHash() == list[0]->GetHash())
Mpd->PlayID(s->GetID());
else
ShowMessage(message_part_of_songs_added);
}
FreeSongList(list);
break;
}
}
break;
}
# ifdef HAVE_TAGLIB_H
case csTinyTagEditor:
{
int option = mTagEditor->GetChoice();
LockStatusbar();
Song &s = edited_song;
switch (option-7)
{
case 1:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Title:[/b] ", 1);
if (s.GetTitle() == UNKNOWN_TITLE)
s.SetTitle(wFooter->GetString());
else
s.SetTitle(wFooter->GetString(s.GetTitle()));
mTagEditor->UpdateOption(option, "[.b]Title:[/b] " + s.GetTitle());
break;
}
case 2:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Artist:[/b] ", 1);
if (s.GetArtist() == UNKNOWN_ARTIST)
s.SetArtist(wFooter->GetString());
else
s.SetArtist(wFooter->GetString(s.GetArtist()));
mTagEditor->UpdateOption(option, "[.b]Artist:[/b] " + s.GetArtist());
break;
}
case 3:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Album:[/b] ", 1);
if (s.GetAlbum() == UNKNOWN_ALBUM)
s.SetAlbum(wFooter->GetString());
else
s.SetAlbum(wFooter->GetString(s.GetAlbum()));
mTagEditor->UpdateOption(option, "[.b]Album:[/b] " + s.GetAlbum());
break;
}
case 4:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Year:[/b] ", 1);
if (s.GetYear() == EMPTY_TAG)
s.SetYear(wFooter->GetString(4));
else
s.SetYear(wFooter->GetString(s.GetYear(), 4));
mTagEditor->UpdateOption(option, "[.b]Year:[/b] " + s.GetYear());
break;
}
case 5:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Track:[/b] ", 1);
if (s.GetTrack() == EMPTY_TAG)
s.SetTrack(wFooter->GetString(3));
else
s.SetTrack(wFooter->GetString(s.GetTrack(), 3));
mTagEditor->UpdateOption(option, "[.b]Track:[/b] " + s.GetTrack());
break;
}
case 6:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Genre:[/b] ", 1);
if (s.GetGenre() == EMPTY_TAG)
s.SetGenre(wFooter->GetString());
else
s.SetGenre(wFooter->GetString(s.GetGenre()));
mTagEditor->UpdateOption(option, "[.b]Genre:[/b] " + s.GetGenre());
break;
}
case 7:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Composer:[/b] ", 1);
if (s.GetComposer() == EMPTY_TAG)
s.SetComposer(wFooter->GetString());
else
s.SetComposer(wFooter->GetString(s.GetComposer()));
mTagEditor->UpdateOption(option, "[.b]Composer:[/b] " + s.GetComposer());
break;
}
case 8:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Performer:[/b] ", 1);
if (s.GetPerformer() == EMPTY_TAG)
s.SetPerformer(wFooter->GetString());
else
s.SetPerformer(wFooter->GetString(s.GetPerformer()));
mTagEditor->UpdateOption(option, "[.b]Performer:[/b] " + s.GetPerformer());
break;
}
case 9:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Disc:[/b] ", 1);
if (s.GetDisc() == EMPTY_TAG)
s.SetDisc(wFooter->GetString());
else
s.SetDisc(wFooter->GetString(s.GetDisc()));
mTagEditor->UpdateOption(option, "[.b]Disc:[/b] " + s.GetDisc());
break;
}
case 10:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Comment:[/b] ", 1);
if (s.GetComment() == EMPTY_TAG)
s.SetComment(wFooter->GetString());
else
s.SetComment(wFooter->GetString(s.GetComment()));
mTagEditor->UpdateOption(option, "[.b]Comment:[/b] " + s.GetComment());
break;
}
case 12:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Filename:[/b] ", 1);
string filename = s.GetNewName().empty() ? s.GetName() : s.GetNewName();
int dot = filename.find_last_of(".");
string extension = filename.substr(dot);
filename = filename.substr(0, dot);
string new_name = wFooter->GetString(filename);
s.SetNewName(new_name + extension);
mTagEditor->UpdateOption(option, "[.b]Filename:[/b] " + (s.GetNewName().empty() ? s.GetName() : s.GetNewName()));
break;
}
case 14:
{
ShowMessage("Updating tags...");
if (WriteTags(s))
{
ShowMessage("Tags updated!");
Mpd->UpdateDirectory(s.GetDirectory());
if (prev_screen == csSearcher)
mSearcher->Current().second = s;
}
ShowMessage("Error writing tags!");
}
case 15:
{
wCurrent->Clear();
wCurrent = wPrev;
current_screen = prev_screen;
redraw_screen = 1;
redraw_header = 1;
if (current_screen == csLibrary)
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
else if (current_screen == csTagEditor)
{
REFRESH_TAG_EDITOR_SCREEN;
}
break;
}
}
UnlockStatusbar();
break;
}
# endif // HAVE_TAGLIB_H
case csSearcher:
{
ENTER_SEARCH_ENGINE_SCREEN:
int option = mSearcher->GetChoice();
LockStatusbar();
Song &s = sought_pattern;
switch (option+1)
{
case 1:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Filename:[/b] ", 1);
if (s.GetName() == EMPTY_TAG)
s.SetFile(wFooter->GetString());
else
s.SetFile(wFooter->GetString(s.GetFile()));
mSearcher->Current().first = "[.b]Filename:[/b] " + s.GetFile();
break;
}
case 2:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Title:[/b] ", 1);
if (s.GetTitle() == UNKNOWN_TITLE)
s.SetTitle(wFooter->GetString());
else
s.SetTitle(wFooter->GetString(s.GetTitle()));
mSearcher->Current().first = "[.b]Title:[/b] " + s.GetTitle();
break;
}
case 3:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Artist:[/b] ", 1);
if (s.GetArtist() == UNKNOWN_ARTIST)
s.SetArtist(wFooter->GetString());
else
s.SetArtist(wFooter->GetString(s.GetArtist()));
mSearcher->Current().first = "[.b]Artist:[/b] " + s.GetArtist();
break;
}
case 4:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Album:[/b] ", 1);
if (s.GetAlbum() == UNKNOWN_ALBUM)
s.SetAlbum(wFooter->GetString());
else
s.SetAlbum(wFooter->GetString(s.GetAlbum()));
mSearcher->Current().first = "[.b]Album:[/b] " + s.GetAlbum();
break;
}
case 5:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Year:[/b] ", 1);
if (s.GetYear() == EMPTY_TAG)
s.SetYear(wFooter->GetString(4));
else
s.SetYear(wFooter->GetString(s.GetYear(), 4));
mSearcher->Current().first = "[.b]Year:[/b] " + s.GetYear();
break;
}
case 6:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Track:[/b] ", 1);
if (s.GetTrack() == EMPTY_TAG)
s.SetTrack(wFooter->GetString(3));
else
s.SetTrack(wFooter->GetString(s.GetTrack(), 3));
mSearcher->Current().first = "[.b]Track:[/b] " + s.GetTrack();
break;
}
case 7:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Genre:[/b] ", 1);
if (s.GetGenre() == EMPTY_TAG)
s.SetGenre(wFooter->GetString());
else
s.SetGenre(wFooter->GetString(s.GetGenre()));
mSearcher->Current().first = "[.b]Genre:[/b] " + s.GetGenre();
break;
}
case 8:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Comment:[/b] ", 1);
if (s.GetComment() == EMPTY_TAG)
s.SetComment(wFooter->GetString());
else
s.SetComment(wFooter->GetString(s.GetComment()));
mSearcher->Current().first = "[.b]Comment:[/b] " + s.GetComment();
break;
}
case 10:
{
search_match_to_pattern = !search_match_to_pattern;
mSearcher->Current().first = "[.b]Search mode:[/b] " + (search_match_to_pattern ? search_mode_normal : search_mode_strict);
break;
}
case 11:
{
search_case_sensitive = !search_case_sensitive;
mSearcher->Current().first = "[.b]Case sensitive:[/b] " + string(search_case_sensitive ? "Yes" : "No");
break;
}
case 13:
{
ShowMessage("Searching...");
Search(s);
if (mSearcher->Back().first == ".")
{
int found = mSearcher->Size()-search_engine_static_options;
found += 3; // don't count options inserted below
mSearcher->InsertSeparator(14);
mSearcher->Insert(15, make_pair("[." + Config.color1 + "]Search results:[/" + Config.color1 + "] [." + Config.color2 + "]Found " + IntoStr(found) + (found > 1 ? " songs" : " song") + "[/" + Config.color2 + "]", Song()), 1, 1);
mSearcher->InsertSeparator(16);
UpdateFoundList();
ShowMessage("Searching finished!");
for (int i = 0; i < 13; i++)
mSearcher->MakeStatic(i, 1);
mSearcher->Go(wDown);
mSearcher->Go(wDown);
}
else
ShowMessage("No results found");
break;
}
case 14:
{
found_pos = 0;
vFoundPositions.clear();
PrepareSearchEngine(sought_pattern);
ShowMessage("Search state reset");
break;
}
default:
{
block_item_list_update = 1;
if (Config.ncmpc_like_songs_adding && mSearcher->IsBold())
{
long long hash = mSearcher->Current().second.GetHash();
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->Play(i);
break;
}
}
}
else
{
const Song &s = mSearcher->Current().second;
int id = Mpd->AddSong(s);
if (id >= 0)
{
Mpd->PlayID(id);
ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format));
mSearcher->BoldOption(mSearcher->GetChoice(), 1);
}
}
break;
}
}
if (option <= 10)
mSearcher->RefreshOption(option);
UnlockStatusbar();
break;
}
case csLibrary:
{
ENTER_LIBRARY_SCREEN: // same code for Key.Space, but without playing.
SongList list;
if (wCurrent == mLibArtists)
{
const string &tag = mLibArtists->GetOption();
Mpd->StartSearch(1);
Mpd->AddSearch(Config.media_lib_primary_tag, tag);
Mpd->CommitSearch(list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
string tag_type = IntoStr(Config.media_lib_primary_tag);
ToLower(tag_type);
ShowMessage("Adding songs of " + tag_type + " \"" + tag + "\"");
Song *s = &mPlaylist->at(mPlaylist->Size()-list.size());
if (s->GetHash() == list[0]->GetHash())
{
if (Keypressed(input, Key.Enter))
Mpd->PlayID(s->GetID());
}
else
ShowMessage(message_part_of_songs_added);
}
}
else if (wCurrent == mLibAlbums)
{
for (int i = 0; i < mLibSongs->Size(); i++)
Mpd->QueueAddSong(mLibSongs->at(i));
if (Mpd->CommitQueue())
{
ShowMessage("Adding songs from album \"" + mLibAlbums->Current().second + "\"");
Song *s = &mPlaylist->at(mPlaylist->Size()-mLibSongs->Size());
if (s->GetHash() == mLibSongs->at(0).GetHash())
{
if (Keypressed(input, Key.Enter))
Mpd->PlayID(s->GetID());
}
else
ShowMessage(message_part_of_songs_added);
}
}
else if (wCurrent == mLibSongs)
{
if (!mLibSongs->Empty())
{
block_item_list_update = 1;
if (Config.ncmpc_like_songs_adding && mLibSongs->IsBold())
{
long long hash = mLibSongs->Current().GetHash();
if (Keypressed(input, Key.Enter))
{
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->Play(i);
break;
}
}
}
else
{
block_playlist_update = 1;
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->QueueDeleteSong(i);
mPlaylist->DeleteOption(i);
i--;
}
}
Mpd->CommitQueue();
mLibSongs->BoldOption(mLibSongs->GetChoice(), 0);
}
}
else
{
Song &s = mLibSongs->Current();
int id = Mpd->AddSong(s);
if (id >= 0)
{
ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format));
if (Keypressed(input, Key.Enter))
Mpd->PlayID(id);
mLibSongs->BoldOption(mLibSongs->GetChoice(), 1);
}
}
}
}
FreeSongList(list);
if (Keypressed(input, Key.Space))
{
wCurrent->Go(wDown);
if (wCurrent == mLibArtists)
{
mLibAlbums->Clear(0);
mLibSongs->Clear(0);
}
else if (wCurrent == mLibAlbums)
mLibSongs->Clear(0);
}
break;
}
case csPlaylistEditor:
{
ENTER_PLAYLIST_EDITOR_SCREEN: // same code for Key.Space, but without playing.
SongList list;
if (wCurrent == mPlaylistList)
{
const string &playlist = mPlaylistList->GetOption();
Mpd->GetPlaylistContent(playlist, list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
ShowMessage("Loading playlist " + playlist + "...");
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() == list[0]->GetHash())
{
if (Keypressed(input, Key.Enter))
Mpd->PlayID(s.GetID());
}
else
ShowMessage(message_part_of_songs_added);
}
}
else if (wCurrent == mPlaylistEditor)
{
if (!mPlaylistEditor->Empty())
{
block_item_list_update = 1;
if (Config.ncmpc_like_songs_adding && mPlaylistEditor->IsBold())
{
long long hash = mPlaylistEditor->Current().GetHash();
if (Keypressed(input, Key.Enter))
{
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->Play(i);
break;
}
}
}
else
{
block_playlist_update = 1;
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->QueueDeleteSong(i);
mPlaylist->DeleteOption(i);
i--;
}
}
Mpd->CommitQueue();
mPlaylistEditor->BoldOption(mPlaylistEditor->GetChoice(), 0);
}
}
else
{
Song &s = mPlaylistEditor->at(mPlaylistEditor->GetChoice());
int id = Mpd->AddSong(s);
if (id >= 0)
{
ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format));
if (Keypressed(input, Key.Enter))
Mpd->PlayID(id);
mPlaylistEditor->BoldOption(mPlaylistEditor->GetChoice(), 1);
}
}
}
}
FreeSongList(list);
if (Keypressed(input, Key.Space))
wCurrent->Go(wDown);
break;
}
# ifdef HAVE_TAGLIB_H
case csTagEditor:
{
if (wCurrent == mEditorDirs)
{
TagList test;
Mpd->GetDirectories(mEditorLeftCol->Current().second, test);
if (!test.empty())
{
editor_highlighted_dir = editor_browsed_dir;
editor_browsed_dir = mEditorLeftCol->Current().second;
mEditorLeftCol->Clear(0);
mEditorLeftCol->Reset();
}
else
ShowMessage("No subdirs found");
break;
}
if (mEditorTags->Empty()) // we need songs to deal with, don't we?
break;
// if there are selected songs, perform operations only on them
SongList list;
if (mEditorTags->IsAnySelected())
{
vector<int> selected;
mEditorTags->GetSelectedList(selected);
for (vector<int>::const_iterator it = selected.begin(); it != selected.end(); it++)
list.push_back(&mEditorTags->at(*it));
}
else
for (int i = 0; i < mEditorTags->Size(); i++)
list.push_back(&mEditorTags->at(i));
SongSetFunction set = 0;
int id = mEditorTagTypes->GetRealChoice();
switch (id)
{
case 0:
set = &Song::SetTitle;
break;
case 1:
set = &Song::SetArtist;
break;
case 2:
set = &Song::SetAlbum;
break;
case 3:
set = &Song::SetYear;
break;
case 4:
set = &Song::SetTrack;
if (wCurrent == mEditorTagTypes)
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Number tracks? [y/n] ", 1);
curs_set(1);
int in = 0;
do
{
TraceMpdStatus();
wFooter->ReadKey(in);
}
while (in != 'y' && in != 'n');
if (in == 'y')
{
int i = 1;
for (SongList::iterator it = list.begin(); it != list.end(); it++, i++)
(*it)->SetTrack(i);
ShowMessage("Tracks numbered!");
}
else
ShowMessage("Aborted!");
curs_set(0);
UnlockStatusbar();
}
break;
case 5:
set = &Song::SetGenre;
break;
case 6:
set = &Song::SetComposer;
break;
case 7:
set = &Song::SetPerformer;
break;
case 8:
set = &Song::SetDisc;
break;
case 9:
set = &Song::SetComment;
break;
case 10:
{
if (wCurrent == mEditorTagTypes)
{
current_screen = csOther;
__deal_with_filenames(list);
current_screen = csTagEditor;
redraw_screen = 1;
REFRESH_TAG_EDITOR_SCREEN;
}
else if (wCurrent == mEditorTags)
{
Song &s = mEditorTags->Current();
string old_name = s.GetNewName().empty() ? s.GetName() : s.GetNewName();
int last_dot = old_name.find_last_of(".");
string extension = old_name.substr(last_dot);
old_name = old_name.substr(0, last_dot);
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New filename:[/b] ", 1);
string new_name = wFooter->GetString(old_name);
UnlockStatusbar();
if (!new_name.empty() && new_name != old_name)
s.SetNewName(new_name + extension);
mEditorTags->Go(wDown);
}
continue;
}
case 11: // reset
{
mEditorTags->Clear(0);
ShowMessage("Changes reset");
continue;
}
case 12: // save
{
bool success = 1;
ShowMessage("Writing changes...");
for (SongList::iterator it = list.begin(); it != list.end(); it++)
{
ShowMessage("Writing tags in '" + (*it)->GetName() + "'...");
if (!WriteTags(**it))
{
ShowMessage("Error writing tags in '" + (*it)->GetFile() + "'!");
success = 0;
break;
}
}
if (success)
{
ShowMessage("Tags updated!");
mEditorTagTypes->HighlightColor(Config.main_highlight_color);
mEditorTagTypes->Reset();
wCurrent->Refresh();
wCurrent = mEditorLeftCol;
mEditorLeftCol->HighlightColor(Config.active_column_color);
Mpd->UpdateDirectory(FindSharedDir(mEditorTags));
}
else
mEditorTags->Clear(0);
continue;
}
default:
break;
}
if (wCurrent == mEditorTagTypes && id != 0 && id != 4 && set != NULL)
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]" + mEditorTagTypes->GetOption() + "[/b]: ", 1);
mEditorTags->Current().GetEmptyFields(1);
string new_tag = wFooter->GetString(mEditorTags->GetOption());
mEditorTags->Current().GetEmptyFields(0);
UnlockStatusbar();
for (SongList::iterator it = list.begin(); it != list.end(); it++)
(**it.*set)(new_tag);
redraw_screen = 1;
}
else if (wCurrent == mEditorTags && set != NULL)
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]" + mEditorTagTypes->GetOption() + "[/b]: ", 1);
mEditorTags->Current().GetEmptyFields(1);
string new_tag = wFooter->GetString(mEditorTags->GetOption());
mEditorTags->Current().GetEmptyFields(0);
UnlockStatusbar();
if (new_tag != mEditorTags->GetOption())
(mEditorTags->Current().*set)(new_tag);
mEditorTags->Go(wDown);
}
}
# endif // HAVE_TAGLIB_H
default:
break;
}
}
else if (Keypressed(input, Key.Space))
{
if (Config.space_selects || wCurrent == mPlaylist || wCurrent == mEditorTags)
{
if (wCurrent == mPlaylist || wCurrent == mEditorTags || (wCurrent == mBrowser && wCurrent->GetChoice() >= (browsed_dir != "/" ? 1 : 0)) || (wCurrent == mSearcher && mSearcher->Current().first == ".") || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
{
int i = wCurrent->GetChoice();
wCurrent->Select(i, !wCurrent->Selected(i));
wCurrent->Go(wDown);
}
}
else
{
if (current_screen == csBrowser)
{
const Item &item = mBrowser->Current();
switch (item.type)
{
case itDirectory:
{
if (browsed_dir != "/" && !mBrowser->GetChoice())
continue; // do not let add parent dir.
SongList list;
Mpd->GetDirectoryRecursive(item.name, list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
ShowMessage("Added folder: " + item.name);
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() != list[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
FreeSongList(list);
break;
}
case itSong:
{
block_item_list_update = 1;
if (Config.ncmpc_like_songs_adding && mBrowser->IsBold())
{
block_playlist_update = 1;
long long hash = mBrowser->Current().song->GetHash();
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->QueueDeleteSong(i);
mPlaylist->DeleteOption(i);
i--;
}
}
Mpd->CommitQueue();
mBrowser->BoldOption(mBrowser->GetChoice(), 0);
}
else
{
Song &s = *item.song;
if (Mpd->AddSong(s) != -1)
{
ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format));
mBrowser->BoldOption(mBrowser->GetChoice(), 1);
}
}
break;
}
case itPlaylist:
{
SongList list;
Mpd->GetPlaylistContent(item.name, list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
ShowMessage("Loading playlist " + item.name + "...");
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() != list[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
FreeSongList(list);
break;
}
}
mBrowser->Go(wDown);
}
else if (current_screen == csSearcher && mSearcher->Current().first == ".")
{
block_item_list_update = 1;
if (Config.ncmpc_like_songs_adding && mSearcher->IsBold())
{
block_playlist_update = 1;
long long hash = mSearcher->Current().second.GetHash();
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (mPlaylist->at(i).GetHash() == hash)
{
Mpd->QueueDeleteSong(i);
mPlaylist->DeleteOption(i);
i--;
}
}
Mpd->CommitQueue();
mSearcher->BoldOption(mSearcher->GetChoice(), 0);
}
else
{
Song &s = mSearcher->Current().second;
if (Mpd->AddSong(s) != -1)
{
ShowMessage("Added to playlist: " + DisplaySong(s, &Config.song_status_format));
mSearcher->BoldOption(mSearcher->GetChoice(), 1);
}
}
mSearcher->Go(wDown);
}
else if (current_screen == csLibrary)
goto ENTER_LIBRARY_SCREEN; // sorry, but that's stupid to copy the same code here.
else if (current_screen == csPlaylistEditor)
goto ENTER_PLAYLIST_EDITOR_SCREEN; // same what in library screen.
# ifdef HAVE_TAGLIB_H
else if (wCurrent == mEditorLeftCol)
{
Config.albums_in_tag_editor = !Config.albums_in_tag_editor;
mEditorLeftCol = Config.albums_in_tag_editor ? mEditorAlbums : mEditorDirs;
wCurrent = mEditorLeftCol;
ShowMessage("Switched to " + string(Config.albums_in_tag_editor ? "albums" : "directories") + " view");
mEditorLeftCol->Display();
mEditorTags->Clear(0);
redraw_screen = 1;
}
# endif // HAVE_TAGLIB_H
else if (current_screen == csLyrics)
{
Config.now_playing_lyrics = !Config.now_playing_lyrics;
ShowMessage("Reload lyrics if song changes: " + string(Config.now_playing_lyrics ? "On" : "Off"));
}
}
}
else if (Keypressed(input, Key.VolumeUp))
{
if (current_screen == csLibrary && input == Key.VolumeUp[0])
{
found_pos = 0;
vFoundPositions.clear();
if (wCurrent == mLibArtists)
{
if (mLibSongs->Empty())
continue;
mLibArtists->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mLibAlbums;
mLibAlbums->HighlightColor(Config.active_column_color);
if (!mLibAlbums->Empty())
continue;
}
if (wCurrent == mLibAlbums && !mLibSongs->Empty())
{
mLibAlbums->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mLibSongs;
mLibSongs->HighlightColor(Config.active_column_color);
}
}
else if (wCurrent == mPlaylistList && input == Key.VolumeUp[0])
{
found_pos = 0;
vFoundPositions.clear();
mPlaylistList->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mPlaylistEditor;
mPlaylistEditor->HighlightColor(Config.active_column_color);
}
# ifdef HAVE_TAGLIB_H
else if (current_screen == csTagEditor && input == Key.VolumeUp[0])
{
found_pos = 0;
vFoundPositions.clear();
if (wCurrent == mEditorLeftCol)
{
mEditorLeftCol->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mEditorTagTypes;
mEditorTagTypes->HighlightColor(Config.active_column_color);
}
else if (wCurrent == mEditorTagTypes && mEditorTagTypes->GetChoice() < 12 && !mEditorTags->Empty())
{
mEditorTagTypes->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mEditorTags;
mEditorTags->HighlightColor(Config.active_column_color);
}
}
# endif // HAVE_TAGLIB_H
else
Mpd->SetVolume(Mpd->GetVolume()+1);
}
else if (Keypressed(input, Key.VolumeDown))
{
if (current_screen == csLibrary && input == Key.VolumeDown[0])
{
found_pos = 0;
vFoundPositions.clear();
if (wCurrent == mLibSongs)
{
mLibSongs->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mLibAlbums;
mLibAlbums->HighlightColor(Config.active_column_color);
if (!mLibAlbums->Empty())
continue;
}
if (wCurrent == mLibAlbums)
{
mLibAlbums->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mLibArtists;
mLibArtists->HighlightColor(Config.active_column_color);
}
}
else if (wCurrent == mPlaylistEditor && input == Key.VolumeDown[0])
{
found_pos = 0;
vFoundPositions.clear();
mPlaylistEditor->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mPlaylistList;
mPlaylistList->HighlightColor(Config.active_column_color);
}
# ifdef HAVE_TAGLIB_H
else if (current_screen == csTagEditor && input == Key.VolumeDown[0])
{
found_pos = 0;
vFoundPositions.clear();
if (wCurrent == mEditorTags)
{
mEditorTags->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mEditorTagTypes;
mEditorTagTypes->HighlightColor(Config.active_column_color);
}
else if (wCurrent == mEditorTagTypes)
{
mEditorTagTypes->HighlightColor(Config.main_highlight_color);
wCurrent->Refresh();
wCurrent = mEditorLeftCol;
mEditorLeftCol->HighlightColor(Config.active_column_color);
}
}
# endif // HAVE_TAGLIB_H
else
Mpd->SetVolume(Mpd->GetVolume()-1);
}
else if (Keypressed(input, Key.Delete))
{
if (!mPlaylist->Empty() && current_screen == csPlaylist)
{
block_playlist_update = 1;
if (mPlaylist->IsAnySelected())
{
vector<int> list;
mPlaylist->GetSelectedList(list);
for (vector<int>::const_reverse_iterator it = list.rbegin(); it != ((const vector<int> &)list).rend(); it++)
{
Mpd->QueueDeleteSong(*it);
mPlaylist->DeleteOption(*it);
}
ShowMessage("Selected items deleted!");
redraw_screen = 1;
}
else
{
dont_change_now_playing = 1;
mPlaylist->SetTimeout(50);
while (!mPlaylist->Empty() && Keypressed(input, Key.Delete))
{
int id = mPlaylist->GetChoice();
TraceMpdStatus();
timer = time(NULL);
if (now_playing > id) // needed for keeping proper
now_playing--; // position of now playing song.
Mpd->QueueDeleteSong(id);
mPlaylist->DeleteOption(id);
mPlaylist->Refresh();
mPlaylist->ReadKey(input);
}
mPlaylist->SetTimeout(ncmpcpp_window_timeout);
dont_change_now_playing = 0;
}
Mpd->CommitQueue();
}
else if (current_screen == csBrowser || wCurrent == mPlaylistList)
{
LockStatusbar();
const string &name = wCurrent == mBrowser ? mBrowser->Current().name : mPlaylistList->Current();
if (current_screen != csBrowser || mBrowser->Current().type == itPlaylist)
{
wFooter->WriteXY(0, Config.statusbar_visibility, "Delete playlist " + name + " ? [y/n] ", 1);
curs_set(1);
int in = 0;
do
{
TraceMpdStatus();
wFooter->ReadKey(in);
}
while (in != 'y' && in != 'n');
if (in == 'y')
{
Mpd->DeletePlaylist(name);
ShowMessage("Playlist " + name + " deleted!");
GetDirectory("/");
}
else
ShowMessage("Aborted!");
curs_set(0);
mPlaylistList->Clear(0); // make playlists list update itself
}
UnlockStatusbar();
}
else if (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty())
{
if (mPlaylistEditor->IsAnySelected())
{
vector<int> list;
mPlaylistEditor->GetSelectedList(list);
for (vector<int>::const_reverse_iterator it = list.rbegin(); it != ((const vector<int> &)list).rend(); it++)
{
Mpd->QueueDeleteFromPlaylist(mPlaylistList->GetOption(), *it);
mPlaylistEditor->DeleteOption(*it);
}
ShowMessage("Selected items deleted from playlist '" + mPlaylistList->GetOption() + "'!");
redraw_screen = 1;
}
else
{
mPlaylistEditor->SetTimeout(50);
while (!mPlaylistEditor->Empty() && Keypressed(input, Key.Delete))
{
TraceMpdStatus();
timer = time(NULL);
Mpd->QueueDeleteFromPlaylist(mPlaylistList->GetOption(), mPlaylistEditor->GetChoice());
mPlaylistEditor->DeleteOption(mPlaylistEditor->GetChoice());
mPlaylistEditor->Refresh();
mPlaylistEditor->ReadKey(input);
}
mPlaylistEditor->SetTimeout(ncmpcpp_window_timeout);
}
Mpd->CommitQueue();
}
}
else if (Keypressed(input, Key.Prev))
{
Mpd->Prev();
}
else if (Keypressed(input, Key.Next))
{
Mpd->Next();
}
else if (Keypressed(input, Key.Pause))
{
Mpd->Pause();
}
else if (Keypressed(input, Key.SavePlaylist))
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Save playlist as: ", 1);
string playlist_name = wFooter->GetString();
UnlockStatusbar();
if (playlist_name.find("/") != string::npos)
{
ShowMessage("Playlist name cannot contain slashes!");
continue;
}
if (!playlist_name.empty())
{
if (Mpd->SavePlaylist(playlist_name))
{
ShowMessage("Playlist saved as: " + playlist_name);
mPlaylistList->Clear(0); // make playlist's list update itself
}
else
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Playlist already exists, overwrite: " + playlist_name + " ? [y/n] ", 1);
curs_set(1);
int in = 0;
messages_allowed = 0;
while (in != 'y' && in != 'n')
{
Mpd->UpdateStatus();
wFooter->ReadKey(in);
}
messages_allowed = 1;
if (in == 'y')
{
Mpd->DeletePlaylist(playlist_name);
if (Mpd->SavePlaylist(playlist_name))
ShowMessage("Playlist overwritten!");
}
else
ShowMessage("Aborted!");
curs_set(0);
mPlaylistList->Clear(0); // make playlist's list update itself
UnlockStatusbar();
}
}
if (browsed_dir == "/" && !mBrowser->Empty())
GetDirectory(browsed_dir);
}
else if (Keypressed(input, Key.Stop))
{
Mpd->Stop();
}
else if (Keypressed(input, Key.MvSongUp))
{
if (current_screen == csPlaylist)
{
block_playlist_update = 1;
mPlaylist->SetTimeout(50);
if (mPlaylist->IsAnySelected())
{
vector<int> list;
mPlaylist->GetSelectedList(list);
for (vector<int>::iterator it = list.begin(); it != list.end(); it++)
if (*it == now_playing && list.front() > 0)
mPlaylist->BoldOption(now_playing, 0);
vector<int> origs(list);
while (Keypressed(input, Key.MvSongUp) && list.front() > 0)
{
TraceMpdStatus();
timer = time(NULL);
for (vector<int>::iterator it = list.begin(); it != list.end(); it++)
{
(*it)--;
mPlaylist->Swap(*it, (*it)+1);
}
mPlaylist->Highlight(list[(list.size()-1)/2]);
mPlaylist->Refresh();
mPlaylist->ReadKey(input);
}
for (int i = 0; i < list.size(); i++)
Mpd->QueueMove(origs[i], list[i]);
Mpd->CommitQueue();
}
else
{
int from, to;
from = to = mPlaylist->GetChoice();
// unbold now playing as if song changes during move, this won't be unbolded.
if (to == now_playing && to > 0)
mPlaylist->BoldOption(now_playing, 0);
while (Keypressed(input, Key.MvSongUp) && to > 0)
{
TraceMpdStatus();
timer = time(NULL);
to--;
mPlaylist->Swap(to, to+1);
mPlaylist->Go(wUp);
mPlaylist->Refresh();
mPlaylist->ReadKey(input);
}
Mpd->Move(from, to);
}
mPlaylist->SetTimeout(ncmpcpp_window_timeout);
}
else if (wCurrent == mPlaylistEditor)
{
mPlaylistEditor->SetTimeout(50);
if (mPlaylistEditor->IsAnySelected())
{
vector<int> list;
mPlaylistEditor->GetSelectedList(list);
vector<int> origs(list);
while (Keypressed(input, Key.MvSongUp) && list.front() > 0)
{
TraceMpdStatus();
timer = time(NULL);
for (vector<int>::iterator it = list.begin(); it != list.end(); it++)
{
(*it)--;
mPlaylistEditor->Swap(*it, (*it)+1);
}
mPlaylistEditor->Highlight(list[(list.size()-1)/2]);
mPlaylistEditor->Refresh();
mPlaylistEditor->ReadKey(input);
}
for (int i = 0; i < list.size(); i++)
if (origs[i] != list[i])
Mpd->QueueMove(mPlaylistList->GetOption(), origs[i], list[i]);
Mpd->CommitQueue();
}
else
{
int from, to;
from = to = mPlaylistEditor->GetChoice();
while (Keypressed(input, Key.MvSongUp) && to > 0)
{
TraceMpdStatus();
timer = time(NULL);
to--;
mPlaylistEditor->Swap(to, to+1);
mPlaylistEditor->Go(wUp);
mPlaylistEditor->Refresh();
mPlaylistEditor->ReadKey(input);
}
if (from != to)
Mpd->Move(mPlaylistList->GetOption(), from, to);
}
mPlaylistEditor->SetTimeout(ncmpcpp_window_timeout);
}
}
else if (Keypressed(input, Key.MvSongDown))
{
if (current_screen == csPlaylist)
{
block_playlist_update = 1;
mPlaylist->SetTimeout(50);
if (mPlaylist->IsAnySelected())
{
vector<int> list;
mPlaylist->GetSelectedList(list);
for (vector<int>::iterator it = list.begin(); it != list.end(); it++)
if (*it == now_playing && list.back() < mPlaylist->Size()-1)
mPlaylist->BoldOption(now_playing, 0);
vector<int> origs(list);
while (Keypressed(input, Key.MvSongDown) && list.back() < mPlaylist->Size()-1)
{
TraceMpdStatus();
timer = time(NULL);
for (vector<int>::reverse_iterator it = list.rbegin(); it != list.rend(); it++)
{
(*it)++;
mPlaylist->Swap(*it, (*it)-1);
}
mPlaylist->Highlight(list[(list.size()-1)/2]);
mPlaylist->Refresh();
mPlaylist->ReadKey(input);
}
for (int i = list.size()-1; i >= 0; i--)
Mpd->QueueMove(origs[i], list[i]);
Mpd->CommitQueue();
}
else
{
int from, to;
from = to = mPlaylist->GetChoice();
// unbold now playing as if song changes during move, this won't be unbolded.
if (to == now_playing && to < mPlaylist->Size()-1)
mPlaylist->BoldOption(now_playing, 0);
while (Keypressed(input, Key.MvSongDown) && to < mPlaylist->Size()-1)
{
TraceMpdStatus();
timer = time(NULL);
to++;
mPlaylist->Swap(to, to-1);
mPlaylist->Go(wDown);
mPlaylist->Refresh();
mPlaylist->ReadKey(input);
}
Mpd->Move(from, to);
}
mPlaylist->SetTimeout(ncmpcpp_window_timeout);
}
else if (wCurrent == mPlaylistEditor)
{
mPlaylistEditor->SetTimeout(50);
if (mPlaylistEditor->IsAnySelected())
{
vector<int> list;
mPlaylistEditor->GetSelectedList(list);
vector<int> origs(list);
while (Keypressed(input, Key.MvSongDown) && list.back() < mPlaylistEditor->Size()-1)
{
TraceMpdStatus();
timer = time(NULL);
for (vector<int>::reverse_iterator it = list.rbegin(); it != list.rend(); it++)
{
(*it)++;
mPlaylistEditor->Swap(*it, (*it)-1);
}
mPlaylistEditor->Highlight(list[(list.size()-1)/2]);
mPlaylistEditor->Refresh();
mPlaylistEditor->ReadKey(input);
}
for (int i = list.size()-1; i >= 0; i--)
if (origs[i] != list[i])
Mpd->QueueMove(mPlaylistList->GetOption(), origs[i], list[i]);
Mpd->CommitQueue();
}
else
{
int from, to;
from = to = mPlaylistEditor->GetChoice();
while (Keypressed(input, Key.MvSongDown) && to < mPlaylistEditor->Size()-1)
{
TraceMpdStatus();
timer = time(NULL);
to++;
mPlaylistEditor->Swap(to, to-1);
mPlaylistEditor->Go(wDown);
mPlaylistEditor->Refresh();
mPlaylistEditor->ReadKey(input);
}
if (from != to)
Mpd->Move(mPlaylistList->GetOption(), from, to);
}
mPlaylistEditor->SetTimeout(ncmpcpp_window_timeout);
}
}
else if (Keypressed(input, Key.Add))
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Add: ", 1);
string path = wFooter->GetString();
UnlockStatusbar();
if (!path.empty())
{
SongList list;
Mpd->GetDirectoryRecursive(path, list);
if (!list.empty())
{
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
Song &s = mPlaylist->at(mPlaylist->Size()-list.size());
if (s.GetHash() != list[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
}
else
Mpd->AddSong(path);
FreeSongList(list);
}
}
else if (Keypressed(input, Key.SeekForward) || Keypressed(input, Key.SeekBackward))
{
if (now_playing < 0)
continue;
if (!mPlaylist->at(now_playing).GetTotalLength())
{
ShowMessage("Unknown item length!");
continue;
}
block_progressbar_update = 1;
LockStatusbar();
int songpos;
time_t t = time(NULL);
songpos = Mpd->GetElapsedTime();
Song &s = mPlaylist->at(now_playing);
while (Keypressed(input, Key.SeekForward) || Keypressed(input, Key.SeekBackward))
{
TraceMpdStatus();
timer = time(NULL);
mPlaylist->ReadKey(input);
int howmuch = Config.incremental_seeking ? (timer-t)/2+Config.seek_time : Config.seek_time;
if (songpos < s.GetTotalLength() && Keypressed(input, Key.SeekForward))
{
songpos += howmuch;
if (songpos > s.GetTotalLength())
songpos = s.GetTotalLength();
}
if (songpos < s.GetTotalLength() && songpos > 0 && Keypressed(input, Key.SeekBackward))
{
songpos -= howmuch;
if (songpos < 0)
songpos = 0;
}
wFooter->Bold(1);
string tracklength = "[" + Song::ShowTime(songpos) + "/" + s.GetLength() + "]";
wFooter->WriteXY(wFooter->GetWidth()-tracklength.length(), 1, tracklength);
double progressbar_size = (double)songpos/(s.GetTotalLength());
int howlong = wFooter->GetWidth()*progressbar_size;
mvwhline(wFooter->RawWin(), 0, 0, 0, wFooter->GetWidth());
mvwhline(wFooter->RawWin(), 0, 0, '=',howlong);
mvwaddch(wFooter->RawWin(), 0, howlong, '>');
wFooter->Bold(0);
wFooter->Refresh();
}
Mpd->Seek(songpos);
block_progressbar_update = 0;
UnlockStatusbar();
}
else if (Keypressed(input, Key.TogglePlaylistDisplayMode) && wCurrent == mPlaylist)
{
Config.columns_in_playlist = !Config.columns_in_playlist;
ShowMessage("Playlist display mode: " + string(Config.columns_in_playlist ? "Columns" : "Classic"));
mPlaylist->SetItemDisplayer(Config.columns_in_playlist ? DisplaySongInColumns : DisplaySong);
mPlaylist->SetItemDisplayerUserData(Config.columns_in_playlist ? &Config.song_columns_list_format : &Config.song_list_format);
mPlaylist->SetTitle(Config.columns_in_playlist ? DisplayColumns(Config.song_columns_list_format) : "");
redraw_screen = 1;
}
else if (Keypressed(input, Key.ToggleAutoCenter))
{
Config.autocenter_mode = !Config.autocenter_mode;
ShowMessage("Auto center mode: " + string(Config.autocenter_mode ? "On" : "Off"));
}
else if (Keypressed(input, Key.UpdateDB))
{
if (current_screen == csBrowser)
Mpd->UpdateDirectory(browsed_dir);
else if (current_screen == csTagEditor && !Config.albums_in_tag_editor)
Mpd->UpdateDirectory(editor_browsed_dir);
else
Mpd->UpdateDirectory("/");
}
else if (Keypressed(input, Key.GoToNowPlaying))
{
if (current_screen == csPlaylist && now_playing >= 0)
mPlaylist->Highlight(now_playing);
}
else if (Keypressed(input, Key.ToggleRepeat))
{
Mpd->SetRepeat(!Mpd->GetRepeat());
}
else if (Keypressed(input, Key.ToggleRepeatOne))
{
Config.repeat_one_mode = !Config.repeat_one_mode;
ShowMessage("'Repeat one' mode: " + string(Config.repeat_one_mode ? "On" : "Off"));
}
else if (Keypressed(input, Key.Shuffle))
{
Mpd->Shuffle();
}
else if (Keypressed(input, Key.ToggleRandom))
{
Mpd->SetRandom(!Mpd->GetRandom());
}
else if (Keypressed(input, Key.ToggleCrossfade))
{
Mpd->SetCrossfade(Mpd->GetCrossfade() ? 0 : Config.crossfade_time);
}
else if (Keypressed(input, Key.SetCrossfade))
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Set crossfade to: ", 1);
string crossfade = wFooter->GetString(3);
UnlockStatusbar();
int cf = StrToInt(crossfade);
if (cf > 0)
{
Config.crossfade_time = cf;
Mpd->SetCrossfade(cf);
}
}
else if (Keypressed(input, Key.EditTags))
{
# ifdef HAVE_TAGLIB_H
if (wCurrent == mLibArtists)
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]" + IntoStr(Config.media_lib_primary_tag) + ":[/b] ", 1);
string new_tag = wFooter->GetString(mLibArtists->GetOption());
UnlockStatusbar();
if (!new_tag.empty() && new_tag != mLibArtists->GetOption())
{
bool success = 1;
SongList list;
ShowMessage("Updating tags...");
Mpd->StartSearch(1);
Mpd->AddSearch(Config.media_lib_primary_tag, mLibArtists->GetOption());
Mpd->CommitSearch(list);
SongSetFunction set = IntoSetFunction(Config.media_lib_primary_tag);
if (!set)
continue;
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
{
((*it)->*set)(new_tag);
ShowMessage("Updating tags in '" + (*it)->GetName() + "'...");
string path = Config.mpd_music_dir + (*it)->GetFile();
if (!WriteTags(**it))
{
ShowMessage("Error updating tags in '" + (*it)->GetFile() + "'!");
success = 0;
break;
}
}
if (success)
{
Mpd->UpdateDirectory(FindSharedDir(list));
ShowMessage("Tags updated succesfully!");
}
FreeSongList(list);
}
}
else if (wCurrent == mLibAlbums)
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Album:[/b] ", 1);
string new_album = wFooter->GetString(mLibAlbums->Current().second);
UnlockStatusbar();
if (!new_album.empty() && new_album != mLibAlbums->Current().second)
{
bool success = 1;
SongList list;
ShowMessage("Updating tags...");
Mpd->StartSearch(1);
Mpd->AddSearch(Config.media_lib_primary_tag, mLibArtists->GetOption());
Mpd->AddSearch(MPD_TAG_ITEM_ALBUM, mLibAlbums->Current().second);
Mpd->CommitSearch(list);
for (SongList::const_iterator it = list.begin(); it != list.end(); it++)
{
ShowMessage("Updating tags in '" + (*it)->GetName() + "'...");
string path = Config.mpd_music_dir + (*it)->GetFile();
TagLib::FileRef f(path.c_str());
if (f.isNull())
{
ShowMessage("Error updating tags in '" + (*it)->GetFile() + "'!");
success = 0;
break;
}
f.tag()->setAlbum(TO_WSTRING(new_album));
f.save();
}
if (success)
{
Mpd->UpdateDirectory(FindSharedDir(list));
ShowMessage("Tags updated succesfully!");
}
FreeSongList(list);
}
}
else if (
(wCurrent == mPlaylist && !mPlaylist->Empty())
|| (wCurrent == mBrowser && mBrowser->Current().type == itSong)
|| (wCurrent == mSearcher && mSearcher->Current().first == ".")
|| (wCurrent == mLibSongs && !mLibSongs->Empty())
|| (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty())
|| (wCurrent == mEditorTags && !mEditorTags->Empty()))
{
int id = wCurrent->GetChoice();
switch (current_screen)
{
case csPlaylist:
edited_song = mPlaylist->at(id);
break;
case csBrowser:
edited_song = *mBrowser->at(id).song;
break;
case csSearcher:
edited_song = mSearcher->at(id).second;
break;
case csLibrary:
edited_song = mLibSongs->at(id);
break;
case csPlaylistEditor:
edited_song = mPlaylistEditor->at(id);
break;
case csTagEditor:
edited_song = mEditorTags->at(id);
break;
default:
break;
}
if (edited_song.IsStream())
{
ShowMessage("Cannot edit streams!");
}
else if (GetSongTags(edited_song))
{
wPrev = wCurrent;
wCurrent = mTagEditor;
prev_screen = current_screen;
current_screen = csTinyTagEditor;
redraw_header = 1;
}
else
ShowMessage("Cannot read file '" + Config.mpd_music_dir + edited_song.GetFile() + "'!");
}
else if (wCurrent == mEditorDirs)
{
string old_dir = mEditorDirs->Current().first;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Directory: ", 1);
string new_dir = wFooter->GetString(old_dir);
UnlockStatusbar();
if (!new_dir.empty() && new_dir != old_dir)
{
string full_old_dir = Config.mpd_music_dir + editor_browsed_dir + "/" + old_dir;
string full_new_dir = Config.mpd_music_dir + editor_browsed_dir + "/" + new_dir;
if (rename(full_old_dir.c_str(), full_new_dir.c_str()) == 0)
{
Mpd->UpdateDirectory(editor_browsed_dir);
ShowMessage("'" + old_dir + "' renamed to '" + new_dir + "'");
}
else
ShowMessage("Cannot rename '" + full_old_dir + "' to '" + full_new_dir + "'!");
}
}
else
# endif // HAVE_TAGLIB_H
if (wCurrent == mBrowser && mBrowser->Current().type == itDirectory)
{
string old_dir = mBrowser->Current().name;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Directory:[/b] ", 1);
string new_dir = wFooter->GetString(old_dir);
UnlockStatusbar();
if (!new_dir.empty() && new_dir != old_dir)
{
string full_old_dir = Config.mpd_music_dir + old_dir;
string full_new_dir = Config.mpd_music_dir + new_dir;
if (rename(full_old_dir.c_str(), full_new_dir.c_str()) == 0)
{
ShowMessage("'" + old_dir + "' renamed to '" + new_dir + "'");
Mpd->UpdateDirectory(FindSharedDir(old_dir, new_dir));
}
else
ShowMessage("Cannot rename '" + full_old_dir + "' to '" + full_new_dir + "'!");
}
}
// blah, this key is already reserved for TagEditor. I'll merge this to its screen later.
/*else if (wCurrent == mBrowser && mBrowser->Current().type == itSong)
{
string old_name = mBrowser->Current().song->GetFile();
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Filename:[/b] ", 1);
string new_name = wFooter->GetString(old_name);
UnlockStatusbar();
if (!new_name.empty() && new_name != old_name)
{
string full_old_name = Config.mpd_music_dir + old_name;
string full_new_name = Config.mpd_music_dir + new_name;
if (rename(full_old_name.c_str(), full_new_name.c_str()) == 0)
{
Mpd->UpdateDirectory(FindSharedDir(old_name, new_name));
ShowMessage("'" + old_name + "' renamed to '" + new_name + "'");
}
else
ShowMessage("Cannot rename '" + old_name + "' to '" + new_name + "'!");
}
}*/
else if (wCurrent == mPlaylistList || (wCurrent == mBrowser && mBrowser->Current().type == itPlaylist))
{
string old_name = wCurrent == mPlaylistList ? mPlaylistList->GetOption() : mBrowser->Current().name;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Playlist:[/b] ", 1);
string new_name = wFooter->GetString(old_name);
UnlockStatusbar();
if (!new_name.empty() && new_name != old_name)
{
Mpd->Rename(old_name, new_name);
ShowMessage("Playlist '" + old_name + "' renamed to '" + new_name + "'");
GetDirectory("/");
mPlaylistList->Clear(0);
}
}
}
else if (Keypressed(input, Key.GoToContainingDir))
{
if ((wCurrent == mPlaylist && !mPlaylist->Empty())
|| (wCurrent == mSearcher && mSearcher->Current().first == ".")
|| (wCurrent == mLibSongs && !mLibSongs->Empty())
|| (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty())
|| (wCurrent == mEditorTags && !mEditorTags->Empty()))
{
int id = wCurrent->GetChoice();
Song *s;
switch (current_screen)
{
case csPlaylist:
s = &mPlaylist->at(id);
break;
case csSearcher:
s = &mSearcher->at(id).second;
break;
case csLibrary:
s = &mLibSongs->at(id);
break;
case csPlaylistEditor:
s = &mPlaylistEditor->at(id);
break;
case csTagEditor:
s = &mEditorTags->at(id);
break;
default:
break;
}
if (s->GetDirectory() == EMPTY_TAG) // for streams
continue;
string option = DisplaySong(*s, &Config.song_list_format, mPlaylist);
GetDirectory(s->GetDirectory());
for (int i = 0; i < mBrowser->Size(); i++)
{
if (option == mBrowser->GetOption(i))
{
mBrowser->Highlight(i);
break;
}
}
goto SWITCHER_BROWSER_REDIRECT;
}
}
else if (Keypressed(input, Key.StartSearching))
{
if (wCurrent == mSearcher)
{
mSearcher->Highlight(12); // highlight 'search' button
goto ENTER_SEARCH_ENGINE_SCREEN;
}
}
else if (Keypressed(input, Key.GoToPosition))
{
if (now_playing < 0)
continue;
if (!mPlaylist->at(now_playing).GetTotalLength())
{
ShowMessage("Unknown item length!");
continue;
}
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Position to go (in %): ", 1);
string position = wFooter->GetString(3);
int newpos = StrToInt(position);
if (newpos > 0 && newpos < 100 && !position.empty())
Mpd->Seek(mPlaylist->at(now_playing).GetTotalLength()*newpos/100.0);
UnlockStatusbar();
}
else if (Keypressed(input, Key.ReverseSelection))
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || (wCurrent == mSearcher && mSearcher->Current().first == ".") || wCurrent == mLibSongs || wCurrent == mPlaylistEditor || wCurrent == mEditorTags)
{
for (int i = 0; i < wCurrent->Size(); i++)
wCurrent->Select(i, !wCurrent->Selected(i) && !wCurrent->IsStatic(i));
// hackish shit begins
if (wCurrent == mBrowser && browsed_dir != "/")
wCurrent->Select(0, 0); // [..] cannot be selected, uhm.
if (wCurrent == mSearcher)
wCurrent->Select(13, 0); // 'Reset' cannot be selected, omgplz.
// hacking shit ends. need better solution :/
ShowMessage("Selection reversed!");
}
}
else if (Keypressed(input, Key.DeselectAll))
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || wCurrent == mSearcher || wCurrent == mLibSongs || wCurrent == mPlaylistEditor || wCurrent == mEditorTags)
{
if (wCurrent->IsAnySelected())
{
for (int i = 0; i < wCurrent->Size(); i++)
wCurrent->Select(i, 0);
ShowMessage("Items deselected!");
}
}
}
else if (Keypressed(input, Key.AddSelected))
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || wCurrent == mSearcher || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
{
if (wCurrent->IsAnySelected())
{
vector<int> list;
wCurrent->GetSelectedList(list);
SongList result;
for (vector<int>::const_iterator it = list.begin(); it != list.end(); it++)
{
switch (current_screen)
{
case csPlaylist:
{
Song *s = new Song(mPlaylist->at(*it));
result.push_back(s);
break;
}
case csBrowser:
{
const Item &item = mBrowser->at(*it);
switch (item.type)
{
case itDirectory:
{
if (browsed_dir != "/")
Mpd->GetDirectoryRecursive(browsed_dir + "/" + item.name, result);
else
Mpd->GetDirectoryRecursive(item.name, result);
break;
}
case itSong:
{
Song *s = new Song(*item.song);
result.push_back(s);
break;
}
case itPlaylist:
{
Mpd->GetPlaylistContent(item.name, result);
break;
}
}
break;
}
case csSearcher:
{
Song *s = new Song(mSearcher->at(*it).second);
result.push_back(s);
break;
}
case csLibrary:
{
Song *s = new Song(mLibSongs->at(*it));
result.push_back(s);
break;
}
case csPlaylistEditor:
{
Song *s = new Song(mPlaylistEditor->at(*it));
result.push_back(s);
break;
}
default:
break;
}
}
const int dialog_width = COLS*0.8;
const int dialog_height = LINES*0.6;
Menu<string> *mDialog = new Menu<string>((COLS-dialog_width)/2, (LINES-dialog_height)/2, dialog_width, dialog_height, "Add selected items to...", Config.main_color, Config.window_border);
mDialog->SetTimeout(ncmpcpp_window_timeout);
mDialog->AddOption("Current MPD playlist");
mDialog->AddOption("Create new playlist (m3u file)");
mDialog->AddSeparator();
TagList playlists;
Mpd->GetPlaylists(playlists);
for (TagList::const_iterator it = playlists.begin(); it != playlists.end(); it++)
mDialog->AddOption("'" + *it + "' playlist");
mDialog->AddSeparator();
mDialog->AddOption("Cancel");
mDialog->Display();
prev_screen = current_screen;
current_screen = csOther;
while (!Keypressed(input, Key.Enter))
{
TraceMpdStatus();
mDialog->Refresh();
mDialog->ReadKey(input);
if (Keypressed(input, Key.Up))
mDialog->Go(wUp);
else if (Keypressed(input, Key.Down))
mDialog->Go(wDown);
else if (Keypressed(input, Key.PageUp))
mDialog->Go(wPageUp);
else if (Keypressed(input, Key.PageDown))
mDialog->Go(wPageDown);
else if (Keypressed(input, Key.Home))
mDialog->Go(wHome);
else if (Keypressed(input, Key.End))
mDialog->Go(wEnd);
}
int id = mDialog->GetChoice();
redraw_screen = 1;
if (current_screen == csLibrary)
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
else
wCurrent->Refresh(1);
if (id == 0)
{
for (SongList::const_iterator it = result.begin(); it != result.end(); it++)
Mpd->QueueAddSong(**it);
if (Mpd->CommitQueue())
{
ShowMessage("Selected items added!");
Song &s = mPlaylist->at(mPlaylist->Size()-result.size());
if (s.GetHash() != result[0]->GetHash())
ShowMessage(message_part_of_songs_added);
}
}
else if (id == 1)
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Save playlist as: ", 1);
string playlist = wFooter->GetString();
UnlockStatusbar();
if (!playlist.empty())
{
for (SongList::const_iterator it = result.begin(); it != result.end(); it++)
Mpd->QueueAddToPlaylist(playlist, **it);
Mpd->CommitQueue();
ShowMessage("Selected items added to playlist '" + playlist + "'!");
}
}
else if (id > 1 && id < mDialog->Size()-1)
{
for (SongList::const_iterator it = result.begin(); it != result.end(); it++)
Mpd->QueueAddToPlaylist(playlists[id-3], **it);
Mpd->CommitQueue();
ShowMessage("Selected items added to playlist '" + playlists[id-3] + "'!");
}
if (id != mDialog->Size()-1)
{
// refresh playlist's lists
if (browsed_dir == "/")
GetDirectory("/");
mPlaylistList->Clear(0); // make playlist editor update itself
}
current_screen = prev_screen;
timer = time(NULL);
delete mDialog;
FreeSongList(result);
}
else
ShowMessage("No selected items!");
}
}
else if (Keypressed(input, Key.Crop))
{
if (mPlaylist->IsAnySelected())
{
for (int i = 0; i < mPlaylist->Size(); i++)
{
if (!mPlaylist->Selected(i) && i != now_playing)
Mpd->QueueDeleteSongId(mPlaylist->at(i).GetID());
}
// if mpd deletes now playing song deletion will be sluggishly slow
// then so we have to assure it will be deleted at the very end.
if (!mPlaylist->Selected(now_playing))
Mpd->QueueDeleteSongId(mPlaylist->at(now_playing).GetID());
ShowMessage("Deleting all items but selected...");
Mpd->CommitQueue();
ShowMessage("Items deleted!");
}
else
{
if (now_playing < 0)
{
ShowMessage("Nothing is playing now!");
continue;
}
for (int i = 0; i < now_playing; i++)
Mpd->QueueDeleteSongId(mPlaylist->at(i).GetID());
for (int i = now_playing+1; i < mPlaylist->Size(); i++)
Mpd->QueueDeleteSongId(mPlaylist->at(i).GetID());
ShowMessage("Deleting all items except now playing one...");
Mpd->CommitQueue();
ShowMessage("Items deleted!");
}
}
else if (Keypressed(input, Key.Clear))
{
ShowMessage("Clearing playlist...");
Mpd->ClearPlaylist();
ShowMessage("Cleared playlist!");
}
else if (Keypressed(input, Key.FindForward) || Keypressed(input, Key.FindBackward))
{
if ((current_screen != csHelp && current_screen != csSearcher)
|| (current_screen == csSearcher && mSearcher->Current().first == "."))
{
string how = Keypressed(input, Key.FindForward) ? "forward" : "backward";
found_pos = -1;
vFoundPositions.clear();
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Find " + how + ": ", 1);
string findme = wFooter->GetString();
UnlockStatusbar();
timer = time(NULL);
if (findme.empty())
continue;
ToLower(findme);
ShowMessage("Searching...");
for (int i = (wCurrent == mSearcher ? search_engine_static_options-1 : 0); i < wCurrent->Size(); i++)
{
string name = Window::OmitBBCodes(wCurrent->GetOption(i));
ToLower(name);
if (name.find(findme) != string::npos && !wCurrent->IsStatic(i))
{
vFoundPositions.push_back(i);
if (Keypressed(input, Key.FindForward)) // forward
{
if (found_pos < 0 && i >= wCurrent->GetChoice())
found_pos = vFoundPositions.size()-1;
}
else // backward
{
if (i <= wCurrent->GetChoice())
found_pos = vFoundPositions.size()-1;
}
}
}
ShowMessage("Searching finished!");
if (Config.wrapped_search ? vFoundPositions.empty() : found_pos < 0)
ShowMessage("Unable to find \"" + findme + "\"");
else
{
wCurrent->Highlight(vFoundPositions[found_pos < 0 ? 0 : found_pos]);
if (wCurrent == mPlaylist)
{
timer = time(NULL);
mPlaylist->Highlighting(1);
}
}
}
}
else if (Keypressed(input, Key.NextFoundPosition) || Keypressed(input, Key.PrevFoundPosition))
{
if (!vFoundPositions.empty())
{
try
{
wCurrent->Highlight(vFoundPositions.at(Keypressed(input, Key.NextFoundPosition) ? ++found_pos : --found_pos));
}
catch (std::out_of_range)
{
if (Config.wrapped_search)
{
if (Keypressed(input, Key.NextFoundPosition))
{
wCurrent->Highlight(vFoundPositions.front());
found_pos = 0;
}
else
{
wCurrent->Highlight(vFoundPositions.back());
found_pos = vFoundPositions.size()-1;
}
}
else
found_pos = Keypressed(input, Key.NextFoundPosition) ? vFoundPositions.size()-1 : 0;
}
}
}
else if (Keypressed(input, Key.ToggleFindMode))
{
Config.wrapped_search = !Config.wrapped_search;
ShowMessage("Search mode: " + string(Config.wrapped_search ? "Wrapped" : "Normal"));
}
else if (Keypressed(input, Key.ToggleSpaceMode))
{
Config.space_selects = !Config.space_selects;
ShowMessage("Space mode: " + string(Config.space_selects ? "Select/deselect" : "Add") + " item");
}
else if (Keypressed(input, Key.ToggleAddMode))
{
Config.ncmpc_like_songs_adding = !Config.ncmpc_like_songs_adding;
ShowMessage("Add mode: " + string(Config.ncmpc_like_songs_adding ? "Add item to playlist, remove if already added" : "Always add item to playlist"));
}
else if (Keypressed(input, Key.SwitchTagTypeList) && wCurrent == mLibArtists)
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Tag type ? [[.b]a[/b]rtist/[.b]y[/b]ear/[.b]g[/b]enre/[.b]c[/b]omposer/[.b]p[/b]erformer] ", 1);
int item;
curs_set(1);
do
{
TraceMpdStatus();
wFooter->ReadKey(item);
}
while (item != 'a' && item != 'y' && item != 'g' && item != 'c' && item != 'p');
curs_set(0);
UnlockStatusbar();
mpd_TagItems new_tagitem = IntoTagItem(item);
if (new_tagitem != Config.media_lib_primary_tag)
{
Config.media_lib_primary_tag = new_tagitem;
string item_type = IntoStr(Config.media_lib_primary_tag);
mLibArtists->SetTitle(item_type + "s");
mLibArtists->Reset();
mLibArtists->Clear(0);
mLibArtists->Display();
ToLower(item_type);
ShowMessage("Switched to list of " + item_type + " tag");
}
}
else if (Keypressed(input, Key.SongInfo))
{
if (wCurrent == sInfo)
{
wCurrent->Hide();
current_screen = prev_screen;
wCurrent = wPrev;
redraw_screen = 1;
redraw_header = 1;
if (current_screen == csLibrary)
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
# ifdef HAVE_TAGLIB_H
else if (current_screen == csTagEditor)
{
REFRESH_TAG_EDITOR_SCREEN;
}
# endif // HAVE_TAGLIB_H
}
else if (
(wCurrent == mPlaylist && !mPlaylist->Empty())
|| (wCurrent == mBrowser && mBrowser->Current().type == itSong)
|| (wCurrent == mSearcher && mSearcher->Current().first == ".")
|| (wCurrent == mLibSongs && !mLibSongs->Empty())
|| (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty())
|| (wCurrent == mEditorTags && !mEditorTags->Empty()))
{
Song *s;
int id = wCurrent->GetChoice();
switch (current_screen)
{
case csPlaylist:
s = &mPlaylist->at(id);
break;
case csBrowser:
s = mBrowser->at(id).song;
break;
case csSearcher:
s = &mSearcher->at(id).second;
break;
case csLibrary:
s = &mLibSongs->at(id);
break;
case csPlaylistEditor:
s = &mPlaylistEditor->at(id);
break;
case csTagEditor:
s = &mEditorTags->at(id);
break;
default:
break;
}
wPrev = wCurrent;
wCurrent = sInfo;
prev_screen = current_screen;
current_screen = csInfo;
redraw_header = 1;
info_title = "Song info";
sInfo->Clear();
sInfo->Add(GetInfo(*s));
sInfo->Hide();
}
}
# ifdef HAVE_CURL_CURL_H
else if (Keypressed(input, Key.ArtistInfo))
{
if (wCurrent == sInfo)
{
wCurrent->Hide();
current_screen = prev_screen;
wCurrent = wPrev;
redraw_screen = 1;
redraw_header = 1;
if (current_screen == csLibrary)
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
# ifdef HAVE_TAGLIB_H
else if (current_screen == csTagEditor)
{
REFRESH_TAG_EDITOR_SCREEN;
}
# endif // HAVE_TAGLIB_H
}
else if (
(wCurrent == mPlaylist && !mPlaylist->Empty())
|| (wCurrent == mBrowser && mBrowser->Current().type == itSong)
|| (wCurrent == mSearcher && mSearcher->Current().first == ".")
|| (wCurrent == mLibArtists && !mLibArtists->Empty())
|| (wCurrent == mLibSongs && !mLibSongs->Empty())
|| (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty())
|| (wCurrent == mEditorTags && !mEditorTags->Empty()))
{
string *artist = new string();
int id = wCurrent->GetChoice();
switch (current_screen)
{
case csPlaylist:
*artist = mPlaylist->at(id).GetArtist();
break;
case csBrowser:
*artist = mBrowser->at(id).song->GetArtist();
break;
case csSearcher:
*artist = mSearcher->at(id).second.GetArtist();
break;
case csLibrary:
*artist = mLibArtists->at(id);
break;
case csPlaylistEditor:
*artist = mPlaylistEditor->at(id).GetArtist();
break;
case csTagEditor:
*artist = mEditorTags->at(id).GetArtist();
break;
default:
break;
}
if (*artist != UNKNOWN_ARTIST)
{
wPrev = wCurrent;
wCurrent = sInfo;
prev_screen = current_screen;
current_screen = csInfo;
redraw_header = 1;
info_title = "Artist's info - " + *artist;
sInfo->Clear();
sInfo->WriteXY(0, 0, "Fetching artist's info...");
sInfo->Refresh();
if (!artist_info_downloader)
pthread_create(&artist_info_downloader, NULL, GetArtistInfo, artist);
}
else
delete artist;
}
}
# endif // HAVE_CURL_CURL_H
else if (Keypressed(input, Key.Lyrics))
{
if (wCurrent == sLyrics)
{
wCurrent->Hide();
current_screen = prev_screen;
wCurrent = wPrev;
redraw_screen = 1;
redraw_header = 1;
if (current_screen == csLibrary)
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csPlaylistEditor)
{
REFRESH_PLAYLIST_EDITOR_SCREEN;
}
# ifdef HAVE_TAGLIB_H
else if (current_screen == csTagEditor)
{
REFRESH_TAG_EDITOR_SCREEN;
}
# endif // HAVE_TAGLIB_H
}
else if (
(wCurrent == mPlaylist && !mPlaylist->Empty())
|| (wCurrent == mBrowser && mBrowser->Current().type == itSong)
|| (wCurrent == mSearcher && mSearcher->Current().first == ".")
|| (wCurrent == mLibSongs && !mLibSongs->Empty())
|| (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty())
|| (wCurrent == mEditorTags && !mEditorTags->Empty()))
{
LOAD_LYRICS:
Song *s;
int id;
if (reload_lyrics)
{
current_screen = csPlaylist;
wCurrent = mPlaylist;
reload_lyrics = 0;
id = now_playing;
}
else
id = wCurrent->GetChoice();
switch (current_screen)
{
case csPlaylist:
s = &mPlaylist->at(id);
break;
case csBrowser:
s = mBrowser->at(id).song;
break;
case csSearcher:
s = &mSearcher->at(id).second;
break;
case csLibrary:
s = &mLibSongs->at(id);
break;
case csPlaylistEditor:
s = &mPlaylistEditor->at(id);
break;
case csTagEditor:
s = &mEditorTags->at(id);
break;
default:
break;
}
if (s->GetArtist() != UNKNOWN_ARTIST && s->GetTitle() != UNKNOWN_TITLE)
{
wPrev = wCurrent;
prev_screen = current_screen;
wCurrent = sLyrics;
redraw_header = 1;
wCurrent->Clear();
current_screen = csLyrics;
lyrics_title = "Lyrics: " + s->GetArtist() + " - " + s->GetTitle();
sLyrics->WriteXY(0, 0, "Fetching lyrics...");
sLyrics->Refresh();
# ifdef HAVE_CURL_CURL_H
if (!lyrics_downloader)
pthread_create(&lyrics_downloader, NULL, GetLyrics, s);
# else
string *lyrics = static_cast<string *>(GetLyrics(s));
sLyrics->Add(*lyrics);
delete lyrics;
# endif
}
}
}
else if (Keypressed(input, Key.Help))
{
if (wCurrent != sHelp)
{
wCurrent = sHelp;
wCurrent->Hide();
current_screen = csHelp;
redraw_header = 1;
}
}
else if (Keypressed(input, Key.ScreenSwitcher))
{
if (wCurrent == mPlaylist)
goto SWITCHER_BROWSER_REDIRECT;
else
goto SWITCHER_PLAYLIST_REDIRECT;
}
else if (Keypressed(input, Key.Playlist))
{
SWITCHER_PLAYLIST_REDIRECT:
if (wCurrent != mPlaylist && current_screen != csTinyTagEditor)
{
found_pos = 0;
vFoundPositions.clear();
wCurrent = mPlaylist;
wCurrent->Hide();
current_screen = csPlaylist;
redraw_screen = 1;
redraw_header = 1;
}
}
else if (Keypressed(input, Key.Browser))
{
SWITCHER_BROWSER_REDIRECT:
if (browsed_dir.empty())
browsed_dir = "/";
mBrowser->Empty() ? GetDirectory(browsed_dir) : UpdateItemList(mBrowser);
if (wCurrent != mBrowser && current_screen != csTinyTagEditor)
{
found_pos = 0;
vFoundPositions.clear();
wCurrent = mBrowser;
wCurrent->Hide();
current_screen = csBrowser;
redraw_screen = 1;
redraw_header = 1;
}
}
else if (Keypressed(input, Key.SearchEngine))
{
if (current_screen != csTinyTagEditor && current_screen != csSearcher)
{
found_pos = 0;
vFoundPositions.clear();
if (mSearcher->Empty())
PrepareSearchEngine(sought_pattern);
wCurrent = mSearcher;
wCurrent->Hide();
current_screen = csSearcher;
redraw_screen = 1;
redraw_header = 1;
if (mSearcher->Back().first == ".")
{
wCurrent->WriteXY(0, 0, "Updating list...");
UpdateFoundList();
}
}
}
else if (Keypressed(input, Key.MediaLibrary))
{
if (current_screen != csLibrary)
{
found_pos = 0;
vFoundPositions.clear();
mLibArtists->HighlightColor(Config.active_column_color);
mLibAlbums->HighlightColor(Config.main_highlight_color);
mLibSongs->HighlightColor(Config.main_highlight_color);
mPlaylist->Hide(); // hack, should be wCurrent, but it doesn't always have 100% width
redraw_screen = 1;
redraw_header = 1;
REFRESH_MEDIA_LIBRARY_SCREEN;
wCurrent = mLibArtists;
current_screen = csLibrary;
UpdateSongList(mLibSongs);
}
}
else if (Keypressed(input, Key.PlaylistEditor))
{
if (current_screen != csPlaylistEditor)
{
found_pos = 0;
vFoundPositions.clear();
mPlaylistList->HighlightColor(Config.active_column_color);
mPlaylistEditor->HighlightColor(Config.main_highlight_color);
mPlaylist->Hide(); // hack, should be wCurrent, but it doesn't always have 100% width
redraw_screen = 1;
redraw_header = 1;
REFRESH_PLAYLIST_EDITOR_SCREEN;
wCurrent = mPlaylistList;
current_screen = csPlaylistEditor;
UpdateSongList(mPlaylistEditor);
}
}
# ifdef HAVE_TAGLIB_H
else if (Keypressed(input, Key.TagEditor))
{
if (current_screen != csTagEditor)
{
found_pos = 0;
vFoundPositions.clear();
mEditorAlbums->HighlightColor(Config.active_column_color);
mEditorDirs->HighlightColor(Config.active_column_color);
mEditorTagTypes->HighlightColor(Config.main_highlight_color);
mEditorTags->HighlightColor(Config.main_highlight_color);
mPlaylist->Hide(); // hack, should be wCurrent, but it doesn't always have 100% width
redraw_screen = 1;
redraw_header = 1;
REFRESH_TAG_EDITOR_SCREEN;
if (mEditorTagTypes->Empty())
{
mEditorTagTypes->AddOption("Title");
mEditorTagTypes->AddOption("Artist");
mEditorTagTypes->AddOption("Album");
mEditorTagTypes->AddOption("Year");
mEditorTagTypes->AddOption("Track");
mEditorTagTypes->AddOption("Genre");
mEditorTagTypes->AddOption("Composer");
mEditorTagTypes->AddOption("Performer");
mEditorTagTypes->AddOption("Disc");
mEditorTagTypes->AddOption("Comment");
mEditorTagTypes->AddSeparator();
mEditorTagTypes->AddOption("Filename");
mEditorTagTypes->AddSeparator();
mEditorTagTypes->AddOption("Options", 1, 1, 0, lCenter);
mEditorTagTypes->AddSeparator();
mEditorTagTypes->AddOption("Reset");
mEditorTagTypes->AddOption("Save");
/*mEditorTagTypes->AddSeparator();
mEditorTagTypes->AddOption("Capitalize first letters");*/
}
wCurrent = mEditorLeftCol;
current_screen = csTagEditor;
}
}
# endif // HAVE_TAGLIB_H
else if (Keypressed(input, Key.Quit))
main_exit = 1;
// key mapping end
}
Mpd->Disconnect();
curs_set(1);
endwin();
std::cout << std::endl;
return 0;
}