Support more CUE filenames

Fixes #835
This commit is contained in:
Jonas Kvinge 2021-11-27 20:28:00 +01:00
parent a97dbab2ae
commit 8f49d1591f
5 changed files with 41 additions and 19 deletions

View File

@ -503,7 +503,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
if (stop_requested_) return;
// Associated CUE
QString new_cue = NoExtensionPart(file) + ".cue";
QString new_cue = CueParser::FindCueFilename(file);
SongList matching_songs;
if (FindSongsByPath(songs_in_db, file, &matching_songs)) { // Found matching song in DB by path.
@ -525,13 +525,17 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
qint64 matching_song_cue_mtime = static_cast<qint64>(GetMtimeForCue(matching_song.cue_path()));
// CUE sheet's path from this file (if any).
qint64 new_cue_mtime = static_cast<qint64>(GetMtimeForCue(new_cue));
qint64 new_cue_mtime = 0;
if (!new_cue.isEmpty()) {
new_cue_mtime = static_cast<qint64>(GetMtimeForCue(new_cue));
}
bool cue_added = new_cue_mtime != 0 && !matching_song.has_cue();
bool cue_deleted = matching_song_cue_mtime == 0 && matching_song.has_cue();
const bool cue_added = new_cue_mtime != 0 && !matching_song.has_cue();
const bool cue_changed = new_cue_mtime != 0 && matching_song.has_cue() && new_cue != matching_song.cue_path();
const bool cue_deleted = matching_song.has_cue() && new_cue_mtime == 0;
// Watch out for CUE songs which have their mtime equal to qMax(media_file_mtime, cue_sheet_mtime)
bool changed = (matching_song.mtime() != qMax(fileinfo.lastModified().toSecsSinceEpoch(), matching_song_cue_mtime)) || cue_deleted || cue_added;
bool changed = (matching_song.mtime() != qMax(fileinfo.lastModified().toSecsSinceEpoch(), matching_song_cue_mtime)) || cue_deleted || cue_added || cue_changed;
// Also want to look to see whether the album art has changed
QUrl image = ImageForSong(file, album_art);
@ -567,12 +571,13 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
}
#endif
if (!cue_deleted && (matching_song.has_cue() || cue_added)) { // If CUE associated.
UpdateCueAssociatedSongs(file, path, fingerprint, new_cue, image, matching_songs, t);
}
else { // 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.
UpdateNonCueAssociatedSong(file, fingerprint, matching_songs, image, cue_deleted, t);
}
else { // If CUE associated.
UpdateCueAssociatedSongs(file, path, fingerprint, new_cue, image, matching_songs, t);
}
}
// Nothing has changed - mark the song available without re-scanning
@ -604,7 +609,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
continue;
}
// Make sure the songs aren't deleted, as they still exist elsewhere with a different fingerprint.
// Make sure the songs aren't deleted, as they still exist elsewhere with a different file path.
bool matching_songs_has_cue = false;
for (const Song &matching_song : matching_songs) {
QString matching_filename = matching_song.url().toLocalFile();
@ -621,19 +626,19 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
}
// CUE sheet's path from this file (if any).
const qint64 new_cue_mtime = static_cast<qint64>(GetMtimeForCue(new_cue));
const bool cue_deleted = new_cue_mtime == 0 && matching_songs_has_cue;
const bool cue_added = new_cue_mtime != 0 && !matching_songs_has_cue;
qint64 new_cue_mtime = 0;
if (!new_cue.isEmpty()) {
new_cue_mtime = static_cast<qint64>(GetMtimeForCue(new_cue));
}
// Get new album art
QUrl image = ImageForSong(file, album_art);
if (!cue_deleted && (matching_songs_has_cue || cue_added)) { // CUE associated.
UpdateCueAssociatedSongs(file, path, fingerprint, new_cue, image, matching_songs, t);
if (new_cue.isEmpty() || new_cue_mtime == 0) { // If no CUE or it's about to lose it.
UpdateNonCueAssociatedSong(file, fingerprint, matching_songs, image, matching_songs_has_cue && new_cue_mtime == 0, t);
}
else { // If no CUE or it's about to lose it.
UpdateNonCueAssociatedSong(file, fingerprint, matching_songs, image, cue_deleted, t);
else { // If CUE associated.
UpdateCueAssociatedSongs(file, path, fingerprint, new_cue, image, matching_songs, t);
}
}

View File

@ -194,6 +194,8 @@ class CollectionWatcher : public QObject {
quint64 FilesCountForPath(ScanTransaction *t, const QString &path);
quint64 FilesCountForSubdirs(ScanTransaction *t, const SubdirectoryList &subdirs, QMap<QString, quint64> &subdir_files_count);
QString FindCueFilename(const QString &filename);
private:
Song::Source source_;
CollectionBackend *backend_;

View File

@ -300,7 +300,7 @@ SongLoader::Result SongLoader::LoadLocalAsync(const QString &filename) {
}
// Check if it's a CUE file
QString matching_cue = filename.section('.', 0, -2) + ".cue";
QString matching_cue = CueParser::FindCueFilename(filename);
if (QFile::exists(matching_cue)) {
// It's a CUE - create virtual tracks
QFile cue(matching_cue);

View File

@ -379,3 +379,16 @@ bool CueParser::TryMagic(const QByteArray &data) const {
return false;
}
QString CueParser::FindCueFilename(const QString &filename) {
QStringList cue_files = QStringList() << filename + ".cue"
<< filename.section('.', 0, -2) + ".cue";
for (const QString &cuefile : cue_files) {
if (QFileInfo::exists(cuefile)) return cuefile;
}
return QString();
}

View File

@ -70,6 +70,8 @@ class CueParser : public ParserBase {
SongList Load(QIODevice *device, const QString &playlist_path = "", const QDir &dir = QDir(), const bool collection_search = true) const override;
void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir(), Playlist::Path path_type = Playlist::Path_Automatic) const override;
static QString FindCueFilename(const QString &filename);
private:
// A single TRACK entry in .cue file.
struct CueEntry {