Add ability to cancel scan per directory.
Store a boolean along with watched directories to indicate active. Use this flag to provide a mechanism to halt scans on a per-directory basis.
This commit is contained in:
parent
97ffae2e70
commit
4ebd3c8c0a
@ -27,13 +27,13 @@
|
|||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QtDebug>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QMutexLocker>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QThread>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
#include <fileref.h>
|
#include <fileref.h>
|
||||||
#include <tag.h>
|
#include <tag.h>
|
||||||
@ -59,7 +59,6 @@ LibraryWatcher::LibraryWatcher(QObject* parent)
|
|||||||
backend_(nullptr),
|
backend_(nullptr),
|
||||||
task_manager_(nullptr),
|
task_manager_(nullptr),
|
||||||
fs_watcher_(FileSystemWatcherInterface::Create(this)),
|
fs_watcher_(FileSystemWatcherInterface::Create(this)),
|
||||||
stop_requested_(false),
|
|
||||||
scan_on_startup_(true),
|
scan_on_startup_(true),
|
||||||
monitor_(true),
|
monitor_(true),
|
||||||
rescan_timer_(new QTimer(this)),
|
rescan_timer_(new QTimer(this)),
|
||||||
@ -85,10 +84,9 @@ LibraryWatcher::LibraryWatcher(QObject* parent)
|
|||||||
// is only created on a stack and the removal of a directory from the watch
|
// is only created on a stack and the removal of a directory from the watch
|
||||||
// list only occurs as a result of a signal and happens on the watcher's
|
// list only occurs as a result of a signal and happens on the watcher's
|
||||||
// thread. So the Directory object will not be deleted out from under us.
|
// thread. So the Directory object will not be deleted out from under us.
|
||||||
LibraryWatcher::ScanTransaction::ScanTransaction(LibraryWatcher* watcher,
|
LibraryWatcher::ScanTransaction::ScanTransaction(
|
||||||
const Directory& dir,
|
LibraryWatcher* watcher, const LibraryWatcher::WatchedDir& dir,
|
||||||
bool incremental,
|
bool incremental, bool ignores_mtime)
|
||||||
bool ignores_mtime)
|
|
||||||
: progress_(0),
|
: progress_(0),
|
||||||
progress_max_(0),
|
progress_max_(0),
|
||||||
dir_(dir),
|
dir_(dir),
|
||||||
@ -109,7 +107,7 @@ LibraryWatcher::ScanTransaction::ScanTransaction(LibraryWatcher* watcher,
|
|||||||
|
|
||||||
LibraryWatcher::ScanTransaction::~ScanTransaction() {
|
LibraryWatcher::ScanTransaction::~ScanTransaction() {
|
||||||
// If we're stopping then don't commit the transaction
|
// If we're stopping then don't commit the transaction
|
||||||
if (watcher_->stop_requested_) {
|
if (aborted()) {
|
||||||
watcher_->task_manager_->SetTaskFinished(task_id_);
|
watcher_->task_manager_->SetTaskFinished(task_id_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -204,12 +202,36 @@ SubdirectoryList LibraryWatcher::ScanTransaction::GetAllSubdirs() {
|
|||||||
return known_subdirs_;
|
return known_subdirs_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LibraryWatcher::WatchList::StopAll() {
|
||||||
|
QMutexLocker l(&mutex_);
|
||||||
|
for (WatchedDir& wdir : list_) {
|
||||||
|
wdir.active_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryWatcher::WatchList::Stop(const Directory& dir) {
|
||||||
|
QMutexLocker l(&mutex_);
|
||||||
|
if (list_.contains(dir.id)) {
|
||||||
|
list_[dir.id].active_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryWatcher::WatchList::Remove(int id) {
|
||||||
|
QMutexLocker l(&mutex_);
|
||||||
|
list_.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LibraryWatcher::WatchList::Add(const Directory& dir) {
|
||||||
|
// Lock is not really necessary here, but it's also not going to block
|
||||||
|
// anything, so include it for sanity and completeness.
|
||||||
|
QMutexLocker l(&mutex_);
|
||||||
|
list_[dir.id] = WatchedDir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
void LibraryWatcher::AddDirectory(const Directory& dir,
|
void LibraryWatcher::AddDirectory(const Directory& dir,
|
||||||
const SubdirectoryList& subdirs) {
|
const SubdirectoryList& subdirs) {
|
||||||
watched_dirs_[dir.id] = dir;
|
watched_dirs_.Add(dir);
|
||||||
// Use a reference to our copy of the directory, not the reference to the
|
const WatchedDir& new_dir = watched_dirs_.list_[dir.id];
|
||||||
// caller's instance.
|
|
||||||
Directory& new_dir = watched_dirs_[dir.id];
|
|
||||||
|
|
||||||
if (subdirs.isEmpty()) {
|
if (subdirs.isEmpty()) {
|
||||||
// This is a new directory that we've never seen before.
|
// This is a new directory that we've never seen before.
|
||||||
@ -225,7 +247,7 @@ void LibraryWatcher::AddDirectory(const Directory& dir,
|
|||||||
transaction.SetKnownSubdirs(subdirs);
|
transaction.SetKnownSubdirs(subdirs);
|
||||||
transaction.AddToProgressMax(subdirs.count());
|
transaction.AddToProgressMax(subdirs.count());
|
||||||
for (const Subdirectory& subdir : subdirs) {
|
for (const Subdirectory& subdir : subdirs) {
|
||||||
if (stop_requested_) return;
|
if (transaction.aborted()) return;
|
||||||
|
|
||||||
if (scan_on_startup_) ScanSubdirectory(subdir.path, subdir, &transaction);
|
if (scan_on_startup_) ScanSubdirectory(subdir.path, subdir, &transaction);
|
||||||
|
|
||||||
@ -246,7 +268,7 @@ void LibraryWatcher::ScanSubdirectory(const QString& path,
|
|||||||
// Do not scan symlinked dirs that are already in collection
|
// Do not scan symlinked dirs that are already in collection
|
||||||
if (path_info.isSymLink()) {
|
if (path_info.isSymLink()) {
|
||||||
QString real_path = path_info.symLinkTarget();
|
QString real_path = path_info.symLinkTarget();
|
||||||
for (const Directory& dir : watched_dirs_) {
|
for (const Directory& dir : watched_dirs_.list_) {
|
||||||
if (real_path.startsWith(dir.path)) {
|
if (real_path.startsWith(dir.path)) {
|
||||||
t->AddToProgress(1);
|
t->AddToProgress(1);
|
||||||
return;
|
return;
|
||||||
@ -290,7 +312,7 @@ void LibraryWatcher::ScanSubdirectory(const QString& path,
|
|||||||
QDirIterator it(
|
QDirIterator it(
|
||||||
path, QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot);
|
path, QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
if (stop_requested_) return;
|
if (t->aborted()) return;
|
||||||
|
|
||||||
QString child(it.next());
|
QString child(it.next());
|
||||||
QFileInfo child_info(child);
|
QFileInfo child_info(child);
|
||||||
@ -316,7 +338,7 @@ void LibraryWatcher::ScanSubdirectory(const QString& path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stop_requested_) return;
|
if (t->aborted()) return;
|
||||||
|
|
||||||
// Ask the database for a list of files in this directory
|
// Ask the database for a list of files in this directory
|
||||||
SongList songs_in_db = t->FindSongsInSubdirectory(path);
|
SongList songs_in_db = t->FindSongsInSubdirectory(path);
|
||||||
@ -325,7 +347,7 @@ void LibraryWatcher::ScanSubdirectory(const QString& path,
|
|||||||
|
|
||||||
// Now compare the list from the database with the list of files on disk
|
// Now compare the list from the database with the list of files on disk
|
||||||
for (const QString& file : files_on_disk) {
|
for (const QString& file : files_on_disk) {
|
||||||
if (stop_requested_) return;
|
if (t->aborted()) return;
|
||||||
|
|
||||||
// associated cue
|
// associated cue
|
||||||
QString matching_cue = NoExtensionPart(file) + ".cue";
|
QString matching_cue = NoExtensionPart(file) + ".cue";
|
||||||
@ -360,7 +382,7 @@ void LibraryWatcher::ScanSubdirectory(const QString& path,
|
|||||||
cue_deleted || cue_added;
|
cue_deleted || cue_added;
|
||||||
|
|
||||||
// Also want to look to see whether the album art has changed
|
// Also want to look to see whether the album art has changed
|
||||||
QString image = ImageForSong(file, album_art);
|
QString image = ImageForSong(file, album_art, t);
|
||||||
if ((matching_song.art_automatic().isEmpty() && !image.isEmpty()) ||
|
if ((matching_song.art_automatic().isEmpty() && !image.isEmpty()) ||
|
||||||
(!matching_song.art_automatic().isEmpty() &&
|
(!matching_song.art_automatic().isEmpty() &&
|
||||||
!matching_song.has_embedded_cover() &&
|
!matching_song.has_embedded_cover() &&
|
||||||
@ -396,7 +418,7 @@ void LibraryWatcher::ScanSubdirectory(const QString& path,
|
|||||||
|
|
||||||
qLog(Debug) << file << "created";
|
qLog(Debug) << file << "created";
|
||||||
// choose an image for the song(s)
|
// choose an image for the song(s)
|
||||||
QString image = ImageForSong(file, album_art);
|
QString image = ImageForSong(file, album_art, t);
|
||||||
|
|
||||||
for (Song song : song_list) {
|
for (Song song : song_list) {
|
||||||
song.set_directory_id(t->dir_id());
|
song.set_directory_id(t->dir_id());
|
||||||
@ -438,7 +460,7 @@ void LibraryWatcher::ScanSubdirectory(const QString& path,
|
|||||||
// Recurse into the new subdirs that we found
|
// Recurse into the new subdirs that we found
|
||||||
t->AddToProgressMax(my_new_subdirs.count());
|
t->AddToProgressMax(my_new_subdirs.count());
|
||||||
for (const Subdirectory& my_new_subdir : my_new_subdirs) {
|
for (const Subdirectory& my_new_subdir : my_new_subdirs) {
|
||||||
if (stop_requested_) return;
|
if (t->aborted()) return;
|
||||||
ScanSubdirectory(my_new_subdir.path, my_new_subdir, t, true);
|
ScanSubdirectory(my_new_subdir.path, my_new_subdir, t, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -642,7 +664,7 @@ void LibraryWatcher::RemoveWatch(const Directory& dir,
|
|||||||
|
|
||||||
void LibraryWatcher::RemoveDirectory(const Directory& dir) {
|
void LibraryWatcher::RemoveDirectory(const Directory& dir) {
|
||||||
rescan_queue_.remove(dir.id);
|
rescan_queue_.remove(dir.id);
|
||||||
watched_dirs_.remove(dir.id);
|
watched_dirs_.Remove(dir.id);
|
||||||
|
|
||||||
// Stop watching the directory's subdirectories
|
// Stop watching the directory's subdirectories
|
||||||
for (const QString& subdir_path : subdir_mapping_.keys(dir)) {
|
for (const QString& subdir_path : subdir_mapping_.keys(dir)) {
|
||||||
@ -682,21 +704,22 @@ void LibraryWatcher::DirectoryChanged(const QString& subdir) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LibraryWatcher::RescanPathsNow() {
|
void LibraryWatcher::RescanPathsNow() {
|
||||||
for (int dir : rescan_queue_.keys()) {
|
for (int id : rescan_queue_.keys()) {
|
||||||
if (stop_requested_) return;
|
if (!watched_dirs_.list_.contains(id)) {
|
||||||
|
qLog(Warning) << "Rescan id" << id << "not in watch list.";
|
||||||
if (!watched_dirs_.contains(dir)) {
|
|
||||||
qLog(Warning) << "Rescan id" << dir << "not in watch list.";
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const WatchedDir& dir = watched_dirs_.list_[id];
|
||||||
|
|
||||||
ScanTransaction transaction(this, watched_dirs_[dir], false);
|
if (!dir.active_) continue;
|
||||||
transaction.AddToProgressMax(rescan_queue_[dir].count());
|
|
||||||
|
|
||||||
for (const QString& path : rescan_queue_[dir]) {
|
ScanTransaction transaction(this, dir, false);
|
||||||
if (stop_requested_) return;
|
transaction.AddToProgressMax(rescan_queue_[id].count());
|
||||||
|
|
||||||
|
for (const QString& path : rescan_queue_[id]) {
|
||||||
|
if (transaction.aborted()) return;
|
||||||
Subdirectory subdir;
|
Subdirectory subdir;
|
||||||
subdir.directory_id = dir;
|
subdir.directory_id = id;
|
||||||
subdir.mtime = 0;
|
subdir.mtime = 0;
|
||||||
subdir.path = path;
|
subdir.path = path;
|
||||||
ScanSubdirectory(path, subdir, &transaction);
|
ScanSubdirectory(path, subdir, &transaction);
|
||||||
@ -708,7 +731,8 @@ void LibraryWatcher::RescanPathsNow() {
|
|||||||
emit CompilationsNeedUpdating();
|
emit CompilationsNeedUpdating();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LibraryWatcher::PickBestImage(const QStringList& images) {
|
QString LibraryWatcher::PickBestImage(const QStringList& images,
|
||||||
|
ScanTransaction* t) {
|
||||||
// This is used when there is more than one image in a directory.
|
// This is used when there is more than one image in a directory.
|
||||||
// Pick the biggest image that matches the most important filter
|
// Pick the biggest image that matches the most important filter
|
||||||
|
|
||||||
@ -748,7 +772,7 @@ QString LibraryWatcher::PickBestImage(const QStringList& images) {
|
|||||||
QString biggest_path;
|
QString biggest_path;
|
||||||
|
|
||||||
for (const QString& path : filtered) {
|
for (const QString& path : filtered) {
|
||||||
if (stop_requested_) return "";
|
if (t->aborted()) return "";
|
||||||
|
|
||||||
QImage image(path);
|
QImage image(path);
|
||||||
if (image.isNull()) continue;
|
if (image.isNull()) continue;
|
||||||
@ -764,14 +788,15 @@ QString LibraryWatcher::PickBestImage(const QStringList& images) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString LibraryWatcher::ImageForSong(const QString& path,
|
QString LibraryWatcher::ImageForSong(const QString& path,
|
||||||
QMap<QString, QStringList>& album_art) {
|
QMap<QString, QStringList>& album_art,
|
||||||
|
ScanTransaction* t) {
|
||||||
QString dir(DirectoryPart(path));
|
QString dir(DirectoryPart(path));
|
||||||
|
|
||||||
if (album_art.contains(dir)) {
|
if (album_art.contains(dir)) {
|
||||||
if (album_art[dir].count() == 1)
|
if (album_art[dir].count() == 1)
|
||||||
return album_art[dir][0];
|
return album_art[dir][0];
|
||||||
else {
|
else {
|
||||||
QString best_image = PickBestImage(album_art[dir]);
|
QString best_image = PickBestImage(album_art[dir], t);
|
||||||
album_art[dir] = QStringList() << best_image;
|
album_art[dir] = QStringList() << best_image;
|
||||||
return best_image;
|
return best_image;
|
||||||
}
|
}
|
||||||
@ -804,7 +829,7 @@ void LibraryWatcher::ReloadSettings() {
|
|||||||
fs_watcher_->Clear();
|
fs_watcher_->Clear();
|
||||||
} else if (monitor_ && !was_monitoring_before) {
|
} else if (monitor_ && !was_monitoring_before) {
|
||||||
// Add all directories to all QFileSystemWatchers again
|
// Add all directories to all QFileSystemWatchers again
|
||||||
for (const Directory& dir : watched_dirs_.values()) {
|
for (const Directory& dir : watched_dirs_.list_.values()) {
|
||||||
SubdirectoryList subdirs = backend_->SubdirsInDirectory(dir.id);
|
SubdirectoryList subdirs = backend_->SubdirsInDirectory(dir.id);
|
||||||
for (const Subdirectory& subdir : subdirs) {
|
for (const Subdirectory& subdir : subdirs) {
|
||||||
AddWatch(dir, subdir.path);
|
AddWatch(dir, subdir.path);
|
||||||
@ -836,13 +861,13 @@ void LibraryWatcher::IncrementalScanNow() { PerformScan(true, false); }
|
|||||||
void LibraryWatcher::FullScanNow() { PerformScan(false, true); }
|
void LibraryWatcher::FullScanNow() { PerformScan(false, true); }
|
||||||
|
|
||||||
void LibraryWatcher::PerformScan(bool incremental, bool ignore_mtimes) {
|
void LibraryWatcher::PerformScan(bool incremental, bool ignore_mtimes) {
|
||||||
for (const Directory& dir : watched_dirs_.values()) {
|
for (const WatchedDir& dir : watched_dirs_.list_.values()) {
|
||||||
ScanTransaction transaction(this, dir, incremental, ignore_mtimes);
|
ScanTransaction transaction(this, dir, incremental, ignore_mtimes);
|
||||||
SubdirectoryList subdirs(transaction.GetAllSubdirs());
|
SubdirectoryList subdirs(transaction.GetAllSubdirs());
|
||||||
transaction.AddToProgressMax(subdirs.count());
|
transaction.AddToProgressMax(subdirs.count());
|
||||||
|
|
||||||
for (const Subdirectory& subdir : subdirs) {
|
for (const Subdirectory& subdir : subdirs) {
|
||||||
if (stop_requested_) return;
|
if (transaction.aborted()) return;
|
||||||
|
|
||||||
ScanSubdirectory(subdir.path, subdir, &transaction);
|
ScanSubdirectory(subdir.path, subdir, &transaction);
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,10 @@
|
|||||||
#include "core/song.h"
|
#include "core/song.h"
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QMutex>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMap>
|
|
||||||
|
|
||||||
class QFileSystemWatcher;
|
class QFileSystemWatcher;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
@ -55,9 +56,9 @@ class LibraryWatcher : public QObject {
|
|||||||
void SetRescanPausedAsync(bool pause);
|
void SetRescanPausedAsync(bool pause);
|
||||||
void ReloadSettingsAsync();
|
void ReloadSettingsAsync();
|
||||||
|
|
||||||
void Stop() { stop_requested_ = true; }
|
void Stop() { watched_dirs_.StopAll(); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void NewOrUpdatedSongs(const SongList& songs);
|
void NewOrUpdatedSongs(const SongList& songs);
|
||||||
void SongsMTimeUpdated(const SongList& songs);
|
void SongsMTimeUpdated(const SongList& songs);
|
||||||
void SongsDeleted(const SongList& songs);
|
void SongsDeleted(const SongList& songs);
|
||||||
@ -77,6 +78,14 @@ signals:
|
|||||||
void SetRescanPaused(bool pause);
|
void SetRescanPaused(bool pause);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class WatchedDir : public Directory {
|
||||||
|
public:
|
||||||
|
WatchedDir() : active_(true) {}
|
||||||
|
WatchedDir(const Directory& dir) : Directory(dir), active_(true) {}
|
||||||
|
|
||||||
|
bool active_;
|
||||||
|
};
|
||||||
|
|
||||||
// This class encapsulates a full or partial scan of a directory.
|
// This class encapsulates a full or partial scan of a directory.
|
||||||
// Each directory has one or more subdirectories, and any number of
|
// Each directory has one or more subdirectories, and any number of
|
||||||
// subdirectories can be scanned during one transaction. ScanSubdirectory()
|
// subdirectories can be scanned during one transaction. ScanSubdirectory()
|
||||||
@ -88,8 +97,9 @@ signals:
|
|||||||
// LibraryBackend::FindSongsInDirectory.
|
// LibraryBackend::FindSongsInDirectory.
|
||||||
class ScanTransaction {
|
class ScanTransaction {
|
||||||
public:
|
public:
|
||||||
ScanTransaction(LibraryWatcher* watcher, const Directory& dir,
|
ScanTransaction(LibraryWatcher* watcher,
|
||||||
bool incremental, bool ignores_mtime = false);
|
const LibraryWatcher::WatchedDir& dir, bool incremental,
|
||||||
|
bool ignores_mtime = false);
|
||||||
~ScanTransaction();
|
~ScanTransaction();
|
||||||
|
|
||||||
SongList FindSongsInSubdirectory(const QString& path);
|
SongList FindSongsInSubdirectory(const QString& path);
|
||||||
@ -105,6 +115,8 @@ signals:
|
|||||||
bool is_incremental() const { return incremental_; }
|
bool is_incremental() const { return incremental_; }
|
||||||
bool ignores_mtime() const { return ignores_mtime_; }
|
bool ignores_mtime() const { return ignores_mtime_; }
|
||||||
|
|
||||||
|
bool aborted() { return !dir_.active_; }
|
||||||
|
|
||||||
SongList deleted_songs;
|
SongList deleted_songs;
|
||||||
SongList readded_songs;
|
SongList readded_songs;
|
||||||
SongList new_songs;
|
SongList new_songs;
|
||||||
@ -120,7 +132,7 @@ signals:
|
|||||||
int progress_;
|
int progress_;
|
||||||
int progress_max_;
|
int progress_max_;
|
||||||
|
|
||||||
const Directory& dir_;
|
const WatchedDir& dir_;
|
||||||
// Incremental scan enters a directory only if it has changed since the
|
// Incremental scan enters a directory only if it has changed since the
|
||||||
// last scan.
|
// last scan.
|
||||||
bool incremental_;
|
bool incremental_;
|
||||||
@ -153,9 +165,10 @@ signals:
|
|||||||
inline static QString NoExtensionPart(const QString& fileName);
|
inline static QString NoExtensionPart(const QString& fileName);
|
||||||
inline static QString ExtensionPart(const QString& fileName);
|
inline static QString ExtensionPart(const QString& fileName);
|
||||||
inline static QString DirectoryPart(const QString& fileName);
|
inline static QString DirectoryPart(const QString& fileName);
|
||||||
QString PickBestImage(const QStringList& images);
|
QString PickBestImage(const QStringList& images, ScanTransaction* t);
|
||||||
QString ImageForSong(const QString& path,
|
QString ImageForSong(const QString& path,
|
||||||
QMap<QString, QStringList>& album_art);
|
QMap<QString, QStringList>& album_art,
|
||||||
|
ScanTransaction* t);
|
||||||
void AddWatch(const Directory& dir, const QString& path);
|
void AddWatch(const Directory& dir, const QString& path);
|
||||||
void RemoveWatch(const Directory& dir, const Subdirectory& subdir);
|
void RemoveWatch(const Directory& dir, const Subdirectory& subdir);
|
||||||
uint GetMtimeForCue(const QString& cue_path);
|
uint GetMtimeForCue(const QString& cue_path);
|
||||||
@ -200,11 +213,30 @@ signals:
|
|||||||
*/
|
*/
|
||||||
QStringList best_image_filters_;
|
QStringList best_image_filters_;
|
||||||
|
|
||||||
bool stop_requested_;
|
|
||||||
bool scan_on_startup_;
|
bool scan_on_startup_;
|
||||||
bool monitor_;
|
bool monitor_;
|
||||||
|
|
||||||
QMap<int, Directory> watched_dirs_;
|
// All methods of QMap are reentrant We should only need to worry about
|
||||||
|
// syncronizing methods that remove directories on the watcher thread and
|
||||||
|
// methods that modify directories called from other threads.
|
||||||
|
class WatchList {
|
||||||
|
public:
|
||||||
|
// These may be called from a different thread.
|
||||||
|
void StopAll();
|
||||||
|
void Stop(const Directory& dir);
|
||||||
|
|
||||||
|
// This should only be called on the watcher thread.
|
||||||
|
void Remove(int id);
|
||||||
|
|
||||||
|
void Add(const Directory& dir);
|
||||||
|
|
||||||
|
QMap<int, WatchedDir> list_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMutex mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
WatchList watched_dirs_;
|
||||||
QTimer* rescan_timer_;
|
QTimer* rescan_timer_;
|
||||||
QMap<int, QStringList>
|
QMap<int, QStringList>
|
||||||
rescan_queue_; // dir id -> list of subdirs to be scanned
|
rescan_queue_; // dir id -> list of subdirs to be scanned
|
||||||
|
Loading…
x
Reference in New Issue
Block a user