Collectionwatcher: sink PerformEBUR128Analysis() into ScanNewFile & friends
This commit is contained in:
committed by
Jonas Kvinge
parent
1462bfa297
commit
bda2b91c92
@@ -610,20 +610,12 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SongList songs;
|
|
||||||
|
|
||||||
if (new_cue.isEmpty() || new_cue_mtime == 0) { // If no CUE or it's about to lose it.
|
if (new_cue.isEmpty() || new_cue_mtime == 0) { // If no CUE or it's about to lose it.
|
||||||
songs.append(UpdateNonCueAssociatedSong(file, fingerprint, matching_songs, art_automatic, cue_deleted, t));
|
UpdateNonCueAssociatedSong(file, fingerprint, matching_songs, art_automatic, cue_deleted, t);
|
||||||
}
|
}
|
||||||
else { // If CUE associated.
|
else { // If CUE associated.
|
||||||
songs = UpdateCueAssociatedSongs(file, path, fingerprint, new_cue, art_automatic, matching_songs, t);
|
UpdateCueAssociatedSongs(file, path, fingerprint, new_cue, art_automatic, matching_songs, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_EBUR128
|
|
||||||
if (song_ebur128_loudness_analysis_) {
|
|
||||||
PerformEBUR128Analysis(songs, t);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing has changed - mark the song available without re-scanning
|
// Nothing has changed - mark the song available without re-scanning
|
||||||
@@ -698,14 +690,6 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||||||
|
|
||||||
qLog(Debug) << file << "is new.";
|
qLog(Debug) << file << "is new.";
|
||||||
|
|
||||||
#ifdef HAVE_EBUR128
|
|
||||||
if (song_ebur128_loudness_analysis_) {
|
|
||||||
// We don't pass `ScanTransaction*` here because later on
|
|
||||||
// all the songs will be addede to `t->new_songs` unconditionally.
|
|
||||||
PerformEBUR128Analysis(songs, nullptr);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Choose art for the song(s)
|
// Choose art for the song(s)
|
||||||
const QUrl art_automatic = ArtForSong(file, album_art);
|
const QUrl art_automatic = ArtForSong(file, album_art);
|
||||||
|
|
||||||
@@ -753,13 +737,13 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const CollectionSu
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionWatcher::UpdateCueAssociatedSongs(const QString &file,
|
void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file,
|
||||||
const QString &path,
|
const QString &path,
|
||||||
const QString &fingerprint,
|
const QString &fingerprint,
|
||||||
const QString &matching_cue,
|
const QString &matching_cue,
|
||||||
const QUrl &art_automatic,
|
const QUrl &art_automatic,
|
||||||
const SongList &old_cue_songs,
|
const SongList &old_cue_songs,
|
||||||
ScanTransaction *t) {
|
ScanTransaction *t) {
|
||||||
|
|
||||||
QHash<quint64, Song> sections_map;
|
QHash<quint64, Song> sections_map;
|
||||||
for (const Song &song : old_cue_songs) {
|
for (const Song &song : old_cue_songs) {
|
||||||
@@ -768,10 +752,10 @@ SongList CollectionWatcher::UpdateCueAssociatedSongs(const QString &file,
|
|||||||
|
|
||||||
// Load new CUE songs
|
// Load new CUE songs
|
||||||
QFile cue_file(matching_cue);
|
QFile cue_file(matching_cue);
|
||||||
if (!cue_file.exists()) return SongList();
|
if (!cue_file.exists()) return;
|
||||||
if (!cue_file.open(QIODevice::ReadOnly)) {
|
if (!cue_file.open(QIODevice::ReadOnly)) {
|
||||||
qLog(Error) << "Could not open CUE file" << matching_cue << "for reading:" << cue_file.errorString();
|
qLog(Error) << "Could not open CUE file" << matching_cue << "for reading:" << cue_file.errorString();
|
||||||
return SongList();
|
return;
|
||||||
}
|
}
|
||||||
const SongList songs = cue_parser_->Load(&cue_file, matching_cue, path, false);
|
const SongList songs = cue_parser_->Load(&cue_file, matching_cue, path, false);
|
||||||
cue_file.close();
|
cue_file.close();
|
||||||
@@ -781,6 +765,7 @@ SongList CollectionWatcher::UpdateCueAssociatedSongs(const QString &file,
|
|||||||
for (Song new_cue_song : songs) {
|
for (Song new_cue_song : songs) {
|
||||||
new_cue_song.set_source(source_);
|
new_cue_song.set_source(source_);
|
||||||
new_cue_song.set_directory_id(t->dir());
|
new_cue_song.set_directory_id(t->dir());
|
||||||
|
PerformEBUR128Analysis(new_cue_song);
|
||||||
new_cue_song.set_fingerprint(fingerprint);
|
new_cue_song.set_fingerprint(fingerprint);
|
||||||
|
|
||||||
if (sections_map.contains(new_cue_song.beginning_nanosec())) { // Changed section
|
if (sections_map.contains(new_cue_song.beginning_nanosec())) { // Changed section
|
||||||
@@ -802,12 +787,9 @@ SongList CollectionWatcher::UpdateCueAssociatedSongs(const QString &file,
|
|||||||
t->deleted_songs << old_cue;
|
t->deleted_songs << old_cue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return songs;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Song CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file,
|
void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file,
|
||||||
const QString &fingerprint,
|
const QString &fingerprint,
|
||||||
const SongList &matching_songs,
|
const SongList &matching_songs,
|
||||||
const QUrl &art_automatic,
|
const QUrl &art_automatic,
|
||||||
@@ -830,14 +812,13 @@ Song CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file,
|
|||||||
song_on_disk.set_source(source_);
|
song_on_disk.set_source(source_);
|
||||||
song_on_disk.set_directory_id(t->dir());
|
song_on_disk.set_directory_id(t->dir());
|
||||||
song_on_disk.set_id(matching_song.id());
|
song_on_disk.set_id(matching_song.id());
|
||||||
|
PerformEBUR128Analysis(song_on_disk);
|
||||||
song_on_disk.set_fingerprint(fingerprint);
|
song_on_disk.set_fingerprint(fingerprint);
|
||||||
song_on_disk.set_art_automatic(art_automatic);
|
song_on_disk.set_art_automatic(art_automatic);
|
||||||
song_on_disk.MergeUserSetData(matching_song, !overwrite_playcount_, !overwrite_rating_);
|
song_on_disk.MergeUserSetData(matching_song, !overwrite_playcount_, !overwrite_rating_);
|
||||||
AddChangedSong(file, matching_song, song_on_disk, t);
|
AddChangedSong(file, matching_song, song_on_disk, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
return song_on_disk;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path, const QString &fingerprint, const QString &matching_cue, QSet<QString> *cues_processed) {
|
SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path, const QString &fingerprint, const QString &matching_cue, QSet<QString> *cues_processed) {
|
||||||
@@ -867,6 +848,7 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
|
|||||||
songs.reserve(cue_congs.count());
|
songs.reserve(cue_congs.count());
|
||||||
for (Song &cue_song : cue_congs) {
|
for (Song &cue_song : cue_congs) {
|
||||||
cue_song.set_source(source_);
|
cue_song.set_source(source_);
|
||||||
|
PerformEBUR128Analysis(cue_song);
|
||||||
cue_song.set_fingerprint(fingerprint);
|
cue_song.set_fingerprint(fingerprint);
|
||||||
if (cue_song.url().toLocalFile().normalized(QString::NormalizationForm_D) == file_nfd) {
|
if (cue_song.url().toLocalFile().normalized(QString::NormalizationForm_D) == file_nfd) {
|
||||||
songs << cue_song;
|
songs << cue_song;
|
||||||
@@ -881,6 +863,7 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
|
|||||||
TagReaderClient::Instance()->ReadFileBlocking(file, &song);
|
TagReaderClient::Instance()->ReadFileBlocking(file, &song);
|
||||||
if (song.is_valid()) {
|
if (song.is_valid()) {
|
||||||
song.set_source(source_);
|
song.set_source(source_);
|
||||||
|
PerformEBUR128Analysis(song);
|
||||||
song.set_fingerprint(fingerprint);
|
song.set_fingerprint(fingerprint);
|
||||||
songs << song;
|
songs << song;
|
||||||
}
|
}
|
||||||
@@ -932,6 +915,10 @@ void CollectionWatcher::AddChangedSong(const QString &file, const Song &matching
|
|||||||
changes << "musicbrainz";
|
changes << "musicbrainz";
|
||||||
notify_new = true;
|
notify_new = true;
|
||||||
}
|
}
|
||||||
|
if (!matching_song.IsEBUR128Equal(new_song)) {
|
||||||
|
changes << "ebur128 loudness characteristics";
|
||||||
|
notify_new = true;
|
||||||
|
}
|
||||||
if (matching_song.mtime() != new_song.mtime()) {
|
if (matching_song.mtime() != new_song.mtime()) {
|
||||||
changes << "mtime";
|
changes << "mtime";
|
||||||
}
|
}
|
||||||
@@ -954,31 +941,19 @@ void CollectionWatcher::AddChangedSong(const QString &file, const Song &matching
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_EBUR128
|
void CollectionWatcher::PerformEBUR128Analysis(Song &song) {
|
||||||
void CollectionWatcher::PerformEBUR128Analysis(SongList &songs, ScanTransaction *t) {
|
|
||||||
|
|
||||||
if (!song_ebur128_loudness_analysis_) return;
|
if (!song_ebur128_loudness_analysis_) return;
|
||||||
|
|
||||||
// FIXME: this should probably be done on thread pool.
|
#ifdef HAVE_EBUR128
|
||||||
for (Song &song : songs) {
|
std::optional<EBUR128Measures> loudness_characteristics = EBUR128Analysis::Compute(song);
|
||||||
std::optional<EBUR128Measures> loudness_characteristics = EBUR128Analysis::Compute(song);
|
if (loudness_characteristics) {
|
||||||
if (loudness_characteristics) {
|
song.set_ebur128_integrated_loudness_lufs(loudness_characteristics->loudness_lufs);
|
||||||
song.set_ebur128_integrated_loudness_lufs(loudness_characteristics->loudness_lufs);
|
song.set_ebur128_loudness_range_lu(loudness_characteristics->range_lu);
|
||||||
song.set_ebur128_loudness_range_lu(loudness_characteristics->range_lu);
|
|
||||||
if (t) {
|
|
||||||
// We have updated the song and we must make note of that,
|
|
||||||
// but we should avoid doing that multiple times,
|
|
||||||
// because that will result in spurious/pointless DB updates.
|
|
||||||
if (!t->new_songs.contains(song)) {
|
|
||||||
t->new_songs << song;
|
|
||||||
}
|
|
||||||
t->touched_songs.removeAll(song);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
quint64 CollectionWatcher::GetMtimeForCue(const QString &cue_path) {
|
quint64 CollectionWatcher::GetMtimeForCue(const QString &cue_path) {
|
||||||
|
|
||||||
|
|||||||
@@ -190,18 +190,16 @@ class CollectionWatcher : public QObject {
|
|||||||
void PerformScan(const bool incremental, const bool ignore_mtimes);
|
void PerformScan(const bool incremental, const bool ignore_mtimes);
|
||||||
|
|
||||||
// Updates the sections of a cue associated and altered (according to mtime) media file during a scan.
|
// Updates the sections of a cue associated and altered (according to mtime) media file during a scan.
|
||||||
SongList UpdateCueAssociatedSongs(const QString &file, const QString &path, const QString &fingerprint, const QString &matching_cue, const QUrl &art_automatic, const SongList &old_cue_songs, ScanTransaction *t);
|
void UpdateCueAssociatedSongs(const QString &file, const QString &path, const QString &fingerprint, const QString &matching_cue, const QUrl &art_automatic, const SongList &old_cue_songs, ScanTransaction *t);
|
||||||
// Updates a single non-cue associated and altered (according to mtime) song during a scan.
|
// Updates a single non-cue associated and altered (according to mtime) song during a scan.
|
||||||
Song UpdateNonCueAssociatedSong(const QString &file, const QString &fingerprint, const SongList &matching_songs, const QUrl &art_automatic, const bool cue_deleted, ScanTransaction *t);
|
void UpdateNonCueAssociatedSong(const QString &file, const QString &fingerprint, const SongList &matching_songs, const QUrl &art_automatic, const bool cue_deleted, ScanTransaction *t);
|
||||||
// Scans a single media file that's present on the disk but not yet in the collection.
|
// Scans a single media file that's present on the disk but not yet in the collection.
|
||||||
// It may result in a multiple files added to the collection when the media file has many sections (like a CUE related media file).
|
// It may result in a multiple files added to the collection when the media file has many sections (like a CUE related media file).
|
||||||
SongList ScanNewFile(const QString &file, const QString &path, const QString &fingerprint, const QString &matching_cue, QSet<QString> *cues_processed);
|
SongList ScanNewFile(const QString &file, const QString &path, const QString &fingerprint, const QString &matching_cue, QSet<QString> *cues_processed);
|
||||||
|
|
||||||
static void AddChangedSong(const QString &file, const Song &matching_song, const Song &new_song, ScanTransaction *t);
|
static void AddChangedSong(const QString &file, const Song &matching_song, const Song &new_song, ScanTransaction *t);
|
||||||
|
|
||||||
#ifdef HAVE_EBUR128
|
void PerformEBUR128Analysis(Song &song);
|
||||||
void PerformEBUR128Analysis(SongList &songs, ScanTransaction *t);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
quint64 FilesCountForPath(ScanTransaction *t, const QString &path);
|
quint64 FilesCountForPath(ScanTransaction *t, const QString &path);
|
||||||
quint64 FilesCountForSubdirs(ScanTransaction *t, const CollectionSubdirectoryList &subdirs, QMap<QString, quint64> &subdir_files_count);
|
quint64 FilesCountForSubdirs(ScanTransaction *t, const CollectionSubdirectoryList &subdirs, QMap<QString, quint64> &subdir_files_count);
|
||||||
|
|||||||
@@ -788,6 +788,13 @@ bool Song::IsMusicBrainzEqual(const Song &other) const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Song::IsEBUR128Equal(const Song &other) const {
|
||||||
|
|
||||||
|
return d->ebur128_integrated_loudness_lufs_ == other.d->ebur128_integrated_loudness_lufs_ &&
|
||||||
|
d->ebur128_loudness_range_lu_ == other.d->ebur128_loudness_range_lu_;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool Song::IsArtEqual(const Song &other) const {
|
bool Song::IsArtEqual(const Song &other) const {
|
||||||
|
|
||||||
return d->art_embedded_ == other.d->art_embedded_ &&
|
return d->art_embedded_ == other.d->art_embedded_ &&
|
||||||
|
|||||||
@@ -374,6 +374,7 @@ class Song {
|
|||||||
bool IsFingerprintEqual(const Song &other) const;
|
bool IsFingerprintEqual(const Song &other) const;
|
||||||
bool IsAcoustIdEqual(const Song &other) const;
|
bool IsAcoustIdEqual(const Song &other) const;
|
||||||
bool IsMusicBrainzEqual(const Song &other) const;
|
bool IsMusicBrainzEqual(const Song &other) const;
|
||||||
|
bool IsEBUR128Equal(const Song &other) const;
|
||||||
bool IsArtEqual(const Song &other) const;
|
bool IsArtEqual(const Song &other) const;
|
||||||
bool IsAllMetadataEqual(const Song &other) const;
|
bool IsAllMetadataEqual(const Song &other) const;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user