aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2021-12-29 13:37:28 +0000
committerdakkar <dakkar@thenautilus.net>2021-12-29 13:37:28 +0000
commit7734605735a027b5e998563e8cbc46b9ae3f9dbb (patch)
tree14bb8cbe1e831d4b34cc66b7e903099fc3b6762d
parentmove more stuff around (diff)
downloadmedia-control-7734605735a027b5e998563e8cbc46b9ae3f9dbb.tar.gz
media-control-7734605735a027b5e998563e8cbc46b9ae3f9dbb.tar.bz2
media-control-7734605735a027b5e998563e8cbc46b9ae3f9dbb.zip
scandir
-rw-r--r--config.toml3
-rw-r--r--lib/App/MediaControl.rakumod25
-rw-r--r--lib/App/MediaControl/DB.rakumod41
-rw-r--r--lib/ScanDir.rakumod49
4 files changed, 114 insertions, 4 deletions
diff --git a/config.toml b/config.toml
index 05a0b0f..8970478 100644
--- a/config.toml
+++ b/config.toml
@@ -7,3 +7,6 @@ port = 8090
[db]
filename = "media-files.sqlite"
+
+[media]
+root = "/home/dakkar/Music" \ No newline at end of file
diff --git a/lib/App/MediaControl.rakumod b/lib/App/MediaControl.rakumod
index 77fda99..cf635d4 100644
--- a/lib/App/MediaControl.rakumod
+++ b/lib/App/MediaControl.rakumod
@@ -1,5 +1,6 @@
use v6.d;
use DB::SQLite;
+use ScanDir;
use Vlc::Client;
use Lirc::Client;
use Lirc::Commands;
@@ -35,8 +36,32 @@ class App::MediaControl {
);
}
+ method !start-scan() {
+ my $root = $.config<media><root>;
+ $!db.clear-seen();
+ start react {
+ whenever scan-dir($root) -> $item {
+ when $item ~~ $root {}
+ when $item ~~ ScanDir::End { $!db.remove-unseen() }
+
+ my $path = $item.parent.relative($root);
+ $path = '' if $path eq '.';
+ my $name = $item.basename;
+
+ if !$item.e {
+ $!db.remove-entry(:$path,:$name);
+ }
+ else {
+ my $is-dir = $item.d;
+ $!db.add-entry(:$path,:$name,:$is-dir);
+ }
+ }
+ }
+ }
+
method start() {
$!db.ensure-schema();
+ self!start-scan();
$!web.start();
}
diff --git a/lib/App/MediaControl/DB.rakumod b/lib/App/MediaControl/DB.rakumod
index 7ce562e..da86d24 100644
--- a/lib/App/MediaControl/DB.rakumod
+++ b/lib/App/MediaControl/DB.rakumod
@@ -26,17 +26,36 @@ class App::MediaControl::DB {
.query(q:to/END/);
CREATE TABLE files (
id INTEGER PRIMARY KEY,
- parent_id INTEGER NULL REFERENCES files(id),
+ parent_id INTEGER NULL REFERENCES files(id)
+ ON DELETE CASCADE,
matpath TEXT NOT NULL,
name TEXT NOT NULL,
is_dir BOOLEAN NOT NULL,
watched_time INTEGER NULL,
+ seen BOOLEAN NOT NULL DEFAULT false,
UNIQUE (matpath, name)
)
END
}
}
+ method clear-seen() {
+ self!db: {
+ .query(q:to/END/)
+ UPDATE files SET seen=false
+ END
+ }
+ }
+
+ method remove-unseen() {
+ self!db: {
+ .query(q:to/END/)
+ DELETE FROM files
+ WHERE seen=false
+ END
+ }
+ }
+
method add-entry(Str :$path! is copy, Str :$name!, Bool :$is-dir!) {
$path ~~ s{<!after '/'>$} = '/';
$path ~~ s{<!before '/'>^} = '/';
@@ -50,12 +69,26 @@ class App::MediaControl::DB {
newrow(path,name,is_dir) AS (
VALUES($path, $name, $is_dir)
)
- INSERT INTO files(parent_id,matpath,name,is_dir)
- SELECT id, newrow.path, name, is_dir
+ INSERT INTO files(parent_id,matpath,name,is_dir,seen)
+ SELECT id, newrow.path, name, is_dir, true
FROM newrow
LEFT JOIN parent ON parent.path=newrow.path
WHERE true
- ON CONFLICT (matpath,name) DO NOTHING
+ ON CONFLICT (matpath,name) DO UPDATE SET seen=true
+ END
+ }
+ }
+
+ method remove-entry(Str :$path! is copy, Str :$name!) {
+ $path ~~ s{<!after '/'>$} = '/';
+ $path ~~ s{<!before '/'>^} = '/';
+
+ note "remove-entry($path,$name)";
+ self!db: {
+ .query(q:to/END/, :$path, :$name);
+ DELETE FROM files
+ WHERE name=$name
+ AND matpath=$path
END
}
}
diff --git a/lib/ScanDir.rakumod b/lib/ScanDir.rakumod
new file mode 100644
index 0000000..f3173a4
--- /dev/null
+++ b/lib/ScanDir.rakumod
@@ -0,0 +1,49 @@
+use v6.d;
+unit module ScanDir;
+
+class End {};
+
+sub scan-dir(*@paths --> Supply) is export {
+ supply {
+ my %watched-dirs;
+
+ CATCH { when X::IO { }; default { warn $_; done } }
+
+ sub start-watching(IO::Path $dir) {
+ return if %watched-dirs{$dir.Str};
+ %watched-dirs{$dir.Str} = True;
+
+ whenever $dir.watch {
+ my $path-io = .path.IO;
+ emit $path-io;
+ when $path-io ~~ :e & :d {
+ add-dir($path-io) unless %watched-dirs{$path-io.Str};
+ }
+ when $path-io ~~ :!e {
+ %watched-dirs{$path-io.Str}:delete
+ }
+ }
+ }
+
+ sub add-dir(*@todo) {
+ while @todo {
+ my $next = @todo.shift;
+
+ next unless $next ~~ :e & :r & :d;
+ start-watching($next);
+
+ for $next.dir {
+ emit $_;
+ when .e && .d {
+ @todo.push($_);
+ start-watching($_);
+ }
+ }
+ }
+
+ }
+
+ add-dir(@paths».IO);
+ emit End;
+ }
+}