ocarina/libsaria/sources/library.py
Bryan Schumaker d91c099723 Added set_attr to the Source() class
Having access to the set_attr function should allow us to change
attributes for the current track easily.
2010-12-17 23:28:55 -05:00

305 lines
5.5 KiB
Python

# Bryan Schumaker (11/05/2010)
import libsaria
import libsaria.sources
import libsaria.path.files
from libsaria import threads
splitext = libsaria.path.splitext
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
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 load():
global fs_tree
global tag_tree
global index
global tracks
global locations
global lib_lock
global loaded
objects = libsaria.path.files.load("library", ".lib")
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()
libsaria.event.start("POSTLIBLOAD")
def is_loaded():
lib_lock.acquire()
val = loaded
lib_lock.release()
return val
def init_bg(callback):
init()
load()
callback()
def save():
global sources
libsaria.path.files.save( (locations, tracks, fs_tree, tag_tree, index),
"library", ".lib")
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 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 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_tags(artist, album, new_value)
else:
rec.__dict__[attr] = new_value
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 add_location(path):
global locations
if path.__class__ == unicode:
path = str(path)
if path not in locations:
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()