Better handling of date/year in tags
This commit is contained in:
@@ -168,8 +168,7 @@ Artist::getReleases(const std::set<id_type>& clusterIds) const
|
|||||||
if (!clusterIds.empty())
|
if (!clusterIds.empty())
|
||||||
oss << " GROUP BY t.id HAVING COUNT(*) = " << clusterIds.size();
|
oss << " GROUP BY t.id HAVING COUNT(*) = " << clusterIds.size();
|
||||||
|
|
||||||
// TODO order
|
oss << " ORDER BY t.year,r.name";
|
||||||
oss << " ORDER BY t.date,r.name";
|
|
||||||
|
|
||||||
Wt::Dbo::Query<Release::pointer> query = session()->query<Release::pointer>( oss.str() );
|
Wt::Dbo::Query<Release::pointer> query = session()->query<Release::pointer>( oss.str() );
|
||||||
|
|
||||||
|
|||||||
@@ -139,10 +139,12 @@ Release::getReleaseYear(bool original) const
|
|||||||
{
|
{
|
||||||
assert(session());
|
assert(session());
|
||||||
|
|
||||||
Wt::Dbo::collection<Wt::WDate> dates = session()->query<Wt::WDate>(
|
std::string field = original ? "t.original_year" : "t.year";
|
||||||
std::string("SELECT ") + (original ? "t.original_date" : "t.date") + " FROM track t INNER JOIN release r ON r.id = t.release_id")
|
|
||||||
|
Wt::Dbo::collection<int> dates = session()->query<int>(
|
||||||
|
std::string("SELECT ") + field + " FROM track t INNER JOIN release r ON r.id = t.release_id")
|
||||||
.where("r.id = ?")
|
.where("r.id = ?")
|
||||||
.groupBy("t.date")
|
.groupBy(field)
|
||||||
.bind(this->id());
|
.bind(this->id());
|
||||||
|
|
||||||
/* various dates, no date */
|
/* various dates, no date */
|
||||||
@@ -151,10 +153,10 @@ Release::getReleaseYear(bool original) const
|
|||||||
|
|
||||||
auto date = dates.front();
|
auto date = dates.front();
|
||||||
|
|
||||||
if (!date.isValid())
|
if (date > 0)
|
||||||
|
return date;
|
||||||
|
else
|
||||||
return boost::none;
|
return boost::none;
|
||||||
|
|
||||||
return date.year();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Wt::Dbo::ptr<Artist>>
|
std::vector<Wt::Dbo::ptr<Artist>>
|
||||||
|
|||||||
+12
-6
@@ -27,12 +27,7 @@ namespace Database {
|
|||||||
|
|
||||||
Track::Track(const boost::filesystem::path& p)
|
Track::Track(const boost::filesystem::path& p)
|
||||||
:
|
:
|
||||||
_trackNumber(0),
|
_filePath( p.string() )
|
||||||
_totalTrackNumber(0),
|
|
||||||
_discNumber(0),
|
|
||||||
_totalDiscNumber(0),
|
|
||||||
_filePath( p.string() ),
|
|
||||||
_coverType(CoverType::None)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +196,17 @@ Track::getTotalDiscNumber(void) const
|
|||||||
return (_totalDiscNumber > 0) ? boost::make_optional<std::size_t>(_totalDiscNumber) : boost::none;
|
return (_totalDiscNumber > 0) ? boost::make_optional<std::size_t>(_totalDiscNumber) : boost::none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::optional<int>
|
||||||
|
Track::getYear() const
|
||||||
|
{
|
||||||
|
return (_year > 0) ? boost::make_optional<int>(_year) : boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<int>
|
||||||
|
Track::getOriginalYear() const
|
||||||
|
{
|
||||||
|
return (_originalYear > 0) ? boost::make_optional<int>(_originalYear) : boost::none;
|
||||||
|
}
|
||||||
|
|
||||||
Cluster::Cluster()
|
Cluster::Cluster()
|
||||||
{
|
{
|
||||||
|
|||||||
+14
-14
@@ -171,8 +171,8 @@ class Track
|
|||||||
void setLastWriteTime(Wt::WDateTime time) { _fileLastWrite = time; }
|
void setLastWriteTime(Wt::WDateTime time) { _fileLastWrite = time; }
|
||||||
void setAddedTime(Wt::WDateTime time) { _fileAdded = time; }
|
void setAddedTime(Wt::WDateTime time) { _fileAdded = time; }
|
||||||
void setChecksum(const std::vector<unsigned char>& checksum) { _fileChecksum = checksum; }
|
void setChecksum(const std::vector<unsigned char>& checksum) { _fileChecksum = checksum; }
|
||||||
void setDate(Wt::WDate date) { _date = date; }
|
void setYear(int year) { _year = year; }
|
||||||
void setOriginalDate(Wt::WDate date) { _originalDate = date; }
|
void setOriginalYear(int year) { _originalYear = year; }
|
||||||
void setGenres(const std::string& genreList) { _genreList = genreList; }
|
void setGenres(const std::string& genreList) { _genreList = genreList; }
|
||||||
void setCoverType(CoverType coverType) { _coverType = coverType; }
|
void setCoverType(CoverType coverType) { _coverType = coverType; }
|
||||||
void setMBID(const std::string& MBID) { _MBID = MBID; }
|
void setMBID(const std::string& MBID) { _MBID = MBID; }
|
||||||
@@ -186,8 +186,8 @@ class Track
|
|||||||
std::string getName(void) const { return _name; }
|
std::string getName(void) const { return _name; }
|
||||||
boost::filesystem::path getPath(void) const { return _filePath; }
|
boost::filesystem::path getPath(void) const { return _filePath; }
|
||||||
std::chrono::milliseconds getDuration(void) const { return _duration; }
|
std::chrono::milliseconds getDuration(void) const { return _duration; }
|
||||||
Wt::WDate getDate(void) const { return _date; }
|
boost::optional<int> getYear(void) const;
|
||||||
Wt::WDate getOriginalDate(void) const { return _originalDate; }
|
boost::optional<int> getOriginalYear(void) const;
|
||||||
Wt::WDateTime getLastWriteTime(void) const { return _fileLastWrite; }
|
Wt::WDateTime getLastWriteTime(void) const { return _fileLastWrite; }
|
||||||
Wt::WDateTime getAddedTime(void) const { return _fileAdded; }
|
Wt::WDateTime getAddedTime(void) const { return _fileAdded; }
|
||||||
const std::vector<unsigned char>& getChecksum(void) const { return _fileChecksum; }
|
const std::vector<unsigned char>& getChecksum(void) const { return _fileChecksum; }
|
||||||
@@ -206,8 +206,8 @@ class Track
|
|||||||
Wt::Dbo::field(a, _totalDiscNumber, "total_disc_number");
|
Wt::Dbo::field(a, _totalDiscNumber, "total_disc_number");
|
||||||
Wt::Dbo::field(a, _name, "name");
|
Wt::Dbo::field(a, _name, "name");
|
||||||
Wt::Dbo::field(a, _duration, "duration");
|
Wt::Dbo::field(a, _duration, "duration");
|
||||||
Wt::Dbo::field(a, _date, "date");
|
Wt::Dbo::field(a, _year, "year");
|
||||||
Wt::Dbo::field(a, _originalDate, "original_date");
|
Wt::Dbo::field(a, _originalYear, "original_year");
|
||||||
Wt::Dbo::field(a, _genreList, "genre_list");
|
Wt::Dbo::field(a, _genreList, "genre_list");
|
||||||
Wt::Dbo::field(a, _filePath, "file_path");
|
Wt::Dbo::field(a, _filePath, "file_path");
|
||||||
Wt::Dbo::field(a, _fileLastWrite, "file_last_write");
|
Wt::Dbo::field(a, _fileLastWrite, "file_last_write");
|
||||||
@@ -225,23 +225,23 @@ class Track
|
|||||||
|
|
||||||
static const std::size_t _maxNameLength = 128;
|
static const std::size_t _maxNameLength = 128;
|
||||||
|
|
||||||
int _trackNumber;
|
int _trackNumber = 0;
|
||||||
int _totalTrackNumber;
|
int _totalTrackNumber = 0;
|
||||||
int _discNumber;
|
int _discNumber = 0;
|
||||||
int _totalDiscNumber;
|
int _totalDiscNumber = 0;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
std::string _artistName;
|
std::string _artistName;
|
||||||
std::string _releaseName;
|
std::string _releaseName;
|
||||||
std::chrono::duration<int, std::milli> _duration;
|
std::chrono::duration<int, std::milli> _duration;
|
||||||
Wt::WDate _date;
|
int _year = 0;
|
||||||
Wt::WDate _originalDate; // original date time
|
int _originalYear = 0;
|
||||||
std::string _genreList;
|
std::string _genreList;
|
||||||
std::string _filePath;
|
std::string _filePath;
|
||||||
std::vector<unsigned char> _fileChecksum;
|
std::vector<unsigned char> _fileChecksum;
|
||||||
Wt::WDateTime _fileLastWrite;
|
Wt::WDateTime _fileLastWrite;
|
||||||
Wt::WDateTime _fileAdded;
|
Wt::WDateTime _fileAdded;
|
||||||
CoverType _coverType;
|
CoverType _coverType = CoverType::None;
|
||||||
std::string _MBID; // Musicbrainz Identifier
|
std::string _MBID = ""; // Musicbrainz Identifier
|
||||||
|
|
||||||
Wt::Dbo::ptr<Artist> _artist;
|
Wt::Dbo::ptr<Artist> _artist;
|
||||||
Wt::Dbo::ptr<Release> _release;
|
Wt::Dbo::ptr<Release> _release;
|
||||||
|
|||||||
@@ -124,16 +124,16 @@ AvFormat::parse(const boost::filesystem::path& p)
|
|||||||
|| tag == "YEAR"
|
|| tag == "YEAR"
|
||||||
|| tag == "WM/Year")
|
|| tag == "WM/Year")
|
||||||
{
|
{
|
||||||
auto date = readAs<Wt::WDate>(value);
|
auto date = readAs<int>(value);
|
||||||
if (date)
|
if (date)
|
||||||
items.insert( std::make_pair(MetaData::Type::Date, *date));
|
items.insert(std::make_pair(MetaData::Type::Year, *date));
|
||||||
}
|
}
|
||||||
else if (tag == "TDOR" // Original release time (ID3v2 2.4)
|
else if (tag == "TDOR" // Original release time (ID3v2 2.4)
|
||||||
|| tag == "TORY") // Original release year
|
|| tag == "TORY") // Original release year
|
||||||
{
|
{
|
||||||
auto date = readAs<Wt::WDate>(value);
|
auto date = readAs<int>(value);
|
||||||
if (date)
|
if (date)
|
||||||
items.insert( std::make_pair(MetaData::Type::OriginalDate, *date));
|
items.insert(std::make_pair(MetaData::Type::OriginalYear, *date));
|
||||||
}
|
}
|
||||||
else if (tag == "MUSICBRAINZ ARTIST ID"
|
else if (tag == "MUSICBRAINZ ARTIST ID"
|
||||||
|| tag == "MUSICBRAINZ_ARTISTID")
|
|| tag == "MUSICBRAINZ_ARTISTID")
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ namespace MetaData
|
|||||||
DiscNumber, // size_t
|
DiscNumber, // size_t
|
||||||
TotalTrack, // size_t
|
TotalTrack, // size_t
|
||||||
TotalDisc, // size_t
|
TotalDisc, // size_t
|
||||||
Date, // Wt::WDate
|
Year, // int
|
||||||
OriginalDate, // Wt::WDate
|
OriginalYear, // int
|
||||||
HasCover, // bool
|
HasCover, // bool
|
||||||
AudioStreams, // vector<AudioStream>
|
AudioStreams, // vector<AudioStream>
|
||||||
MusicBrainzArtistID, // string
|
MusicBrainzArtistID, // string
|
||||||
|
|||||||
@@ -156,28 +156,29 @@ TagLibParser::parse(const boost::filesystem::path& p)
|
|||||||
}
|
}
|
||||||
else if (tag == "DATE")
|
else if (tag == "DATE")
|
||||||
{
|
{
|
||||||
auto timePoint = readAs<Wt::WDate>(values.front().to8Bit());
|
auto timePoint = readAs<int>(values.front().to8Bit());
|
||||||
if (timePoint)
|
if (timePoint)
|
||||||
items.insert( std::make_pair(MetaData::Type::Date, *timePoint));
|
items.insert( std::make_pair(MetaData::Type::Year, *timePoint));
|
||||||
}
|
}
|
||||||
else if (tag == "ORIGINALDATE")
|
else if (tag == "ORIGINALDATE")
|
||||||
{
|
{
|
||||||
auto timePoint = readAs<Wt::WDate>(values.front().to8Bit());
|
// lower priority than original year
|
||||||
if (timePoint)
|
if (items.find(MetaData::Type::OriginalYear) == items.end())
|
||||||
{
|
{
|
||||||
// Take priority on original year
|
auto timePoint = readAs<int>(values.front().to8Bit());
|
||||||
items.erase( MetaData::Type::OriginalDate );
|
if (timePoint)
|
||||||
items.insert( std::make_pair(MetaData::Type::OriginalDate, *timePoint));
|
items.insert( std::make_pair(MetaData::Type::OriginalYear, *timePoint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tag == "ORIGINALYEAR")
|
else if (tag == "ORIGINALYEAR")
|
||||||
{
|
{
|
||||||
// lower priority than original date
|
auto timePoint = readAs<int>(values.front().to8Bit());
|
||||||
if (items.find(MetaData::Type::OriginalDate) == items.end())
|
if (timePoint)
|
||||||
{
|
{
|
||||||
auto timePoint = readAs<Wt::WDate>(values.front().to8Bit());
|
// Take priority on original year
|
||||||
if (timePoint)
|
items[MetaData::Type::OriginalYear] = *timePoint;
|
||||||
items.insert( std::make_pair(MetaData::Type::OriginalDate, *timePoint));
|
// items.erase( MetaData::Type::OriginalYear );
|
||||||
|
// items.insert( std::make_pair(MetaData::Type::OriginalYear, *timePoint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tag == "METADATA_BLOCK_PICTURE")
|
else if (tag == "METADATA_BLOCK_PICTURE")
|
||||||
|
|||||||
@@ -570,16 +570,16 @@ MediaScanner::scanAudioFile( const boost::filesystem::path& file, Stats& stats)
|
|||||||
if ((*items).find(MetaData::Type::TotalDisc) != (*items).end())
|
if ((*items).find(MetaData::Type::TotalDisc) != (*items).end())
|
||||||
track.modify()->setTotalDiscNumber( boost::any_cast<std::size_t>((*items)[MetaData::Type::TotalDisc]) );
|
track.modify()->setTotalDiscNumber( boost::any_cast<std::size_t>((*items)[MetaData::Type::TotalDisc]) );
|
||||||
|
|
||||||
if ((*items).find(MetaData::Type::Date) != (*items).end())
|
if ((*items).find(MetaData::Type::Year) != (*items).end())
|
||||||
track.modify()->setDate( boost::any_cast<Wt::WDate>((*items)[MetaData::Type::Date]) );
|
track.modify()->setYear( boost::any_cast<int>((*items)[MetaData::Type::Year]) );
|
||||||
|
|
||||||
if ((*items).find(MetaData::Type::OriginalDate) != (*items).end())
|
if ((*items).find(MetaData::Type::OriginalYear) != (*items).end())
|
||||||
{
|
{
|
||||||
track.modify()->setOriginalDate( boost::any_cast<Wt::WDate>((*items)[MetaData::Type::OriginalDate]) );
|
track.modify()->setOriginalYear( boost::any_cast<int>((*items)[MetaData::Type::OriginalYear]) );
|
||||||
|
|
||||||
// If a file has an OriginalDate but no date, set the date to ease filtering
|
// If a file has an OriginalYear but no Year, set it o ease filtering
|
||||||
if ((*items).find(MetaData::Type::Date) == (*items).end())
|
if ((*items).find(MetaData::Type::Year) == (*items).end())
|
||||||
track.modify()->setDate( boost::any_cast<Wt::WDate>((*items)[MetaData::Type::OriginalDate]) );
|
track.modify()->setYear( boost::any_cast<int>((*items)[MetaData::Type::OriginalYear]) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*items).find(MetaData::Type::MusicBrainzRecordingID) != (*items).end())
|
if ((*items).find(MetaData::Type::MusicBrainzRecordingID) != (*items).end())
|
||||||
|
|||||||
+1
-25
@@ -23,33 +23,9 @@
|
|||||||
|
|
||||||
#include <boost/algorithm/string/split.hpp>
|
#include <boost/algorithm/string/split.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <iostream>
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
|
|
||||||
template<>
|
|
||||||
boost::optional<Wt::WDate> readAs(const std::string& str)
|
|
||||||
{
|
|
||||||
const std::vector<std::string> formats = {
|
|
||||||
"yyyy-MM-dd",
|
|
||||||
"yyyy/MM/dd",
|
|
||||||
"yyyy-MM",
|
|
||||||
"yyyy/MM",
|
|
||||||
"yyyy"
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto format : formats)
|
|
||||||
{
|
|
||||||
auto date = Wt::WDate::fromString(str, format);
|
|
||||||
|
|
||||||
if (!date.isValid())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return date;
|
|
||||||
}
|
|
||||||
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool readList(const std::string& str, const std::string& separators, std::list<std::string>& results)
|
bool readList(const std::string& str, const std::string& separators, std::list<std::string>& results)
|
||||||
{
|
{
|
||||||
std::string curStr;
|
std::string curStr;
|
||||||
|
|||||||
@@ -57,7 +57,3 @@ boost::optional<T> readAs(const std::string& str)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
|
||||||
boost::optional<Wt::WDate> readAs(const std::string& str);
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -86,12 +86,12 @@ int main(int argc, char *argv[])
|
|||||||
std::cout << "TotalDisc: " << boost::any_cast<std::size_t>(item.second) << std::endl;
|
std::cout << "TotalDisc: " << boost::any_cast<std::size_t>(item.second) << std::endl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MetaData::Type::Date:
|
case MetaData::Type::Year:
|
||||||
std::cout << "Date: " << boost::any_cast<Wt::WDate>(item.second).toString() << std::endl;
|
std::cout << "Year: " << std::to_string(boost::any_cast<int>(item.second)) << std::endl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MetaData::Type::OriginalDate:
|
case MetaData::Type::OriginalYear:
|
||||||
std::cout << "Original date: " << boost::any_cast<Wt::WDate>(item.second).toString() << std::endl;
|
std::cout << "Original year: " << std::to_string(boost::any_cast<int>(item.second)) << std::endl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MetaData::Type::HasCover:
|
case MetaData::Type::HasCover:
|
||||||
|
|||||||
Reference in New Issue
Block a user