Playlists will want to use this when reading saved state to figure out what tracks they hold. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
59 lines
1.6 KiB
Python
59 lines
1.6 KiB
Python
# Copyright 2020 (c) Anna Schumaker.
|
|
from lib import publisher
|
|
import pathlib
|
|
import threading
|
|
|
|
# Note that these are called in the LibraryPath thread, and not the main thread
|
|
TrackAdded = publisher.Publisher()
|
|
TrackRemoved = publisher.Publisher()
|
|
IDLock = threading.Lock()
|
|
NextID = 0
|
|
|
|
class LibraryPath:
|
|
def __init__(self, path):
|
|
self.path = pathlib.Path(path)
|
|
self.tracks = dict()
|
|
self.thread = None
|
|
self.lock = threading.Lock()
|
|
|
|
def __getitem__(self, trackid):
|
|
return self.tracks.get(trackid)
|
|
|
|
def __scan_remove(self):
|
|
with self.lock:
|
|
removed = [ (id, track) for (id, track) in self.tracks.items() if not track.exists() ]
|
|
for (id, track) in removed:
|
|
del self.tracks[id]
|
|
TrackRemoved.publish(track)
|
|
return set([ track for (id, track) in self.tracks.items() ])
|
|
|
|
def __do_scan__(self):
|
|
global NextID
|
|
|
|
track_set = self.__scan_remove()
|
|
files = [ f for f in self.path.rglob("*") if f.is_file() and f not in track_set ]
|
|
with self.lock as A, IDLock as B:
|
|
for f in files:
|
|
self.tracks[NextID] = f
|
|
NextID += 1
|
|
TrackAdded.publish(f)
|
|
|
|
self.thread = None
|
|
|
|
def scan(self):
|
|
if not self.thread:
|
|
self.thread = threading.Thread(target = self.__do_scan__)
|
|
self.thread.start()
|
|
return self
|
|
|
|
def join(self):
|
|
if self.thread:
|
|
self.thread.join()
|
|
|
|
|
|
def reset():
|
|
global NextID
|
|
TrackAdded.reset()
|
|
TrackRemoved.reset()
|
|
NextID = 0
|