filename parser for tag editor, renaming files support, minor fixes

This commit is contained in:
unK
2008-09-12 22:06:48 +02:00
parent 8fb83ac476
commit 2605b29dd9
14 changed files with 529 additions and 120 deletions

View File

@@ -51,7 +51,7 @@
#
#key_playlist_editor = '6' 270
#
#key_album_tag_editor = '7' 271
#key_tag_editor = '7' 271
#
#key_stop = 's'
#

View File

@@ -93,19 +93,17 @@
#
##### various settings #####
#
## can be "normal" or "columns"
#
#playlist_display_mode = "normal"
#playlist_display_mode = "normal" (classic/columns)
#
#autocenter_mode = "no"
#
#repeat_one_mode = "no"
#
## can be "wrapped" or "normal"
#default_find_mode = "wrapped" (wrapped/normal)
#
#default_find_mode = "wrapped"
#default_space_mode = "add" (add/select)
#
#default_space_mode = "add"
#default_tag_editor_left_col = "albums" (albums/dirs)
#
#header_visibility = "yes"
#

View File

@@ -100,7 +100,7 @@ string GetKeybindings()
result += DisplayKeys(Key.SearchEngine) + "Search engine\n";
result += DisplayKeys(Key.MediaLibrary) + "Media library\n";
result += DisplayKeys(Key.PlaylistEditor) + "Playlist editor\n";
result += DisplayKeys(Key.AlbumEditor) + "Album editor\n\n\n";
result += DisplayKeys(Key.TagEditor) + "Tag editor\n\n\n";
result += " [.b]Keys - Global\n -----------------------------------------[/b]\n";
@@ -188,7 +188,13 @@ string GetKeybindings()
# ifdef HAVE_TAGLIB_H
result += "\n\n [.b]Keys - Tag editor\n -----------------------------------------[/b]\n";
result += DisplayKeys(Key.Enter) + "Change option\n";
result += DisplayKeys(Key.Enter) + "Change tag/filename for one song (left column)\n";
result += DisplayKeys(Key.Enter) + "Perform operation on all/selected songs (middle column)\n";
result += DisplayKeys(Key.Space) + "Switch to albums/directories view (left column)\n";
result += DisplayKeys(Key.Space) + "Select/deselect song (right column)\n";
result += DisplayKeys(&Key.VolumeDown[0], 1) + "Previous column\n";
result += DisplayKeys(&Key.VolumeUp[0], 1) + "Next column\n";
# endif // HAVE_TAGLIB_H
return result;

View File

