emmental/tagdb/__init__.py

112 lines
2.9 KiB
Python

# Copyright 2020 (c) Anna Schumaker.
from . import allocator
from . import stack
from . import tags
from . import track
import db
import lib
import pathlib
import scanner
import threading
File = "tagdb.pickle"
Bus = lib.bus.Bus(500)
Tracks = allocator.TrackAllocator()
Stack = stack.TagStack()
class LibraryTag(lib.tag.Tag):
def __init__(self, path):
super().__init__(path)
self.clear = lib.thread.Thread(self.__do_clear__)
self.scan = lib.thread.Thread(self.__do_scan__)
def __setstate__(self, state):
super().__setstate__(state)
self.clear = lib.thread.Thread(self.__do_clear__)
self.scan = lib.thread.Thread(self.__do_scan__)
def __do_scan__(self):
for trak in Tracks.autoremove(self):
self.remove_track(trak)
track_set = set([ t.filepath() for t in Tracks.list_tracks(self) ])
for f in self.name.rglob("*"):
if f not in track_set and f.is_file():
if (track := Tracks.allocate(self, f)) != None:
self.add_track(track)
def __do_clear__(self):
for trak in self.tracks:
Tracks.remove(trak)
self.tracks.clear()
def fix_tracks(self):
for (index, trak) in enumerate(self.tracks):
t = Tracks[trak]
if t is not None:
self.tracks[index] = t
class LibraryStore(lib.tagstore.TagStore):
def __alloc_tag__(self, name, sort):
return LibraryTag(name)
def add(self, name):
return super().__add_tag__(name, None, None)
def remove(self, lib):
lib.clear()
super().remove(lib)
def fix_tracks(self):
for (id, tag) in self.store.items():
tag.fix_tracks()
Library = LibraryStore()
def _do_save():
try:
with lib.data.DataFile(File, lib.data.WRITE) as f:
f.pickle([ tags.get_state(), Tracks, Library, Stack ])
except Exception as e:
return lib.bus.RETRY
def save(*args):
Bus.board(_do_save)
def load():
global Library
global Tracks
global Stack
if not db.new_db():
return
with lib.data.DataFile(File, lib.data.READ) as f:
if f.exists():
(tagstate, Tracks, Library, Stack) = f.unpickle()
tags.set_state(*tagstate)
Tracks.load_tags()
Library.fix_tracks()
__register_callbacks()
scanner.Queue.push(scanner.task.CommitTask())
def __register_callbacks():
for store in [ Library, tags.User, Tracks ]:
store.Added.register(save)
store.Removed.register(save)
Tracks.Updated.register(save)
Stack.PushPop.register(save)
Stack.NextTrack.register(save)
__register_callbacks()
def reset():
Tracks.reset()
Library.reset()
Stack.reset()
tags.reset()
Bus.clear()
lib.data.DataFile(File, lib.data.READ).remove()
__register_callbacks()