128 lines
2.8 KiB
C++
128 lines
2.8 KiB
C++
// Copyright (c) 2012 Bryan Schumaker.
|
|
#include <library.h>
|
|
#include <notify.h>
|
|
#include <track.h>
|
|
#include <print.h>
|
|
#include <deck.h>
|
|
#include <idle.h>
|
|
#include <fs.h>
|
|
#include "library.h"
|
|
|
|
static unsigned int MAX_SCAN = 20;
|
|
|
|
static void validate_path(void *d)
|
|
{
|
|
struct libsaria::library::Path *path;
|
|
libsaria::Track *track;
|
|
unsigned int i = 0;
|
|
|
|
path = (struct libsaria::library::Path *)d;
|
|
while (i < path->tracks.size()) {
|
|
track = path->tracks[i];
|
|
if (!libsaria::exists(track->filepath)) {
|
|
println("Reaping: " + track->filepath);
|
|
lib_playlist.remove_track(track);
|
|
path->tracks.erase(path->tracks.begin() + i);
|
|
} else
|
|
i++;
|
|
}
|
|
|
|
libsaria::notify(PATH_UPDATED, path);
|
|
save_path(path);
|
|
}
|
|
|
|
struct ScanData {
|
|
struct libsaria::library::Path *path;
|
|
list<string> files;
|
|
};
|
|
|
|
static void setup_scan_data(struct ScanData *scan, list<string> &files)
|
|
{
|
|
list<string>::iterator it;
|
|
|
|
if (files.size() <= MAX_SCAN)
|
|
it = files.end();
|
|
else {
|
|
it = files.begin();
|
|
for (unsigned int i = 0; i < MAX_SCAN; i++)
|
|
it++;
|
|
}
|
|
|
|
scan->files.splice(scan->files.begin(), files, files.begin(), it);
|
|
}
|
|
|
|
static bool find_file(libsaria::library::Path *path, string &file)
|
|
{
|
|
for (unsigned int i = 0; i < path->tracks.size(); i++) {
|
|
if (path->tracks[i]->filepath == file)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static void scan_path(void *data)
|
|
{
|
|
struct ScanData *scan = (struct ScanData *)data;
|
|
list<string>::iterator it;
|
|
libsaria::library::Path *path = scan->path;
|
|
libsaria::Track *track;
|
|
|
|
for (it = scan->files.begin(); it != scan->files.end(); it++) {
|
|
/*
|
|
* TODO: What I really should do for this check is build up
|
|
* a path component tree right before scanning, and then walk
|
|
* the tree to check if the path exists. It'll be much faster
|
|
* than having to walk the same list over and over...
|
|
*/
|
|
if (find_file(path, *it))
|
|
continue;
|
|
|
|
try {
|
|
track = new libsaria::Track(*it, path);
|
|
path->tracks.push_back(track);
|
|
lib_playlist.push_back(track);
|
|
} catch (string message) {
|
|
println(message);
|
|
}
|
|
}
|
|
|
|
libsaria::notify(PATH_UPDATED, path);
|
|
delete scan;
|
|
}
|
|
|
|
static void update_path(void *d)
|
|
{
|
|
struct libsaria::library::Path *path;
|
|
list<string> file_list;
|
|
unsigned int i;
|
|
struct ScanData *data;
|
|
|
|
path = (struct libsaria::library::Path *)d;
|
|
libsaria::list_dir(path->path, file_list);
|
|
println("Found: %d files to scan", file_list.size());
|
|
|
|
i = 0;
|
|
while (file_list.size() > 0) {
|
|
data = new ScanData;
|
|
data->path = path;
|
|
setup_scan_data(data, file_list);
|
|
libsaria::idle::schedule(scan_path, data);
|
|
if ((i++ % 50) == 0)
|
|
save_path(path);
|
|
}
|
|
save_path(path);
|
|
}
|
|
|
|
void do_update_path(struct libsaria::library::Path *path)
|
|
{
|
|
println("Updating path: " + path->path);
|
|
|
|
if (!libsaria::exists(path->path)) {
|
|
libsaria::library::delete_path(path);
|
|
return;
|
|
}
|
|
|
|
libsaria::idle::schedule(validate_path, path);
|
|
libsaria::idle::schedule(update_path, path);
|
|
}
|