@@ -42,6 +42,7 @@ extern string browsed_dir;
extern bool messages_allowed;
extern bool block_progressbar_update;
extern bool block_statusbar_update;
extern bool allow_statusbar_unlock;
extern bool search_case_sensitive;
extern bool search_match_to_pattern;
@@ -53,6 +54,27 @@ extern string UNKNOWN_ARTIST;
extern string UNKNOWN_TITLE;
extern string UNKNOWN_ALBUM;
void LockStatusbar()
{
if (Config.statusbar_visibility)
block_statusbar_update = 1;
else
block_progressbar_update = 1;
allow_statusbar_unlock = 0;
}
void UnlockStatusbar()
{
allow_statusbar_unlock = 1;
if (lock_statusbar_delay < 0)
{
if (Config.statusbar_visibility)
block_statusbar_update = 0;
else
block_progressbar_update = 0;
}
}
bool CaseInsensitiveSorting::operator()(string a, string b)
{
transform(a.begin(), a.end(), a.begin(), tolower);
@@ -478,7 +500,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetArtist() != UNKNOWN_ARTIST)
if (!s.GetArtist().empty() && s.GetArtist() != UNKNOWN_ARTIST)
{
result += s.GetArtist();
i += s.GetArtist().length();
@@ -494,7 +516,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetAlbum() != UNKNOWN_ALBUM)
if (!s.GetAlbum().empty() && s.GetAlbum() != UNKNOWN_ALBUM)
{
result += s.GetAlbum();
i += s.GetAlbum().length();
@@ -510,7 +532,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetYear() != EMPTY_TAG)
if (!s.GetYear().empty() && s.GetYear() != EMPTY_TAG)
{
result += s.GetYear();
i += s.GetYear().length();
@@ -526,7 +548,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetTrack() != EMPTY_TAG)
if (!s.GetTrack().empty() && s.GetTrack() != EMPTY_TAG)
{
result += s.GetTrack();
i += s.GetTrack().length();
@@ -542,7 +564,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetGenre() != EMPTY_TAG)
if (!s.GetGenre().empty() && s.GetGenre() != EMPTY_TAG)
{
result += s.GetGenre();
i += s.GetGenre().length();
@@ -558,7 +580,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetComposer() != EMPTY_TAG)
if (!s.GetComposer().empty() && s.GetComposer() != EMPTY_TAG)
{
result += s.GetComposer();
i += s.GetComposer().length();
@@ -574,7 +596,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetPerformer() != EMPTY_TAG)
if (!s.GetPerformer().empty() && s.GetPerformer() != EMPTY_TAG)
{
result += s.GetPerformer();
i += s.GetPerformer().length();
@@ -590,7 +612,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetDisc() != EMPTY_TAG)
if (!s.GetDisc().empty() && s.GetDisc() != EMPTY_TAG)
{
result += s.GetDisc();
i += s.GetDisc().length();
@@ -606,7 +628,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetComment() != EMPTY_TAG)
if (!s.GetComment().empty() && s.GetComment() != EMPTY_TAG)
{
result += s.GetComment();
i += s.GetComment().length();
@@ -622,7 +644,7 @@ string DisplaySong(const Song &s, void *s_template)
{
if (link_tags)
{
if (s.GetTitle() != UNKNOWN_TITLE)
if (!s.GetTitle().empty() && s.GetTitle() != UNKNOWN_TITLE)
{
result += s.GetTitle();
i += s.GetTitle().length();

View File

@@ -27,6 +27,9 @@
extern ncmpcpp_config Config;
void LockStatusbar();
void UnlockStatusbar();
class CaseInsensitiveSorting
{
public:

View File

@@ -30,23 +30,6 @@
#include "status_checker.h"
#include "tag_editor.h"
#define LOCK_STATUSBAR \
if (Config.statusbar_visibility) \
block_statusbar_update = 1; \
else \
block_progressbar_update = 1; \
allow_statusbar_unlock = 0
#define UNLOCK_STATUSBAR \
allow_statusbar_unlock = 1; \
if (lock_statusbar_delay < 0) \
{ \
if (Config.statusbar_visibility) \
block_statusbar_update = 0; \
else \
block_progressbar_update = 0; \
}
#define REFRESH_MEDIA_LIBRARY_SCREEN \
mLibArtists->Display(redraw_screen); \
mvvline(main_start_y, middle_col_startx-1, 0, main_height); \
@@ -60,7 +43,7 @@
mPlaylistEditor->Display(redraw_screen)
#define REFRESH_ALBUM_EDITOR_SCREEN \
mEditorAlbums->Display(redraw_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); \
@@ -89,8 +72,8 @@ Menu<StringPair> *mEditorLeftCol;
Menu<StringPair> *mEditorAlbums;
Menu<StringPair> *mEditorDirs;
Menu<string> *mEditorTagTypes;
Menu<Song> *mEditorTags;
#endif // HAVE_TAGLIB_H
Menu<Song> *mEditorTags = 0; // blah, I use it in conditionals, so just let it be.
Menu<string> *mPlaylistList;
Menu<Song> *mPlaylistEditor;
@@ -256,6 +239,8 @@ int main(int argc, char *argv[])
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
@@ -349,8 +334,8 @@ int main(int argc, char *argv[])
case csBrowser:
title = "Browse: ";
break;
case csTinyTagEditor:
case csTagEditor:
case csAlbumEditor:
title = "Tag editor";
break;
case csInfo:
@@ -579,7 +564,7 @@ int main(int argc, char *argv[])
// album editor stuff
# ifdef HAVE_TAGLIB_H
if (current_screen == csAlbumEditor)
if (current_screen == csTagEditor)
{
if (mEditorLeftCol->Empty())
{
@@ -685,7 +670,7 @@ int main(int argc, char *argv[])
break;
case csLibrary:
case csPlaylistEditor:
case csAlbumEditor:
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))
{
@@ -808,7 +793,7 @@ int main(int argc, char *argv[])
{
REFRESH_MEDIA_LIBRARY_SCREEN;
}
else if (current_screen == csAlbumEditor)
else if (current_screen == csTagEditor)
{
REFRESH_ALBUM_EDITOR_SCREEN;
}
@@ -894,18 +879,18 @@ int main(int argc, char *argv[])
break;
}
# ifdef HAVE_TAGLIB_H
case csTagEditor:
case csTinyTagEditor:
{
int id = mTagEditor->GetRealChoice()+1;
int option = mTagEditor->GetChoice();
LOCK_STATUSBAR;
LockStatusbar();
Song &s = edited_song;
switch (id)
{
case 1:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New title:[/b] ", 1);
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Title:[/b] ", 1);
if (s.GetTitle() == UNKNOWN_TITLE)
s.SetTitle(wFooter->GetString());
else
@@ -915,7 +900,7 @@ int main(int argc, char *argv[])
}
case 2:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New artist:[/b] ", 1);
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Artist:[/b] ", 1);
if (s.GetArtist() == UNKNOWN_ARTIST)
s.SetArtist(wFooter->GetString());
else
@@ -925,7 +910,7 @@ int main(int argc, char *argv[])
}
case 3:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New album:[/b] ", 1);
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Album:[/b] ", 1);
if (s.GetAlbum() == UNKNOWN_ALBUM)
s.SetAlbum(wFooter->GetString());
else
@@ -935,7 +920,7 @@ int main(int argc, char *argv[])
}
case 4:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New year:[/b] ", 1);
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Year:[/b] ", 1);
if (s.GetYear() == EMPTY_TAG)
s.SetYear(wFooter->GetString(4));
else
@@ -945,7 +930,7 @@ int main(int argc, char *argv[])
}
case 5:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New track:[/b] ", 1);
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Track:[/b] ", 1);
if (s.GetTrack() == EMPTY_TAG)
s.SetTrack(wFooter->GetString(3));
else
@@ -955,7 +940,7 @@ int main(int argc, char *argv[])
}
case 6:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New genre:[/b] ", 1);
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Genre:[/b] ", 1);
if (s.GetGenre() == EMPTY_TAG)
s.SetGenre(wFooter->GetString());
else
@@ -965,7 +950,7 @@ int main(int argc, char *argv[])
}
case 7:
{
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]New comment:[/b] ", 1);
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Comment:[/b] ", 1);
if (s.GetComment() == EMPTY_TAG)
s.SetComment(wFooter->GetString());
else
@@ -1002,7 +987,7 @@ int main(int argc, char *argv[])
break;
}
}
UNLOCK_STATUSBAR;
UnlockStatusbar();
break;
}
# endif // HAVE_TAGLIB_H
@@ -1011,7 +996,7 @@ int main(int argc, char *argv[])
ENTER_SEARCH_ENGINE_SCREEN:
int option = mSearcher->GetChoice();
LOCK_STATUSBAR;
LockStatusbar();
Song &s = sought_pattern;
switch (option+1)
@@ -1154,7 +1139,7 @@ int main(int argc, char *argv[])
}
if (option <= 10)
mSearcher->RefreshOption(option);
UNLOCK_STATUSBAR;
UnlockStatusbar();
break;
}
case csLibrary:
@@ -1274,7 +1259,7 @@ int main(int argc, char *argv[])
break;
}
# ifdef HAVE_TAGLIB_H
case csAlbumEditor:
case csTagEditor:
{
if (wCurrent == mEditorDirs)
{
@@ -1292,7 +1277,20 @@ int main(int argc, char *argv[])
break;
}
void (Song::*set)(const string &) = 0;
// 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)
{
@@ -1312,7 +1310,7 @@ int main(int argc, char *argv[])
set = &Song::SetTrack;
if (wCurrent == mEditorTagTypes)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Number tracks? [y/n] ", 1);
curs_set(1);
int in = 0;
@@ -1324,14 +1322,15 @@ int main(int argc, char *argv[])
while (in != 'y' && in != 'n');
if (in == 'y')
{
for (int i = 0; i < mEditorTags->Size(); i++)
mEditorTags->at(i).SetTrack(i+1);
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);
UNLOCK_STATUSBAR;
UnlockStatusbar();
}
break;
case 5:
@@ -1340,6 +1339,32 @@ int main(int argc, char *argv[])
case 6:
set = &Song::SetComment;
break;
case 7:
{
if (wCurrent == mEditorTagTypes)
{
current_screen = csOther;
__deal_with_filenames(list);
current_screen = csTagEditor;
redraw_screen = 1;
REFRESH_ALBUM_EDITOR_SCREEN;
}
else if (wCurrent == mEditorTags)
{
Song &s = mEditorTags->Current();
string old_name = s.GetNewName().empty() ? s.GetShortFilename() : 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);
}
continue;
}
case 8: // reset
{
mEditorTags->Clear(0);
@@ -1350,9 +1375,9 @@ int main(int argc, char *argv[])
{
bool success = 1;
ShowMessage("Writing changes...");
for (int i = 0; i < mEditorTags->Size(); i++)
for (SongList::iterator it = list.begin(); it != list.end(); it++)
{
if (!WriteTags(mEditorTags->at(i)))
if (!WriteTags(**it))
{
ShowMessage("Error writing tags!");
success = 0;
@@ -1379,23 +1404,23 @@ int main(int argc, char *argv[])
if (wCurrent == mEditorTagTypes && id != 0 && id != 4 && set != NULL)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]" + mEditorTagTypes->GetOption() + "[/b]: ", 1);
mEditorTags->at(mEditorTags->GetChoice()).GetEmptyFields(1);
string new_tag = wFooter->GetString(mEditorTags->GetOption());
mEditorTags->at(mEditorTags->GetChoice()).GetEmptyFields(0);
UNLOCK_STATUSBAR;
for (int i = 0; i < mEditorTags->Size(); i++)
(mEditorTags->at(i).*set)(new_tag);
UnlockStatusbar();
for (SongList::iterator it = list.begin(); it != list.end(); it++)
(**it.*set)(new_tag);
}
else if (wCurrent == mEditorTags && set != NULL)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]" + mEditorTagTypes->GetOption() + "[/b]: ", 1);
mEditorTags->at(mEditorTags->GetChoice()).GetEmptyFields(1);
string new_tag = wFooter->GetString(mEditorTags->GetOption());
mEditorTags->at(mEditorTags->GetChoice()).GetEmptyFields(0);
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (new_tag != mEditorTags->GetOption())
(mEditorTags->at(mEditorTags->GetChoice()).*set)(new_tag);
mEditorTags->Go(wDown);
@@ -1408,9 +1433,9 @@ int main(int argc, char *argv[])
}
else if (Keypressed(input, Key.Space))
{
if (Config.space_selects || wCurrent == mPlaylist)
if (Config.space_selects || wCurrent == mPlaylist || wCurrent == mEditorTags)
{
if (wCurrent == mPlaylist || (wCurrent == mBrowser && wCurrent->GetChoice() >= (browsed_dir != "/" ? 1 : 0)) || (wCurrent == mSearcher && mSearcher->Current().first == ".") || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
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));
@@ -1532,7 +1557,7 @@ int main(int argc, char *argv[])
mPlaylistEditor->HighlightColor(Config.active_column_color);
}
# ifdef HAVE_TAGLIB_H
else if (current_screen == csAlbumEditor && input == Key.VolumeUp[0])
else if (current_screen == csTagEditor && input == Key.VolumeUp[0])
{
found_pos = 0;
vFoundPositions.clear();
@@ -1588,7 +1613,7 @@ int main(int argc, char *argv[])
mPlaylistList->HighlightColor(Config.active_column_color);
}
# ifdef HAVE_TAGLIB_H
else if (current_screen == csAlbumEditor && input == Key.VolumeDown[0])
else if (current_screen == csTagEditor && input == Key.VolumeDown[0])
{
found_pos = 0;
vFoundPositions.clear();
@@ -1648,7 +1673,7 @@ int main(int argc, char *argv[])
}
else if (current_screen == csBrowser || wCurrent == mPlaylistList)
{
LOCK_STATUSBAR;
LockStatusbar();
int id = wCurrent->GetChoice();
const string &name = wCurrent == mBrowser ? mBrowser->at(id).name : mPlaylistList->at(id);
if (current_screen != csBrowser || mBrowser->at(id).type == itPlaylist)
@@ -1673,7 +1698,7 @@ int main(int argc, char *argv[])
curs_set(0);
mPlaylistList->Clear(0); // make playlists list update itself
}
UNLOCK_STATUSBAR;
UnlockStatusbar();
}
else if (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty())
{
@@ -1720,10 +1745,10 @@ int main(int argc, char *argv[])
}
else if (Keypressed(input, Key.SavePlaylist))
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Save playlist as: ", 1);
string playlist_name = wFooter->GetString();
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (playlist_name.find("/") != string::npos)
{
ShowMessage("Playlist name cannot contain slashes!");
@@ -1738,7 +1763,7 @@ int main(int argc, char *argv[])
}
else
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Playlist already exists, overwrite: " + playlist_name + " ? [y/n] ", 1);
curs_set(1);
int in = 0;
@@ -1760,7 +1785,7 @@ int main(int argc, char *argv[])
ShowMessage("Aborted!");
curs_set(0);
mPlaylistList->Clear(0); // make playlist's list update itself
UNLOCK_STATUSBAR;
UnlockStatusbar();
}
}
if (browsed_dir == "/" && !mBrowser->Empty())
@@ -1957,10 +1982,10 @@ int main(int argc, char *argv[])
}
else if (Keypressed(input, Key.Add))
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Add: ", 1);
string path = wFooter->GetString();
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (!path.empty())
{
SongList list;
@@ -1991,7 +2016,7 @@ int main(int argc, char *argv[])
continue;
}
block_progressbar_update = 1;
LOCK_STATUSBAR;
LockStatusbar();
int songpos, in;
@@ -2030,7 +2055,7 @@ int main(int argc, char *argv[])
Mpd->Seek(songpos);
block_progressbar_update = 0;
UNLOCK_STATUSBAR;
UnlockStatusbar();
}
else if (Keypressed(input, Key.TogglePlaylistDisplayMode) && wCurrent == mPlaylist)
{
@@ -2081,10 +2106,10 @@ int main(int argc, char *argv[])
}
else if (Keypressed(input, Key.SetCrossfade))
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Set crossfade to: ", 1);
string crossfade = wFooter->GetString(3);
UNLOCK_STATUSBAR;
UnlockStatusbar();
int cf = StrToInt(crossfade);
if (cf > 0)
{
@@ -2097,10 +2122,10 @@ int main(int argc, char *argv[])
# ifdef HAVE_TAGLIB_H
if (wCurrent == mLibArtists)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Artist:[/b] ", 1);
string new_artist = wFooter->GetString(mLibArtists->GetOption());
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (!new_artist.empty() && new_artist != mLibArtists->GetOption())
{
bool success = 1;
@@ -2129,10 +2154,10 @@ int main(int argc, char *argv[])
}
else if (wCurrent == mLibAlbums)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Album:[/b] ", 1);
string new_album = wFooter->GetString(mLibAlbums->Current().second);
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (!new_album.empty() && new_album != mLibAlbums->Current().second)
{
bool success = 1;
@@ -2193,17 +2218,17 @@ int main(int argc, char *argv[])
wPrev = wCurrent;
wCurrent = mTagEditor;
prev_screen = current_screen;
current_screen = csTagEditor;
current_screen = csTinyTagEditor;
}
else
ShowMessage("Cannot read file '" + Config.mpd_music_dir + edited_song.GetFile() + "'!");
}
else if (wCurrent == mEditorDirs)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Directory: ", 1);
string new_dir = wFooter->GetString(mEditorDirs->Current().first);
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (!new_dir.empty() && new_dir != mEditorDirs->Current().first)
{
string old_dir = Config.mpd_music_dir + mEditorDirs->Current().second;
@@ -2221,10 +2246,10 @@ int main(int argc, char *argv[])
# endif // HAVE_TAGLIB_H
if (wCurrent == mPlaylistList)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Playlist:[/b] ", 1);
string new_name = wFooter->GetString(mPlaylistList->GetOption());
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (!new_name.empty() && new_name != mPlaylistList->GetOption())
{
Mpd->Rename(mPlaylistList->GetOption(), new_name);
@@ -2293,17 +2318,17 @@ int main(int argc, char *argv[])
ShowMessage("Unknown item length!");
continue;
}
LOCK_STATUSBAR;
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);
UNLOCK_STATUSBAR;
UnlockStatusbar();
}
else if (Keypressed(input, Key.ReverseSelection))
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || (wCurrent == mSearcher && mSearcher->Current().first == ".") || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
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));
@@ -2318,7 +2343,7 @@ int main(int argc, char *argv[])
}
else if (Keypressed(input, Key.DeselectAll))
{
if (wCurrent == mPlaylist || wCurrent == mBrowser || wCurrent == mSearcher || wCurrent == mLibSongs || wCurrent == mPlaylistEditor)
if (wCurrent == mPlaylist || wCurrent == mBrowser || wCurrent == mSearcher || wCurrent == mLibSongs || wCurrent == mPlaylistEditor || wCurrent == mEditorTags)
{
if (wCurrent->IsAnySelected())
{
@@ -2413,9 +2438,12 @@ int main(int argc, char *argv[])
mDialog->AddOption("Cancel");
mDialog->Display();
prev_screen = current_screen;
current_screen = csOther;
while (!Keypressed(input, Key.Enter))
{
TraceMpdStatus();
mDialog->Refresh();
mDialog->ReadKey(input);
@@ -2461,10 +2489,10 @@ int main(int argc, char *argv[])
}
else if (id == 1)
{
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Save playlist as: ", 1);
string playlist = wFooter->GetString();
UNLOCK_STATUSBAR;
UnlockStatusbar();
if (!playlist.empty())
{
for (SongList::const_iterator it = result.begin(); it != result.end(); it++)
@@ -2489,6 +2517,8 @@ int main(int argc, char *argv[])
GetDirectory("/");
mPlaylistList->Clear(0); // make playlist editor update itself
}
current_screen = prev_screen;
timer = time(NULL);
delete mDialog;
FreeSongList(result);
}
@@ -2544,10 +2574,10 @@ int main(int argc, char *argv[])
string how = Keypressed(input, Key.FindForward) ? "forward" : "backward";
found_pos = -1;
vFoundPositions.clear();
LOCK_STATUSBAR;
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "Find " + how + ": ", 1);
string findme = wFooter->GetString();
UNLOCK_STATUSBAR;
UnlockStatusbar();
timer = time(NULL);
if (findme.empty())
continue;
@@ -2760,7 +2790,7 @@ int main(int argc, char *argv[])
else if (Keypressed(input, Key.Playlist))
{
SWITCHER_PLAYLIST_REDIRECT:
if (wCurrent != mPlaylist && current_screen != csTagEditor)
if (wCurrent != mPlaylist && current_screen != csTinyTagEditor)
{
found_pos = 0;
vFoundPositions.clear();
@@ -2778,7 +2808,7 @@ int main(int argc, char *argv[])
mBrowser->Empty() ? GetDirectory(browsed_dir) : UpdateItemList(mBrowser);
if (wCurrent != mBrowser && current_screen != csTagEditor)
if (wCurrent != mBrowser && current_screen != csTinyTagEditor)
{
found_pos = 0;
vFoundPositions.clear();
@@ -2790,7 +2820,7 @@ int main(int argc, char *argv[])
}
else if (Keypressed(input, Key.SearchEngine))
{
if (current_screen != csTagEditor && current_screen != csSearcher)
if (current_screen != csTinyTagEditor && current_screen != csSearcher)
{
found_pos = 0;
vFoundPositions.clear();
@@ -2851,9 +2881,9 @@ int main(int argc, char *argv[])
}
}
# ifdef HAVE_TAGLIB_H
else if (Keypressed(input, Key.AlbumEditor))
else if (Keypressed(input, Key.TagEditor))
{
if (current_screen != csAlbumEditor)
if (current_screen != csTagEditor)
{
found_pos = 0;
vFoundPositions.clear();
@@ -2880,13 +2910,16 @@ int main(int argc, char *argv[])
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 = csAlbumEditor;
current_screen = csTagEditor;
}
}
# endif // HAVE_TAGLIB_H

View File

@@ -49,13 +49,14 @@ enum NcmpcppScreen
csHelp,
csPlaylist,
csBrowser,
csTagEditor,
csTinyTagEditor,
csInfo,
csSearcher,
csLibrary,
csLyrics,
csPlaylistEditor,
csAlbumEditor
csTagEditor,
csOther
};
const int ncmpcpp_window_timeout = 500;

View File

@@ -45,7 +45,7 @@ void DefaultKeys(ncmpcpp_keys &keys)
keys.SearchEngine[0] = '4';
keys.MediaLibrary[0] = '5';
keys.PlaylistEditor[0] = '6';
keys.AlbumEditor[0] = '7';
keys.TagEditor[0] = '7';
keys.Stop[0] = 's';
keys.Pause[0] = 'P';
keys.Next[0] = '>';
@@ -104,7 +104,7 @@ void DefaultKeys(ncmpcpp_keys &keys)
keys.SearchEngine[1] = 268;
keys.MediaLibrary[1] = 269;
keys.PlaylistEditor[1] = 270;
keys.AlbumEditor[1] = 271;
keys.TagEditor[1] = 271;
keys.Stop[1] = null_key;
keys.Pause[1] = null_key;
keys.Next[1] = null_key;
@@ -176,7 +176,7 @@ void DefaultConfiguration(ncmpcpp_config &conf)
conf.repeat_one_mode = false;
conf.wrapped_search = true;
conf.space_selects = false;
conf.albums_in_tag_editor = true;
conf.albums_in_tag_editor = false;
conf.set_window_title = true;
conf.mpd_connection_timeout = 15;
conf.crossfade_time = 5;
@@ -328,8 +328,8 @@ void ReadKeys(ncmpcpp_keys &keys)
GetKeys(*it, keys.MediaLibrary);
else if (it->find("key_playlist_editor ") != string::npos)
GetKeys(*it, keys.PlaylistEditor);
else if (it->find("key_album_tag_editor ") != string::npos)
GetKeys(*it, keys.AlbumEditor);
else if (it->find("key_tag_editor ") != string::npos)
GetKeys(*it, keys.TagEditor);
else if (it->find("key_stop ") != string::npos)
GetKeys(*it, keys.Stop);
else if (it->find("key_pause ") != string::npos)
@@ -498,23 +498,45 @@ void ReadConfiguration(ncmpcpp_config &conf)
conf.selected_item_suffix = v;
}
else if (it->find("colors_enabled") != string::npos)
{
conf.colors_enabled = v == "yes";
}
else if (it->find("playlist_display_mode") != string::npos)
{
conf.columns_in_playlist = v == "columns";
}
else if (it->find("header_visibility") != string::npos)
{
conf.header_visibility = v == "yes";
}
else if (it->find("statusbar_visibility") != string::npos)
{
conf.statusbar_visibility = v == "yes";
}
else if (it->find("autocenter_mode") != string::npos)
{
conf.autocenter_mode = v == "yes";
}
else if (it->find("repeat_one_mode") != string::npos)
{
conf.repeat_one_mode = v == "yes";
}
else if (it->find("default_find_mode") != string::npos)
{
conf.wrapped_search = v == "wrapped";
}
else if (it->find("default_space_mode") != string::npos)
{
conf.space_selects = v == "select";
}
else if (it->find("default_tag_editor_left_col") != string::npos)
{
conf.albums_in_tag_editor = v == "albums";
}
else if (it->find("enable_window_title") != string::npos)
{
conf.set_window_title = v == "yes";
}
else if (it->find("song_window_title_format") != string::npos)
{
if (!v.empty())

View File

@@ -47,7 +47,7 @@ struct ncmpcpp_keys
int SearchEngine[2];
int MediaLibrary[2];
int PlaylistEditor[2];
int AlbumEditor[2];
int TagEditor[2];
int Stop[2];
int Pause[2];
int Next[2];

View File

@@ -75,6 +75,9 @@ class Song
void SetComment(const string &str) { itsComment = str; }
void SetPosition(int pos) { itsPosition = pos; }
void SetNewName(string name) { itsNewName = name == itsShortName ? "" : name; }
string GetNewName() const { return itsNewName; }
void GetEmptyFields(bool get) { itsGetEmptyFields = get; }
void Clear();
bool Empty() const;
@@ -85,6 +88,7 @@ class Song
private:
string itsFile;
string itsShortName;
string itsNewName;
string itsDirectory;
string itsArtist;
string itsTitle;

View File

@@ -22,8 +22,16 @@
#ifdef HAVE_TAGLIB_H
#include "helpers.h"
#include "status_checker.h"
extern ncmpcpp_config Config;
extern ncmpcpp_keys Key;
extern Menu<string> *mTagEditor;
extern Window *wFooter;
string pattern = "%n - %t";
string FindSharedDir(Menu<Song> *menu)
{
@@ -71,7 +79,7 @@ string DisplayTag(const Song &s, void *data)
case 6:
return s.GetComment();
case 8:
return s.GetShortFilename();
return s.GetNewName().empty() ? s.GetShortFilename() : s.GetShortFilename() + " [.green]->[/green] " + s.GetNewName();
default:
return "";
}
@@ -128,11 +136,312 @@ bool WriteTags(Song &s)
f.tag()->setComment(TO_WSTRING(s.GetComment()));
s.GetEmptyFields(0);
f.save();
if (!s.GetNewName().empty())
{
string old_name = Config.mpd_music_dir + s.GetFile();
string new_name = Config.mpd_music_dir + s.GetDirectory() + "/" + s.GetNewName();
rename(old_name.c_str(), new_name.c_str());
}
return true;
}
else
return false;
}
SongSetFunction IntoSetFunction(char c)
{
switch (c)
{
case 'a':
return &Song::SetArtist;
case 't':
return &Song::SetTitle;
case 'b':
return &Song::SetAlbum;
case 'y':
return &Song::SetYear;
case 'n':
return &Song::SetTrack;
case 'g':
return &Song::SetGenre;
/*case 'c':
return &Song::SetComposer;
case 'p':
return &Song::SetPerformer;
case 'd':
return &Song::SetDisc;*/
case 'C':
return &Song::SetComment;
default:
return NULL;
}
}
string ParseFilename(Song &s, string mask, bool preview)
{
std::stringstream result;
vector<string> separators;
vector< std::pair<char, string> > tags;
string file = s.GetShortFilename().substr(0, s.GetShortFilename().find_last_of("."));
try
{
for (int i = mask.find("%"); i != string::npos; i = mask.find("%"))
{
tags.push_back(std::pair<char, string>(mask.at(i+1), ""));
mask = mask.substr(i+2);
i = mask.find("%");
if (!mask.empty())
separators.push_back(mask.substr(0, i));
}
int i = 0;
for (vector<string>::const_iterator it = separators.begin(); it != separators.end(); it++, i++)
{
int j = file.find(*it);
tags.at(i).second = file.substr(0, j);
file = file.substr(j+it->length());
}
if (!file.empty())
tags.at(i).second = file;
}
catch (std::out_of_range)
{
return "Error while parsing filename!";
}
for (vector< std::pair<char, string> >::iterator it = tags.begin(); it != tags.end(); it++)
{
for (string::iterator j = it->second.begin(); j != it->second.end(); j++)
if (*j == '_')
*j = ' ';
if (!preview)
{
SongSetFunction set = IntoSetFunction(it->first);
if (set)
(s.*set)(it->second);
}
else
result << "%" << it->first << ": " << it->second << "\n";
}
return result.str();
}
void __deal_with_filenames(SongList &v)
{
int width = 30;
int height = 6;
Menu<string> *Main = new Menu<string>((COLS-width)/2, (LINES-height)/2, width, height, "", Config.main_color, brGreen);
Main->SetTimeout(ncmpcpp_window_timeout);
Main->AddOption("Get tags from filename");
Main->AddOption("Rename files");
Main->AddSeparator();
Main->AddOption("Cancel");
Main->Display();
int input = 0;
while (!Keypressed(input, Key.Enter))
{
TraceMpdStatus();
Main->Refresh();
Main->ReadKey(input);
if (Keypressed(input, Key.Down))
Main->Go(wDown);
else if (Keypressed(input, Key.Up))
Main->Go(wUp);
}
width = COLS*0.9;
height = LINES*0.8;
bool exit = 0;
bool preview = 1;
int choice = Main->GetChoice();
int one_width = width/2;
int two_width = width-one_width;
delete Main;
Main = 0;
Scrollpad *Helper = 0;
Scrollpad *Legend = 0;
Scrollpad *Preview = 0;
Window *Active = 0;
if (choice != 3)
{
Legend = new Scrollpad((COLS-width)/2+one_width, (LINES-height)/2, two_width, height, "Legend", Config.main_color, brGreen);
Legend->SetTimeout(ncmpcpp_window_timeout);
Legend->Add("%a - artist\n");
Legend->Add("%t - title\n");
Legend->Add("%b - album\n");
Legend->Add("%y - year\n");
Legend->Add("%n - track number\n");
Legend->Add("%g - genre\n");
if (choice)
{
Legend->Add("%c - composer\n");
Legend->Add("%p - performer\n");
Legend->Add("%d - disc\n");
}
Legend->Add("%C - comment\n\n");
Legend->Add("[.b]Files:[/b]\n");
for (SongList::const_iterator it = v.begin(); it != v.end(); it++)
Legend->Add("[.green]*[/green] " + (*it)->GetShortFilename() + "\n");
Preview = static_cast<Scrollpad *>(Legend->EmptyClone());
Preview->SetTitle("Preview");
Preview->SetTimeout(ncmpcpp_window_timeout);
Main = new Menu<string>((COLS-width)/2, (LINES-height)/2, one_width, height, "", Config.main_color, brRed);
Main->SetTimeout(ncmpcpp_window_timeout);
Main->AddOption("[.b]Pattern:[/b] " + pattern);
Main->AddOption("Preview");
Main->AddOption("Legend");
Main->AddSeparator();
Main->AddOption("Proceed");
Main->AddOption("Cancel");
/*Main->AddSeparator();
Main->AddOption("Recent patterns", 1, 1, 0, lCenter);
Main->AddSeparator();
Main->AddOption("item1");
Main->AddOption("item2 etc.");*/
Active = Main;
Helper = Legend;
Main->SetTitle(!choice ? "Get tags from filename" : "Rename files");
Main->Display();
Helper->Display();
while (!exit)
{
TraceMpdStatus();
Active->Refresh();
Active->ReadKey(input);
if (Keypressed(input, Key.Up))
Active->Go(wUp);
else if (Keypressed(input, Key.Down))
Active->Go(wDown);
else if (Keypressed(input, Key.PageUp))
Active->Go(wPageUp);
else if (Keypressed(input, Key.PageDown))
Active->Go(wPageDown);
else if (Keypressed(input, Key.Home))
Active->Go(wHome);
else if (Keypressed(input, Key.End))
Active->Go(wEnd);
else if (Keypressed(input, Key.Enter) && Active == Main)
{
switch (Main->GetRealChoice())
{
case 0:
{
LockStatusbar();
wFooter->WriteXY(0, Config.statusbar_visibility, "[.b]Pattern:[/b] ", 1);
string new_pattern = wFooter->GetString(pattern);
UnlockStatusbar();
if (!new_pattern.empty())
{
pattern = new_pattern;
Main->UpdateOption(0, "[.b]Pattern:[/b] " + pattern);
}
break;
}
case 3: // save
preview = 0;
case 1:
{
bool success = 1;
ShowMessage("Parsing...");
Preview->Clear();
for (SongList::iterator it = v.begin(); it != v.end(); it++)
{
Song &s = **it;
if (!choice)
{
if (preview)
{
Preview->Add("[.b]" + s.GetShortFilename() + ":[/b]\n");
Preview->Add(ParseFilename(s, pattern, preview) + "\n");
}
else
ParseFilename(s, pattern, preview);
}
else
{
const string &file = s.GetShortFilename();
int last_dot = file.find_last_of(".");
string extension = file.substr(last_dot);
s.GetEmptyFields(1);
string new_file = Window::OmitBBCodes(DisplaySong(s, &pattern));
if (new_file.empty())
{
if (preview)
new_file = "[.red]!EMPTY![/red]";
else
{
ShowMessage("File '" + s.GetShortFilename() + "' would have an empty name!");
success = 0;
break;
}
}
if (!preview)
s.SetNewName(new_file + extension);
Preview->Add(file + " [.green]->[/green] " + new_file + extension + "\n");
s.GetEmptyFields(0);
}
}
if (!success)
{
preview = 1;
continue;
}
ShowMessage("Operation finished!");
if (preview)
{
Helper = Preview;
Helper->Display();
break;
}
}
case 4:
{
exit = 1;
break;
}
case 2:
{
Helper = Legend;
Helper->Display();
break;
}
}
}
else if (Keypressed(input, Key.VolumeUp) && Active == Main)
{
Active->SetBorder(brGreen);
Active->Display(1);
Active = Helper;
Active->SetBorder(brRed);
Active->Display();
}
else if (Keypressed(input, Key.VolumeDown) && Active == Helper)
{
Active->SetBorder(brGreen);
Active->Display();
Active = Main;
Active->SetBorder(brRed);
Active->Display(1);
}
}
}
delete Main;
delete Legend;
delete Preview;
}
#endif

View File

@@ -32,6 +32,8 @@
#include "mpdpp.h"
#include "settings.h"
typedef void (Song::*SongSetFunction)(const string &);
string FindSharedDir(Menu<Song> *);
string FindSharedDir(const SongList &);
string DisplayTag(const Song &, void *);
@@ -39,6 +41,9 @@ string DisplayTag(const Song &, void *);
bool GetSongTags(Song &);
bool WriteTags(Song &);
string ParseFilename(Song &, string, bool);
void __deal_with_filenames(SongList &);
#endif
#endif

View File

@@ -113,6 +113,11 @@ void Window::SetBorder(Border border)
itsWidth -= 2;
Recreate();
}
else
{
wattron(itsWinBorder,COLOR_PAIR(border));
box(itsWinBorder,0,0);
}
itsBorder = border;
}
@@ -414,6 +419,7 @@ string Window::GetString(const string &base, unsigned int length, int width) con
getyx(itsWindow,y,x);
minx = maxx = x;
width--;
if (width == -1)
width = itsWidth-x-1;
if (width < 0)
@@ -438,7 +444,7 @@ string Window::GetString(const string &base, unsigned int length, int width) con
if (beginning > maxbeginning)
beginning = maxbeginning;
mvwhline(itsWindow, y, minx, 32, width);
mvwhline(itsWindow, y, minx, 32, width+1);
mvwprintw(itsWindow, y, minx, "%ls", tmp.substr(beginning, width+1).c_str());
if (itsGetStringHelper)

View File

@@ -96,8 +96,8 @@ class Window
virtual void WriteXY(int x, int y, const wstring &s, bool ete = 0) { WriteXY(x, y, 0xFFFF, s, ete); }
virtual void WriteXY(int, int, int, const wstring &, bool = 0);
#endif
virtual string GetString(const string &, unsigned int = -1, int = -1) const;
virtual string GetString(unsigned int length = -1, int width = -1) const { return GetString("", length, width); }
virtual string GetString(const string &, unsigned int = -1, int = 0) const;
virtual string GetString(unsigned int length = -1, int width = 0) const { return GetString("", length, width); }
virtual void Scrollable(bool) const;
virtual void GetXY(int &, int &) const;
virtual void GotoXY(int, int) const;