ocarina/libsaria/sources/library.py
Bryan Schumaker 2a78d870ee libsaria: Set artwork from a local file
I set it in the new cache, rather than using the old one.
2011-05-07 16:45:04 -04:00

335 lines
6.2 KiB
Python

# Bryan Schumaker (11/05/2010)
import libsaria
import libsaria.sources
import libsaria.path.files
from libsaria import threads
splitext = libsaria.path.splitext
from libsaria.trees import *
from index import Index
os = None
tagpy = None
Track = None
FileRef = None
fs_tree = None
tag_tree = None
index = None
tracks = None
locations = None
size = None
visible = None
source = None
ttable = None
cur_id = -1
lib_lock = threads.get_mutex("library")
loaded = False
filtered = False
badfiles = set()
def init():
global source
global ttable
import string
ttable = dict()
for s in string.punctuation:
ttable[ord(s)] = u""
for s in string.lowercase:
ttable[ord(s)] = ord(s) - 32
source = libsaria.sources.Source()
source.get_attrs = get_attrs
source.set_attr = set_attr
source.get_cur_id = get_cur_id
source.save = save
def reset():
from libsaria.trees import FSTree, DLFSTree, DLValTree
from index import Index
global index
global tracks
global fs_tree
global tag_tree
global locations
global visible
locations = []
fs_tree = DLFSTree()
tag_tree = DLValTree()
index = Index()
tracks = dict()
size = 0
visible = set()
def default_objects():
return ([], dict(), DLFSTree(), DLValTree(), Index())
def load():
global fs_tree
global tag_tree
global index
global tracks
global locations
global lib_lock
global loaded
objects = libsaria.storage.load_obj("library", default_objects)
if objects == None or len(objects) != 5:
reset()
else:
(locations, tracks, fs_tree, tag_tree, index) = objects
lib_lock.acquire()
loaded = True
lib_lock.release()
def is_loaded():
lib_lock.acquire()
val = loaded
lib_lock.release()
return val
def init_bg():
init()
load()
def save():
global sources
libsaria.storage.save_obj("library", (locations, tracks, fs_tree, tag_tree, index))
def walk():
for tag in tag_tree.walk():
yield tag[3]
def get_locations():
for loc in locations:
yield loc
def artists():
keys = tag_tree.keys()
keys.sort()
res = []
for key in keys:
res.append( (tag_tree[key].value, key) )
return res
def albums(artist):
art = tag_tree[artist]
keys = art.keys()
keys.sort()
res = []
for key in keys:
res.append( (art[key].value, key) )
return res
def titles(artist, album):
art = tag_tree[artist]
alb = art[album]
keys = alb.keys()
keys.sort()
res = []
for key in keys:
res.append( (alb[key].value, key) )
return res
def song_id(artist, album, title):
art = tag_tree[artist]
alb = art[album]
title = alb[title]
return title.keys()[0]
def has_id(id):
return tracks.get(id, None) != None
def get_cur_id():
return cur_id
def get_attrs(id, *attrs):
res = []
rec = tracks.get(id, None)
if rec == None:
return [0] * len(attrs)
get = rec.__dict__.get
tags = rec.tags.walk_vals_backwards()
append = res.append
for attr in attrs:
if attr == "id":
append(id)
elif attr == "filepath":
append(rec.fs.walk_path_backwards())
elif attr == "art":
from libsaria import lastfm
append(lastfm.get_artwork_id(id))
elif attr == "artist":
append(tags[0])
elif attr == "album":
append(tags[1])
elif attr == "title":
append(tags[2])
else:
append(get(attr, None))
if len(res) == 1:
return res[0]
return res
def walk_library(*attrs):
res = []
for id in walk():
res.append(get_attrs(id, *attrs))
return res
def set_attr(id, attr, new_value):
rec = tracks.get(id, None)
if rec:
if attr == "art":
from libsaria import lastfm
artist, album = get_attrs(id, "artist", "album")
lastfm.set_artwork(artist, album, new_value)
else:
rec.__dict__[attr] = new_value
save()
def inc_count(id = cur_id):
rec = tracks.get(id, None)
if rec:
rec.count += 1
save()
def play_id(id):
if load_id(id) == True:
libsaria.controls.play()
return True
return False
def load_id(id):
global cur_id
if tracks.get(id, None) == None:
return False
cur_id = id
return source.load_file(get_attrs(id, "filepath"))
def filter(text):
global visible
global index
global filtered
if len(text) > 0:
visible = index.filter(text)
filtered = True
else:
visible = None
filtered = False
def test_filter(text):
return index.filter(text)
def is_visible(id):
global filtered
global visible
if filtered == False:
return True
else:
return id in visible
def num_visible():
if filtered == True:
return len(visible)
else:
return len(tag_tree)
def add_location(path):
global locations
commonprefix = libsaria.path.commonprefix
if path.__class__ == unicode:
path = str(path)
to_remove = []
for loc in locations:
# Don't add a subdirectory of a current path
if commonprefix([path, loc]) == loc:
return
# Remove subdirectories of the requested path
if commonprefix([path, loc]) == path:
to_remove.append(loc)
for loc in to_remove:
locations.remove(loc)
locations.append(path)
def scan(path):
add_location(path)
update()
save()
def insert_track(path, ref):
global tracks
global ttable
global fs_tree
global tag_tree
global index
tags = ref.tag()
audio = ref.audioProperties()
ino = os.stat(path).st_ino
track = Track(tags, audio)
artist = tags.artist or u"Unknown Artist"
album = tags.album or u"Unknown Album"
title = tags.title or u"Unknown Title"
fs = fs_tree.insert_path(path)
tag = tag_tree.insert( [artist.translate(ttable),
album.translate(ttable),
title.translate(ttable), ino],
[artist, album, title, ino]
)
index.insert(ino, (artist, album, title))
track.fs = fs
track.tags = tag
tracks[ino] = track
def update_path(path):
global badfiles
tree = libsaria.path.make_tree(path)
for path in tree.walk_paths():
ext = splitext(path)[1]
if ext in badfiles:
continue
try:
ref = FileRef(path)
except Exception, e:
badfiles.add(ext)
print e
continue
try:
insert_track(path, ref)
except Exception, e:
print e
def update():
global os
global tagpy
global FileRef
global Track
import os
import tagpy
from track import Track
FileRef = tagpy.FileRef
sep = libsaria.path.sep
for path in locations:
update_path(path)
def update_bg2():
update()
save()
def update_bg():
if is_loaded():
from libsaria import threads
thr = threads.BG_Thread(update_bg2)
thr.start()