22 query.prepare(
"SELECT directory_id, path FROM music_directories");
27 m_directoryid[query.value(1).toString()] = query.value(0).toInt();
32 query.prepare(
"SELECT genre_id, LOWER(genre) FROM music_genres");
37 m_genreid[query.value(1).toString()] = query.value(0).toInt();
42 query.prepare(
"SELECT artist_id, LOWER(artist_name) FROM music_artists");
43 if (query.exec() || query.isActive())
47 m_artistid[query.value(1).toString()] = query.value(0).toInt();
52 query.prepare(
"SELECT album_id, artist_id, LOWER(album_name) FROM music_albums");
57 m_albumid[query.value(1).toString() +
"#" + query.value(2).toString()] = query.value(0).toInt();
81 d.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
83 QFileInfoList list =
d.entryInfoList();
89 for (
const auto& fi : std::as_const(list))
91 QString
filename = fi.absoluteFilePath();
100 if (newparentid == 0)
111 LOG(VB_GENERAL, LOG_ERR,
112 QString(
"Failed to get directory id for path %1")
137 LOG(VB_GENERAL, LOG_INFO,
138 QString(
"Found file with unsupported extension %1")
148 QString extension = fi.suffix().toLower();
152 return !extension.isEmpty() && nameFilter.indexOf(extension.toLower()) > -1;
158 QString extension = fi.suffix().toLower();
161 return !extension.isEmpty() && nameFilter.indexOf(extension.toLower()) > -1;
176 if (directory.isEmpty())
182 query.
prepare(
"SELECT directory_id FROM music_directories "
183 "WHERE path = BINARY :DIRECTORY ;");
184 query.
bindValue(
":DIRECTORY", directory);
195 return query.
value(0).toInt();
199 query.
prepare(
"INSERT INTO music_directories (path, parent_id) "
200 "VALUES (:DIRECTORY, :PARENTID);");
201 query.
bindValue(
":DIRECTORY", directory);
222 const QString &
filename,
const QString &date_modified)
225 QDateTime dt = fi.lastModified();
229 return !old_dt.isValid() || (dt > old_dt);
231 LOG(VB_GENERAL, LOG_ERR, QString(
"Failed to stat file: %1")
253 QString extension =
filename.section(
'.', -1 ) ;
255 directory.remove(0, startDir.length());
256 directory = directory.section(
'/', 0, -2);
261 if (nameFilter.indexOf(extension.toLower()) > -1)
263 QString name =
filename.section(
'/', -1);
266 query.
prepare(
"INSERT INTO music_albumart "
267 "SET filename = :FILE, directory_id = :DIRID, "
268 "imagetype = :TYPE, hostname = :HOSTNAME;");
287 LOG(VB_GENERAL, LOG_WARNING, QString(
"Ignoring filename with unsupported filename: '%1'").arg(
filename));
291 LOG(VB_FILE, LOG_INFO, QString(
"Reading metadata from %1").arg(
filename));
298 QString album_cache_string;
311 album_cache_string = QString::number(data->
getArtistId()) +
"#"
312 + data->
Album().toLower();
339 album_cache_string = QString::number(data->
getArtistId()) +
"#"
340 + data->
Album().toLower();
371 LOG(VB_GENERAL, LOG_INFO,
"Cleaning old entries from music database");
377 if (!query.
exec(
"SELECT g.genre_id FROM music_genres g "
378 "LEFT JOIN music_songs s ON g.genre_id=s.genre_id "
379 "WHERE s.genre_id IS NULL;"))
380 MythDB::DBError(
"MusicFileScanner::cleanDB - select music_genres", query);
382 deletequery.
prepare(
"DELETE FROM music_genres WHERE genre_id=:GENREID");
385 int genreid = query.
value(0).toInt();
386 deletequery.
bindValue(
":GENREID", genreid);
387 if (!deletequery.
exec())
393 if (!query.
exec(
"SELECT a.album_id FROM music_albums a "
394 "LEFT JOIN music_songs s ON a.album_id=s.album_id "
395 "WHERE s.album_id IS NULL;"))
396 MythDB::DBError(
"MusicFileScanner::cleanDB - select music_albums", query);
398 deletequery.
prepare(
"DELETE FROM music_albums WHERE album_id=:ALBUMID");
401 int albumid = query.
value(0).toInt();
402 deletequery.
bindValue(
":ALBUMID", albumid);
403 if (!deletequery.
exec())
409 if (!query.
exec(
"SELECT a.artist_id FROM music_artists a "
410 "LEFT JOIN music_songs s ON a.artist_id=s.artist_id "
411 "LEFT JOIN music_albums l ON a.artist_id=l.artist_id "
412 "WHERE s.artist_id IS NULL AND l.artist_id IS NULL"))
413 MythDB::DBError(
"MusicFileScanner::cleanDB - select music_artists", query);
416 deletequery.
prepare(
"DELETE FROM music_artists WHERE artist_id=:ARTISTID");
419 int artistid = query.
value(0).toInt();
420 deletequery.
bindValue(
":ARTISTID", artistid);
421 if (!deletequery.
exec())
428 if (!query.
exec(
"SELECT d.directory_id, d.parent_id FROM music_directories d "
429 "LEFT JOIN music_songs s ON d.directory_id=s.directory_id "
430 "WHERE s.directory_id IS NULL ORDER BY directory_id DESC;"))
431 MythDB::DBError(
"MusicFileScanner::cleanDB - select music_directories", query);
433 deletequery.
prepare(
"DELETE FROM music_directories WHERE directory_id=:DIRECTORYID");
436 parentquery.
prepare(
"SELECT COUNT(*) FROM music_directories "
437 "WHERE parent_id=:DIRECTORYID ");
439 int deletedCount = 0;
452 int directoryid = query.
value(0).toInt();
455 parentquery.
bindValue(
":DIRECTORYID", directoryid);
456 if (!parentquery.
exec())
457 MythDB::DBError(
"MusicFileScanner::cleanDB - get parent directory count",
460 if (parentquery.
next())
462 int parentCount = parentquery.
value(0).toInt();
464 if (parentCount == 0)
466 deletequery.
bindValue(
":DIRECTORYID", directoryid);
467 if (!deletequery.
exec())
468 MythDB::DBError(
"MusicFileScanner::cleanDB - delete music_directories",
475 }
while (query.
next());
477 }
while (deletedCount > 0);
480 if (!query.
exec(
"SELECT a.albumart_id FROM music_albumart a LEFT JOIN "
481 "music_songs s ON a.song_id=s.song_id WHERE "
482 "embedded='1' AND s.song_id IS NULL;"))
483 MythDB::DBError(
"MusicFileScanner::cleanDB - select music_albumart", query);
485 deletequery.
prepare(
"DELETE FROM music_albumart WHERE albumart_id=:ALBUMARTID");
488 int albumartid = query.
value(0).toInt();
489 deletequery.
bindValue(
":ALBUMARTID", albumartid);
490 if (!deletequery.
exec())
509 sqlfilename.remove(0, startDir.length());
511 QString directory = sqlfilename.section(
'/', 0, -2 ) ;
512 sqlfilename = sqlfilename.section(
'/', -1 ) ;
514 QString extension = sqlfilename.section(
'.', -1 ) ;
517 "*.png;*.jpg;*.jpeg;*.gif;*.bmp");
519 if (nameFilter.indexOf(extension.toLower()) > -1)
522 query.
prepare(
"DELETE FROM music_albumart WHERE filename= :FILE AND "
523 "directory_id= :DIRID;");
538 query.
prepare(
"DELETE FROM music_songs WHERE filename = :NAME ;");
541 MythDB::DBError(
"MusicFileScanner::RemoveFileFromDB - deleting music_songs",
560 dbFilename.remove(0, startDir.length());
563 directory.remove(0, startDir.length());
564 directory = directory.section(
'/', 0, -2);
569 if (db_meta && disk_meta)
571 if (db_meta->
ID() <= 0)
573 LOG(VB_GENERAL, LOG_ERR, QString(
"Asked to update track with "
575 .arg(db_meta->
ID()));
581 disk_meta->
setID(db_meta->
ID());
586 QString album_cache_string;
599 album_cache_string = QString::number(disk_meta->
getArtistId()) +
"#" +
600 disk_meta->
Album().toLower();
628 album_cache_string = QString::number(disk_meta->
getArtistId()) +
"#" +
629 disk_meta->
Album().toLower();
655 if (!lastRun.isEmpty())
658 if (dtLastRun.isValid())
660 static constexpr int64_t kOneHour {60LL * 60};
663 LOG(VB_GENERAL, LOG_INFO,
"Music file scanner has been running for more than 60 minutes. Lets reset and try again");
671 LOG(VB_GENERAL, LOG_INFO,
"Music file scanner is already running");
681 LOG(VB_GENERAL, LOG_INFO,
"Music file scanner started");
685 QString status = QString(
"running");
693 MusicLoadedMap::Iterator iter;
695 for (
int x = 0; x < dirList.count(); x++)
697 QString startDir = dirList[x];
699 LOG(VB_GENERAL, LOG_INFO, QString(
"Searching '%1' for music files").arg(startDir));
710 LOG(VB_GENERAL, LOG_INFO,
"Updating database");
725 for (iter = music_files.begin(); iter != music_files.end(); iter++)
738 for (iter = art_files.begin(); iter != art_files.end(); iter++)
754 QString trackStatus = QString(
"total tracks found: %1 (unchanged: %2, added: %3, removed: %4, updated %5)")
757 QString coverartStatus = QString(
"total coverart found: %1 (unchanged: %2, added: %3, removed: %4, updated %5)")
762 LOG(VB_GENERAL, LOG_INFO,
"Music file scanner finished ");
763 LOG(VB_GENERAL, LOG_INFO, trackStatus);
764 LOG(VB_GENERAL, LOG_INFO, coverartStatus);
771 status = QString(
"success - %1 - %2").arg(trackStatus, coverartStatus);
784 MusicLoadedMap::Iterator iter;
787 query.
prepare(
"SELECT CONCAT_WS('/', path, filename), date_modified "
788 "FROM music_songs LEFT JOIN music_directories ON "
789 "music_songs.directory_id=music_directories.directory_id "
790 "WHERE filename NOT LIKE BINARY ('%://%') "
791 "AND hostname = :HOSTNAME");
798 LOG(VB_GENERAL, LOG_INFO,
"Checking tracks");
809 iter = music_files.find(name);
810 if (iter != music_files.end())
814 if (iter != music_files.end())
823 music_files.erase(iter);
843 MusicLoadedMap::Iterator iter;
846 query.
prepare(
"SELECT CONCAT_WS('/', path, filename) "
847 "FROM music_albumart "
848 "LEFT JOIN music_directories ON music_albumart.directory_id=music_directories.directory_id "
849 "WHERE music_albumart.embedded = 0 "
850 "AND music_albumart.hostname = :HOSTNAME");
857 LOG(VB_GENERAL, LOG_INFO,
"Checking artwork");
868 iter = music_files.find(name);
869 if (iter != music_files.end())
873 if (iter != music_files.end())
878 music_files.erase(iter);