browser: read tags from local songs
This commit is contained in:
@@ -819,7 +819,7 @@ void Delete::Run()
|
|||||||
if (myBrowser->isParentDir(myBrowser->Main()->Choice()))
|
if (myBrowser->isParentDir(myBrowser->Main()->Choice()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string name = item.type == itSong ? item.song.getName() : item.name;
|
std::string name = item.type == itSong ? item.song->getName() : item.name;
|
||||||
std::string question;
|
std::string question;
|
||||||
if (myBrowser->Main()->hasSelected())
|
if (myBrowser->Main()->hasSelected())
|
||||||
question = "Delete selected items?";
|
question = "Delete selected items?";
|
||||||
@@ -842,7 +842,7 @@ void Delete::Run()
|
|||||||
for (size_t i = 0; i < list.size(); ++i)
|
for (size_t i = 0; i < list.size(); ++i)
|
||||||
{
|
{
|
||||||
const MPD::Item &it = (*myBrowser->Main())[list[i]];
|
const MPD::Item &it = (*myBrowser->Main())[list[i]];
|
||||||
name = it.type == itSong ? it.song.getName() : it.name;
|
name = it.type == itSong ? it.song->getName() : it.name;
|
||||||
if (myBrowser->DeleteItem(it))
|
if (myBrowser->DeleteItem(it))
|
||||||
{
|
{
|
||||||
const char msg[] = "\"%s\" deleted";
|
const char msg[] = "\"%s\" deleted";
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ void Browser::EnterPressed()
|
|||||||
}
|
}
|
||||||
case itSong:
|
case itSong:
|
||||||
{
|
{
|
||||||
bool res = myPlaylist->Add(item.song, w->isBold(), 1);
|
bool res = myPlaylist->Add(*item.song, w->isBold(), 1);
|
||||||
w->Bold(w->Choice(), res);
|
w->Bold(w->Choice(), res);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ void Browser::SpacePressed()
|
|||||||
myBrowser->GetLocalDirectory(items, item.name, 1);
|
myBrowser->GetLocalDirectory(items, item.name, 1);
|
||||||
list.reserve(items.size());
|
list.reserve(items.size());
|
||||||
for (MPD::ItemList::const_iterator it = items.begin(); it != items.end(); ++it)
|
for (MPD::ItemList::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||||
list.push_back(it->song);
|
list.push_back(*it->song);
|
||||||
result = myPlaylist->Add(list, 0);
|
result = myPlaylist->Add(list, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -201,7 +201,7 @@ void Browser::SpacePressed()
|
|||||||
}
|
}
|
||||||
case itSong:
|
case itSong:
|
||||||
{
|
{
|
||||||
bool res = myPlaylist->Add(item.song, w->isBold(), 0);
|
bool res = myPlaylist->Add(*item.song, w->isBold(), 0);
|
||||||
w->Bold(w->Choice(), res);
|
w->Bold(w->Choice(), res);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -258,7 +258,7 @@ void Browser::MouseButtonPressed(MEVENT me)
|
|||||||
|
|
||||||
MPD::Song *Browser::CurrentSong()
|
MPD::Song *Browser::CurrentSong()
|
||||||
{
|
{
|
||||||
return !w->Empty() && w->Current().type == itSong ? &w->Current().song : 0;
|
return !w->Empty() && w->Current().type == itSong ? w->Current().song.get() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Browser::ReverseSelection()
|
void Browser::ReverseSelection()
|
||||||
@@ -287,7 +287,7 @@ void Browser::GetSelectedSongs(MPD::SongList &v)
|
|||||||
MPD::ItemList list;
|
MPD::ItemList list;
|
||||||
GetLocalDirectory(list, item.name, 1);
|
GetLocalDirectory(list, item.name, 1);
|
||||||
for (auto j = list.begin(); j != list.end(); ++j)
|
for (auto j = list.begin(); j != list.end(); ++j)
|
||||||
v.push_back(j->song);
|
v.push_back(*j->song);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
# endif // !WIN32
|
# endif // !WIN32
|
||||||
@@ -300,7 +300,7 @@ void Browser::GetSelectedSongs(MPD::SongList &v)
|
|||||||
}
|
}
|
||||||
case itSong:
|
case itSong:
|
||||||
{
|
{
|
||||||
v.push_back(item.song);
|
v.push_back(*item.song);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case itPlaylist:
|
case itPlaylist:
|
||||||
@@ -344,7 +344,7 @@ void Browser::LocateSong(const MPD::Song &s)
|
|||||||
GetDirectory(s.getDirectory());
|
GetDirectory(s.getDirectory());
|
||||||
for (size_t i = 0; i < w->Size(); ++i)
|
for (size_t i = 0; i < w->Size(); ++i)
|
||||||
{
|
{
|
||||||
if ((*w)[i].type == itSong && s.getHash() == (*w)[i].song.getHash())
|
if ((*w)[i].type == itSong && s.getHash() == (*w)[i].song->getHash())
|
||||||
{
|
{
|
||||||
w->Highlight(i);
|
w->Highlight(i);
|
||||||
break;
|
break;
|
||||||
@@ -416,7 +416,7 @@ void Browser::GetDirectory(std::string dir, std::string subdir)
|
|||||||
bool bold = 0;
|
bool bold = 0;
|
||||||
for (size_t i = 0; i < myPlaylist->Items->Size(); ++i)
|
for (size_t i = 0; i < myPlaylist->Items->Size(); ++i)
|
||||||
{
|
{
|
||||||
if (myPlaylist->Items->at(i).getHash() == it->song.getHash())
|
if (myPlaylist->Items->at(i).getHash() == it->song->getHash())
|
||||||
{
|
{
|
||||||
bold = 1;
|
bold = 1;
|
||||||
break;
|
break;
|
||||||
@@ -477,11 +477,12 @@ void Browser::GetLocalDirectory(MPD::ItemList &v, const std::string &directory,
|
|||||||
{
|
{
|
||||||
new_item.type = itSong;
|
new_item.type = itSong;
|
||||||
mpd_pair file_pair = { "file", full_path.c_str() };
|
mpd_pair file_pair = { "file", full_path.c_str() };
|
||||||
new_item.song = MPD::Song(mpd_song_begin(&file_pair));
|
MPD::MutableSong *s = new MPD::MutableSong(mpd_song_begin(&file_pair));
|
||||||
|
new_item.song = std::shared_ptr<MPD::Song>(s);
|
||||||
# ifdef HAVE_TAGLIB_H
|
# ifdef HAVE_TAGLIB_H
|
||||||
// FIXME
|
// FIXME
|
||||||
//if (!recursively)
|
if (!recursively)
|
||||||
// TagEditor::ReadTags(*new_item.song);
|
TagEditor::ReadTags(*s);
|
||||||
# endif // HAVE_TAGLIB_H
|
# endif // HAVE_TAGLIB_H
|
||||||
v.push_back(new_item);
|
v.push_back(new_item);
|
||||||
}
|
}
|
||||||
@@ -558,7 +559,7 @@ bool Browser::DeleteItem(const MPD::Item &item)
|
|||||||
std::string path;
|
std::string path;
|
||||||
if (!isLocal())
|
if (!isLocal())
|
||||||
path = Config.mpd_music_dir;
|
path = Config.mpd_music_dir;
|
||||||
path += item.type == itSong ? item.song.getURI() : item.name;
|
path += item.type == itSong ? item.song->getURI() : item.name;
|
||||||
|
|
||||||
if (item.type == itDirectory)
|
if (item.type == itDirectory)
|
||||||
ClearDirectory(path);
|
ClearDirectory(path);
|
||||||
@@ -569,23 +570,9 @@ bool Browser::DeleteItem(const MPD::Item &item)
|
|||||||
|
|
||||||
void Browser::UpdateItemList()
|
void Browser::UpdateItemList()
|
||||||
{
|
{
|
||||||
bool bold = 0;
|
|
||||||
for (size_t i = 0; i < w->Size(); ++i)
|
for (size_t i = 0; i < w->Size(); ++i)
|
||||||
{
|
if ((*w)[i].type == itSong)
|
||||||
if (w->at(i).type == itSong)
|
w->Bold(i, myPlaylist->checkForSong(*(*w)[i].song));
|
||||||
{
|
|
||||||
for (size_t j = 0; j < myPlaylist->Items->Size(); ++j)
|
|
||||||
{
|
|
||||||
if (myPlaylist->Items->at(j).getHash() == w->at(i).song.getHash())
|
|
||||||
{
|
|
||||||
bold = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w->Bold(i, bold);
|
|
||||||
bold = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w->Refresh();
|
w->Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,9 +587,9 @@ std::string Browser::ItemToString(const MPD::Item &item, void *)
|
|||||||
case MPD::itSong:
|
case MPD::itSong:
|
||||||
{
|
{
|
||||||
if (!Config.columns_in_browser)
|
if (!Config.columns_in_browser)
|
||||||
return item.song.toString(Config.song_list_format_dollar_free);
|
return item.song->toString(Config.song_list_format_dollar_free);
|
||||||
else
|
else
|
||||||
return Playlist::SongInColumnsToString(item.song, 0);
|
return Playlist::SongInColumnsToString(*item.song, 0);
|
||||||
}
|
}
|
||||||
case MPD::itPlaylist:
|
case MPD::itPlaylist:
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class Browser : public Screen< Menu<MPD::Item> >
|
|||||||
virtual bool isTabbable() { return true; }
|
virtual bool isTabbable() { return true; }
|
||||||
|
|
||||||
virtual MPD::Song *CurrentSong();
|
virtual MPD::Song *CurrentSong();
|
||||||
virtual MPD::Song *GetSong(size_t pos) { return w->at(pos).type == MPD::itSong ? &(*w)[pos].song : 0; }
|
virtual MPD::Song *GetSong(size_t pos) { return w->at(pos).type == MPD::itSong ? (*w)[pos].song.get() : 0; }
|
||||||
|
|
||||||
virtual bool allowsSelection() { return true; }
|
virtual bool allowsSelection() { return true; }
|
||||||
virtual void ReverseSelection();
|
virtual void ReverseSelection();
|
||||||
|
|||||||
@@ -364,19 +364,14 @@ void Display::Items(const MPD::Item &item, void *data, Menu<MPD::Item> *menu)
|
|||||||
{
|
{
|
||||||
case MPD::itDirectory:
|
case MPD::itDirectory:
|
||||||
{
|
{
|
||||||
if (!item.song.empty())
|
|
||||||
{
|
|
||||||
*menu << "[..]";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*menu << "[" << getBasename(item.name) << "]";
|
*menu << "[" << getBasename(item.name) << "]";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case MPD::itSong:
|
case MPD::itSong:
|
||||||
if (!Config.columns_in_browser)
|
if (!Config.columns_in_browser)
|
||||||
Display::Songs(item.song, data, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
Display::Songs(*item.song, data, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||||
else
|
else
|
||||||
Display::SongsInColumns(item.song, data, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
Display::SongsInColumns(*item.song, data, reinterpret_cast<Menu<MPD::Song> *>(menu));
|
||||||
return;
|
return;
|
||||||
case MPD::itPlaylist:
|
case MPD::itPlaylist:
|
||||||
*menu << Config.browser_playlist_prefix << getBasename(item.name);
|
*menu << Config.browser_playlist_prefix << getBasename(item.name);
|
||||||
|
|||||||
@@ -1186,7 +1186,7 @@ void MPD::Connection::GetDirectory(const std::string &path, std::function<void(I
|
|||||||
it.type = itDirectory;
|
it.type = itDirectory;
|
||||||
break;
|
break;
|
||||||
case MPD_ENTITY_TYPE_SONG:
|
case MPD_ENTITY_TYPE_SONG:
|
||||||
it.song = Song(mpd_song_dup(mpd_entity_get_song(item)));
|
it.song = std::shared_ptr<Song>(new Song(mpd_song_dup(mpd_entity_get_song(item))));
|
||||||
it.type = itSong;
|
it.type = itSong;
|
||||||
break;
|
break;
|
||||||
case MPD_ENTITY_TYPE_PLAYLIST:
|
case MPD_ENTITY_TYPE_PLAYLIST:
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace MPD
|
|||||||
|
|
||||||
struct Item
|
struct Item
|
||||||
{
|
{
|
||||||
Song song;
|
std::shared_ptr<Song> song;
|
||||||
ItemType type;
|
ItemType type;
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -152,6 +152,20 @@ void MutableSong::setNewURI(const std::string &value)
|
|||||||
m_uri = value;
|
m_uri = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned MutableSong::getDuration() const
|
||||||
|
{
|
||||||
|
if (m_duration > 0)
|
||||||
|
return m_duration;
|
||||||
|
else
|
||||||
|
return Song::getDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MutableSong::setDuration(unsigned int duration)
|
||||||
|
{
|
||||||
|
m_duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
void MutableSong::setTag(SetFunction set, const std::string &value, const std::string &delimiter)
|
void MutableSong::setTag(SetFunction set, const std::string &value, const std::string &delimiter)
|
||||||
{
|
{
|
||||||
auto tags = split(value, delimiter);
|
auto tags = split(value, delimiter);
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ struct MutableSong : public Song
|
|||||||
{
|
{
|
||||||
typedef void (MutableSong::*SetFunction)(const std::string &, unsigned);
|
typedef void (MutableSong::*SetFunction)(const std::string &, unsigned);
|
||||||
|
|
||||||
MutableSong() { }
|
MutableSong() : m_duration(0) { }
|
||||||
MutableSong(Song s) : Song(s) { }
|
MutableSong(Song s) : Song(s), m_duration(0) { }
|
||||||
|
|
||||||
virtual std::string getArtist(unsigned idx = 0) const;
|
virtual std::string getArtist(unsigned idx = 0) const;
|
||||||
virtual std::string getTitle(unsigned idx = 0) const;
|
virtual std::string getTitle(unsigned idx = 0) const;
|
||||||
@@ -60,6 +60,9 @@ struct MutableSong : public Song
|
|||||||
const std::string &getNewURI() const;
|
const std::string &getNewURI() const;
|
||||||
void setNewURI(const std::string &value);
|
void setNewURI(const std::string &value);
|
||||||
|
|
||||||
|
virtual unsigned getDuration() const;
|
||||||
|
void setDuration(unsigned duration);
|
||||||
|
|
||||||
void setTag(SetFunction set, const std::string &value, const std::string &delimiter = "");
|
void setTag(SetFunction set, const std::string &value, const std::string &delimiter = "");
|
||||||
|
|
||||||
bool isModified() const;
|
bool isModified() const;
|
||||||
@@ -89,6 +92,7 @@ private:
|
|||||||
void replaceTag(mpd_tag_type tag_type, std::string &&orig_value, const std::string &value, unsigned idx);
|
void replaceTag(mpd_tag_type tag_type, std::string &&orig_value, const std::string &value, unsigned idx);
|
||||||
|
|
||||||
std::string m_uri;
|
std::string m_uri;
|
||||||
|
unsigned m_duration;
|
||||||
std::map<Tag, std::string> m_tags;
|
std::map<Tag, std::string> m_tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ std::string Song::getLength(unsigned idx) const
|
|||||||
assert(m_song);
|
assert(m_song);
|
||||||
if (idx > 0)
|
if (idx > 0)
|
||||||
return "";
|
return "";
|
||||||
unsigned len = mpd_song_get_duration(m_song.get());
|
unsigned len = getDuration();
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
return ShowTime(len);
|
return ShowTime(len);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -962,7 +962,8 @@ void TagEditor::ReadTags(MPD::MutableSong &s)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
TagLib::MPEG::File *mpegf = dynamic_cast<TagLib::MPEG::File *>(f.file());
|
TagLib::MPEG::File *mpegf = dynamic_cast<TagLib::MPEG::File *>(f.file());
|
||||||
|
s.setDuration(f.audioProperties()->length());
|
||||||
|
|
||||||
s.setArtist(f.tag()->artist().to8Bit(1));
|
s.setArtist(f.tag()->artist().to8Bit(1));
|
||||||
s.setTitle(f.tag()->title().to8Bit(1));
|
s.setTitle(f.tag()->title().to8Bit(1));
|
||||||
s.setAlbum(f.tag()->album().to8Bit(1));
|
s.setAlbum(f.tag()->album().to8Bit(1));
|
||||||
|
|||||||
@@ -55,13 +55,13 @@ bool CaseInsensitiveSorting::operator()(const MPD::Item &a, const MPD::Item &b)
|
|||||||
switch (Config.browser_sort_mode)
|
switch (Config.browser_sort_mode)
|
||||||
{
|
{
|
||||||
case smName:
|
case smName:
|
||||||
result = operator()(a.song, b.song);
|
result = operator()(*a.song, *b.song);
|
||||||
break;
|
break;
|
||||||
case smMTime:
|
case smMTime:
|
||||||
result = a.song.getMTime() > b.song.getMTime();
|
result = a.song->getMTime() > b.song->getMTime();
|
||||||
break;
|
break;
|
||||||
case smCustomFormat:
|
case smCustomFormat:
|
||||||
result = cmp(a.song.toString(Config.browser_sort_format), b.song.toString(Config.browser_sort_format)) < 0;
|
result = cmp(a.song->toString(Config.browser_sort_format), b.song->toString(Config.browser_sort_format)) < 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user