[DB] Switched from ffmpeg to TagLib in order to get tags

This commit is contained in:
emeric
2016-05-02 19:58:27 +02:00
parent 2975d87889
commit 6f973096f3
17 changed files with 567 additions and 39 deletions
+56 -25
View File
@@ -34,41 +34,44 @@ Classifier::Classifier(Wt::Dbo::SqlConnectionPool& connectionPool)
{}
void
Classifier::processTrackUpdate(bool added, Track::id_type trackId)
Classifier::processTrackUpdate(bool added, Track::id_type trackId, std::string mbid, boost::filesystem::path path)
{
if (!added)
return;
LMS_LOG(DBUPDATER, DEBUG) << "Processing track id " << trackId;
boost::filesystem::path path;
if (mbid.empty())
{
Wt::Dbo::Transaction transaction(_db.getSession());
Track::pointer track = Database::Track::getById(_db.getSession(), trackId);
if (!track)
return;
path = track->getPath();
// Remove outdated features
for (auto feature : track->getFeatures())
feature.remove();
// TODO compute from file
LMS_LOG(CLASSIFICATION, INFO) << "File '" << path << "' has no MBID: skipping feature extraction";
return;
}
boost::property_tree::ptree pt;
if (!::Feature::Extractor::getLowLevel(pt, path))
return;
std::ostringstream oss;
boost::property_tree::write_json(oss, pt);
if (::Feature::Extractor::getLowLevel(pt, mbid))
{
Wt::Dbo::Transaction transaction(_db.getSession());
std::ostringstream oss;
boost::property_tree::write_json(oss, pt);
Track::pointer track = Database::Track::getById(_db.getSession(), trackId);
Feature::pointer feature = Feature::create( _db.getSession(), track, "low_level", oss.str());
{
Wt::Dbo::Transaction transaction(_db.getSession());
Track::pointer track = Database::Track::getById(_db.getSession(), trackId);
Feature::create( _db.getSession(), track, "low_level", oss.str());
}
}
pt.clear();
if (::Feature::Extractor::getHighLevel(pt, mbid))
{
std::ostringstream oss;
boost::property_tree::write_json(oss, pt);
{
Wt::Dbo::Transaction transaction(_db.getSession());
Track::pointer track = Database::Track::getById(_db.getSession(), trackId);
Feature::create( _db.getSession(), track, "high_level", oss.str());
}
}
}
@@ -816,11 +819,39 @@ Classifier::processDatabaseUpdate(Updater::Stats stats)
trackClusters[coordinates.first][coordinates.second].push_back({trackIds[id], entry, maxValue});
}
// Create clusters
LMS_LOG(DBUPDATER, DEBUG) << "Erasing old clusters";
{
Wt::Dbo::Transaction transaction(_db.getSession());
Cluster::removeByType(_db.getSession(), "similarity");
}
LMS_LOG(DBUPDATER, DEBUG) << "Creating new cluster...";
for (std::size_t i = 0; i < nbRows; i++)
{
for (std::size_t j = 0; j < nbColumns; j++)
{
LMS_LOG(DBUPDATER, DEBUG) << "Creating cluster " << i << " " << j;
Wt::Dbo::Transaction transaction(_db.getSession());
Cluster::pointer cluster = Cluster::create(_db.getSession(), "similarity", "cluster_" + std::to_string(i) + "_" + std::to_string(j));
for (auto track : trackClusters[i][j])
{
Track::pointer t = Database::Track::getById(_db.getSession(), track.trackId);
cluster.modify()->addTrack(t);
}
}
}
for (std::size_t i = 0; i < nbRows; i++)
{
for (std::size_t j = 0; j < nbColumns; j++)
{
std::cout << "Cluster [" << i << "," << j << "] - ";
// Display the neuron for this cluster
+1 -1
View File
@@ -42,7 +42,7 @@ class Classifier
public:
Classifier(Wt::Dbo::SqlConnectionPool& connectionPool);
void processTrackUpdate(bool added, Track::id_type trackId);
void processTrackUpdate(bool added, Track::id_type trackId, std::string mbid, boost::filesystem::path p);
void processDatabaseUpdate(Updater::Stats stats);
private:
+2
View File
@@ -103,9 +103,11 @@ Handler::Handler(Wt::Dbo::SqlConnectionPool& connectionPool)
_session.execute("CREATE INDEX artist_name_idx ON artist(name)");
_session.execute("CREATE INDEX cluster_name_idx ON cluster(name)");
_session.execute("CREATE INDEX cluster_type_idx ON cluster(type)");
_session.execute("CREATE INDEX cluster_name_type_idx ON cluster(name, type)");
_session.execute("CREATE INDEX release_name_idx ON release(name)");
_session.execute("CREATE INDEX track_name_idx ON track(name)");
_session.execute("CREATE INDEX feature_type_idx ON feature(type)");
_session.execute("CREATE INDEX feature_track_type_idx ON feature(track_id,type)");
}
catch(std::exception& e) {
LMS_LOG(DB, ERROR) << "Cannot create tables: " << e.what();
+11 -3
View File
@@ -537,6 +537,14 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
else
{
LMS_LOG(DBUPDATER, INFO) << "Updating '" << file << "'";
// TODO Remove the songs from its clusters
// TODO Remove the features of this song
track.remove();
track.flush();
track = Track::create(_db->getSession(), file);
stats.nbModified++;
}
@@ -589,9 +597,9 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
track.modify()->setDate( boost::any_cast<boost::posix_time::ptime>(items[MetaData::Type::OriginalDate]) );
}
if (items.find(MetaData::Type::MusicBrainzTrackID) != items.end())
if (items.find(MetaData::Type::MusicBrainzRecordingID) != items.end())
{
track.modify()->setMBID( boost::any_cast<std::string>(items[MetaData::Type::MusicBrainzTrackID]) );
track.modify()->setMBID( boost::any_cast<std::string>(items[MetaData::Type::MusicBrainzRecordingID]) );
}
if (items.find(MetaData::Type::HasCover) != items.end())
@@ -603,7 +611,7 @@ Updater::processAudioFile( const boost::filesystem::path& file, Stats& stats)
transaction.commit();
_sigTrackChanged.emit(true, track.id());
_sigTrackChanged.emit(true, track.id(), track->getMBID(), track->getPath());
}
+11 -7
View File
@@ -19,14 +19,14 @@
#pragma once
#include <Wt/WIOService>
#include <Wt/WSignal>
#include <mutex>
#include <boost/asio/deadline_timer.hpp>
#include "metadata/AvFormat.hpp"
#include <Wt/WIOService>
#include <Wt/WSignal>
#include "metadata/TagLibParser.hpp"
#include "database/DatabaseHandler.hpp"
@@ -65,7 +65,11 @@ class Updater
// Emitted when a track changed
// true -> added or modified, false -> to be deleted
Wt::Signal<bool, Track::id_type>& trackChanged() { return _sigTrackChanged; }
// id of the track
// musicbrainz recordid
// path of the track
typedef Wt::Signal<bool, Track::id_type, std::string, boost::filesystem::path> SigTrackChanged;
SigTrackChanged& trackChanged() { return _sigTrackChanged; }
std::mutex& getMutex(void) { return _mutex; }
@@ -117,7 +121,7 @@ class Updater
Wt::Signal<Stats> _sigScanComplete;
Wt::Signal<bool, Artist::id_type> _sigArtistChanged;
Wt::Signal<bool, Release::id_type> _sigReleaseChanged;
Wt::Signal<bool, Track::id_type> _sigTrackChanged;
SigTrackChanged _sigTrackChanged;
std::mutex _mutex;
boost::asio::deadline_timer _scheduleTimer;
@@ -127,7 +131,7 @@ class Updater
std::vector<boost::filesystem::path> _audioFileExtensions;
std::vector<boost::filesystem::path> _videoFileExtensions;
MetaData::AvFormat _metadataParser;
MetaData::TagLibParser _metadataParser;
}; // class Updater
+7 -1
View File
@@ -247,6 +247,13 @@ Cluster::create(Wt::Dbo::Session& session, std::string type, std::string name)
return session.add(new Cluster(type, name));
}
void
Cluster::removeByType(Wt::Dbo::Session& session, std::string type)
{
session.execute( "DELETE FROM cluster WHERE type = ?").bind(type);
}
Wt::Dbo::Query<Cluster::pointer>
Cluster::getQuery(Wt::Dbo::Session& session, SearchFilter filter)
{
@@ -318,6 +325,5 @@ Feature::getByTrack(Wt::Dbo::Session& session, Track::id_type trackId, const std
return std::vector<pointer>(res.begin(), res.end());
}
} // namespace Database
+5
View File
@@ -55,6 +55,7 @@ class Cluster
static pointer getNone(Wt::Dbo::Session& session);
static std::vector<pointer> getByFilter(Wt::Dbo::Session& session, SearchFilter filter, int offset = -1, int size = -1);
static Wt::Dbo::collection<pointer> getAll(Wt::Dbo::Session& session);
static Wt::Dbo::collection<pointer> getByType(Wt::Dbo::Session& session, std::stirng type);
// MVC models for the user interface
// ClusterID, type, name, track count
@@ -65,12 +66,16 @@ class Cluster
// Create utility
static pointer create(Wt::Dbo::Session& session, std::string type, std::string name);
// Remove utility
static void removeByType(Wt::Dbo::Session& session, std::string type);
// Accessors
const std::string& getName(void) const { return _name; }
const std::string& getType(void) const { return _type; }
bool isNone(void) const;
const Wt::Dbo::collection< Wt::Dbo::ptr<Track> >& getTracks() const { return _tracks;}
void addTrack(Wt::Dbo::dbo_traits<Track>::IdType trackId);
void addTrack(Wt::Dbo::ptr<Track> track) { _tracks.insert(track); }
template<class Action>