Improved startup efficiency, don't store as much for library

git-svn-id: file:///home/anna/Desktop/ocarina-legacy/mithos/ocarina@47 1daee41c-8060-4895-b1f0-2197c00d777a
This commit is contained in:
bjschuma 2009-07-29 22:12:04 +00:00
parent 396631bc3d
commit 207febb3bc
12 changed files with 400 additions and 144 deletions

View File

@ -14,6 +14,9 @@ clean:
compile:
cd src && ./cythonize
count:
cat src/*.py | grep -v '[[:space:]]*\#' | cat -b
install:
# mkdir ~/bin/ocarina-bin
rsync -avz src/ ~/bin/ocarina-bin/src

View File

@ -1,8 +1,8 @@
import gtk
from libView import LibView
#from libView import LibView
from scrobbler import Scrobbler
from plistView import PlistView
#from plistView import PlistView
from controlPanel import ControlPanel
from rightPane import RightPane

View File

@ -6,8 +6,8 @@ from library import Library
class Data:
def __init__(self,options):
path = os.path.join(options.user,".ocarina")
self.updateQ = False
self.updateList = False
#self.updateQ = False
#self.updateList = False
self.path = path
self.song = None
self.quit = None
@ -20,9 +20,11 @@ class Data:
# Dump user data to a file
def dump(self):
libview = self.library.libview
self.library.libview = None
self.save(self.library,"library")
self.save([self.curList,self.curQ,self.curSong,self.playingQ],"playlist")
self.library.libview = libview
self.save([self.curList,self.curQ,self.curSong],"playlist")
self.save([self.size,self.divider,self.colSizes,self.sortedCol,self.random],"preferences")
self.save([self.lfm,self.lfmuser,self.lfmpass],"last.fm")
@ -46,18 +48,18 @@ class Data:
self.curList = []
self.curQ = []
self.curSong = 0
self.playingQ = False
#self.playingQ = False
else:
self.curList = plist[0]
self.curQ = plist[1]
self.curSong = plist[2]
self.playingQ = plist[3]
#self.playingQ = plist[3]
prefs = self.load2("preferences")
if prefs == None:
self.size = (800,600)
self.divider = 150
self.colSizes = [110,110,110,110,110]
self.colSizes = [200,110,110,110,110]
self.sortedCol = 3
self.random = False
else:

View File

@ -1,20 +1,27 @@
import gtk
import gobject
import thread
from list import List
from menuItem import MenuItem
class LibList(List):
def __init__(self,data):
List.__init__(self,data,"Library")
def __init__(self,data,playlist,queue,nextFunc,labelFunc,plause):
List.__init__(self,data,"Library",nextFunc,labelFunc,plause)
self.plist = playlist
self.queue = queue
self.pbar = gtk.ProgressBar()
self.pbaralign = gtk.Alignment(0,0,0,0)
self.pbaralign.add(self.pbar)
self.pbaralign.show()
self.updating = False
for file in self.data.library.files:
self.insert(file)
self.filterRows("")
self.populated = False
#for file in self.data.library.files:
# self.insert(file)
self.count = len(self.data.library.files)
self.makeLabel()
self.makeRCMenu()
def updates(self):
@ -23,6 +30,13 @@ class LibList(List):
gobject.timeout_add(500,self.updateLibview)
def visible(self,func):
List.visible(self,func)
if (func == "show") and (self.populated == False):
for file in self.data.library.files:
List.insert(self,file)
self.populated = True
def stopUpdates(self):
self.updating = False
self.pbar.hide()
@ -30,7 +44,31 @@ class LibList(List):
def updateLibview(self):
self.makeLabel()
self.pbar.pulse()
self.makeLabel()
self.timeText()
return self.updating
def filterRows(self,string):
if self.updating == True:
return
List.filterRows(self,string)
def makeRCMenu(self):
List.makeRCMenu(self)
toQ = MenuItem("Add to queue",self.addToQueue,None,None,None)
self.rcmenu.prepend(toQ)
toPlist = MenuItem("Add to playlist",self.addToPlist,None,None,None)
self.rcmenu.prepend(toPlist)
def addToPlist(self,widgit,func,data):
self.selection(self.plist.insert)
self.plist.filterRows("")
def addToQueue(self,widgit,func,data):
self.selection(self.queue.insert)
self.queue.filterRows("")

View File

@ -27,6 +27,7 @@ class Library:
return
self.traverse("")
self.libview.stopUpdates()
self.data.dump()
def reset(self):
@ -120,22 +121,22 @@ class Library:
else:
self.albTrk[(artist,album)] += [index]
for letter in title:
info.single[letter] = True
for letter in artist:
info.single[letter] = True
for letter in album:
info.single[letter] = True
#for letter in title:
# info.single[letter] = True
#for letter in artist:
# info.single[letter] = True
#for letter in album:
# info.single[letter] = True
for i in range(len(title)-1):
str = title[i]+title[i+1]
info.double[str] = True
for i in range(len(artist)-1):
str = artist[i]+artist[i+1]
info.double[str] = True
for i in range(len(album)-1):
str = album[i]+album[i+1]
info.double[str] = True
#for i in range(len(title)-1):
# str = title[i]+title[i+1]
# info.double[str] = True
#for i in range(len(artist)-1):
# str = artist[i]+artist[i+1]
# info.double[str] = True
#for i in range(len(album)-1):
# str = album[i]+album[i+1]
# info.double[str] = True
self.libview.insert(info)

View File

@ -1,42 +1,27 @@
import gtk
import re
from menuItem import MenuItem
from song import Song
class List(gtk.ScrolledWindow):
def __init__(self,data,text):
def __init__(self,data,text,nextFunc,labelFunc,plauseFunc):
gtk.ScrolledWindow.__init__(self)
self.show()
self.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
self.text = text
self.data = data
# Function pointers...whoo...
self.next = nextFunc
self.labels = labelFunc
self.plause = plauseFunc
self.count = 0
self.seconds = 0
self.list = gtk.ListStore(int,str,str,str,str,int)
self.tree = gtk.TreeView(self.list)
self.data = data
cell = gtk.CellRendererText()
cols = ["Id","Title","Length","Artist","Album","#"]
for i in range(len(cols)):
col = gtk.TreeViewColumn(cols[i],cell)
col.add_attribute(cell,'text',i)
col.set_resizable(True)
col.set_sort_column_id(i)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_min_width(2)
col.set_max_width(700)
col.set_sort_indicator(False)
if cols[i] != "Id":
self.tree.append_column(col)
col.set_fixed_width(self.data.colSizes[i-1])
self.tree.set_rules_hint(True)
self.tree.connect("row-activated",self.selectSong,"cliked",list)
self.sel = self.tree.get_selection()
self.sel.set_mode(gtk.SELECTION_MULTIPLE)
self.list.set_sort_column_id(self.data.sortedCol,gtk.SORT_ASCENDING)
self.tree.show()
self.add(self.tree)
self.show()
self.resizeCols()
self.makeList()
self.label = gtk.Label()
self.makeLabel()
@ -54,22 +39,53 @@ class List(gtk.ScrolledWindow):
#self.align.show()
def selectSong(self):
print "song selected"
def makeList(self):
self.list = gtk.ListStore(int,str,str,str,str,int)
self.tree = gtk.TreeView(self.list)
cell = gtk.CellRendererText()
cols = ["Id","Title","Length","Artist","Album","#"]
for i in range(len(cols)):
col = gtk.TreeViewColumn(cols[i],cell)
col.add_attribute(cell,'text',i)
col.set_resizable(True)
col.set_sort_column_id(i)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_min_width(2)
col.set_max_width(700)
col.set_sort_indicator(False)
if cols[i] != "Id":
self.tree.append_column(col)
col.set_fixed_width(self.data.colSizes[i-1])
self.tree.set_rules_hint(True)
self.tree.connect("row-activated",self.selectSong,"clicked",list)
self.tree.connect("button_release_event",self.clicked)
self.sel = self.tree.get_selection()
self.sel.set_mode(gtk.SELECTION_MULTIPLE)
self.list.set_sort_column_id(self.data.sortedCol,gtk.SORT_ASCENDING)
#self.tree.show()
self.add(self.tree)
def resizeCols(self):
print "resize cols"
def selectSong(self,widgit,iter,path,data,list):
self.loadSong(self.data.library.files[self.filter[iter][0]])
self.plause(None,None)
self.data.scrobbler.nowPlaying(self.data.song.info)
def clicked(self,widgit,data):
if data.button == 3:
self.rcmenu.popup(None,None,None,data.button,data.time)
def insert(self,file):
self.list.insert(self.count,[file.id,file.title,file.length,file.artist,file.album,file.count])
self.makeLabel()
self.timeText()
self.count+=1
self.seconds+=file.duration
def makeLabel(self):
print self.count, self.text
self.label.set_text(self.text+" ("+str(self.count)+")")
@ -122,10 +138,13 @@ class List(gtk.ScrolledWindow):
self.seconds = 0
self.count = 0
self.filter.refilter()
for row in self.filter:
#for row in self.filter:
#file = self.data.library.files[row[0]]
self.seconds+=self.data.library.files[row[0]].duration
self.count+=1
# self.seconds+=self.data.library.files[row[0]].duration
# self.count+=1
self.count = len(self.filter)
for i in range(self.count):
self.seconds+=self.data.library.files[self.filter[i][0]].duration
self.makeLabel()
self.timeText()
@ -133,34 +152,75 @@ class List(gtk.ScrolledWindow):
def hideRows(self,list,iter,string):
file = self.data.library.files[list[iter][0]]
if self.string == "":
self.visibleSong(file)
return True
elif len(self.string) == 1:
try:
file.single[self.string]
self.visibleSong(file)
return True
except:
return False
elif len(self.string) == 2:
try:
file.double[self.string]
self.visibleSong(file)
return True
except:
return False
#elif len(self.string) == 1:
#return (self.string in file.single)
#try:
# file.single[self.string]
# return True
#except:
# return False
#elif len(self.string) == 2:
# return (self.string in file.double)
#try:
# file.double[self.string]
# return True
#except:
# return False
if re.search(self.string,file.titlel):
self.visibleSong(file)
return True
elif re.search(self.string,file.artistl):
self.visibleSong(file)
return True
elif re.search(self.string,file.albuml):
self.visibleSong(file)
return True
return False
def visibleSong(self,file):
self.seconds += file.duration
self.count+=1
def makeRCMenu(self):
self.rcmenu = gtk.Menu()
rm = MenuItem("Remove from "+self.text.lower(),self.rm,None,None,None)
self.rcmenu.append(rm)
def rm(self,widgit,func,data):
#print widgit,data,selection
print "remove"
def selection(self,func):
(model,pathlist) = self.sel.get_selected_rows()
for path in pathlist:
func(self.data.library.files[model[path[0]][0]])
self.sel.unselect_path(path)
def loadSong(self,file):
if self.data.song:
self.data.scrobbler.submit(self.data.song.timestamp)
self.data.song.close()
self.data.song = Song(file,self.next)
self.data.curSong = file.id
self.labels()
def gotoCurSong(self):
if len(self.filter) == 0:
return
for i in range(len(self.tree)):
if self.tree[i][0] == self.data.curSong:
print self.tree[i][0],self.data.curSong
if i > 10:
self.tree.scroll_to_cell(i-10,None,True,0,0)
else:
self.tree.scroll_to_cell(0,None,True,0,0)
self.tree.set_cursor_on_cell(i,None,None,False)
#return
def visible(self,func):
if func=="show":
self.align.show()
self.tree.show()
else:
self.align.hide()
self.tree.hide()

View File

@ -1,7 +1,63 @@
from list import List
import random
from menuItem import MenuItem
class Playlist(List):
def __init__(self,data):
List.__init__(self,data,"Playlist")
print "playlist"
def __init__(self,data,queue,nextFunc,labelFunc,plause):
List.__init__(self,data,"Playlist",nextFunc,labelFunc,plause)
self.queue = queue
#for file in self.data.curList:
# List.insert(self,file)
self.populated = False
self.makeRCMenu()
def visible(self,func):
List.visible(self,func)
if (func == "show") and (self.populated == False):
for file in self.data.curList:
List.insert(self,file)
self.populated = True
self.makeLabel()
def insert(self,file):
if self.populated == False:
self.visible("show")
List.insert(self,file)
self.data.curList+=[file]
#self.populated = True
def drop(self):
List.drop(self)
self.data.curList = []
def getNext(self):
# If random is true, give back a random song
max = len(self.filter) - 1
if max == -1:
return False
if self.data.random == True:
self.data.curSong = self.filter[random.randint(0,max)][0]
# Otherwise, give back next non-filtered song
else:
next = self.filter[0][0]
for i in range(max):
if self.filter[i][0]==self.data.curSong:
next = self.filter[i+1][0]
break
self.data.curSong = next
self.loadSong(self.data.library.files[self.data.curSong])
return True
def makeRCMenu(self):
List.makeRCMenu(self)
toQ = MenuItem("Add to queue",self.addToQ,None,None,None)
self.rcmenu.prepend(toQ)
def addToQ(self,widgit,func,data):
self.selection(self.queue.insert)
self.queue.filterRows("")

View File

@ -1,6 +1,37 @@
from list import List
class Queue(List):
def __init__(self,data):
List.__init__(self,data,"Queue")
print "Making queue"
def __init__(self,data,nextFunc,labelFunc,plause):
List.__init__(self,data,"Queue",nextFunc,labelFunc,plause)
self.data = data
#for file in self.data.curQ:
# List.insert(self,self.data.library.files[file])
self.populated = False
self.count = len(self.data.curQ)
self.makeLabel()
#self.filterRows("")
def getNext(self):
if len(self.list) == 0:
return False
# Queue ignores random settings and filtering
self.data.curSong = self.list[0][0]
self.data.curQ.pop(self.data.curQ.index(self.data.curSong))
self.remove(self.list.get_iter_root())
self.filterRows(self.string)
self.loadSong(self.data.library.files[self.data.curSong])
return True
def insert(self,file):
List.insert(self,file)
self.data.curQ += [file.id]
def visible(self,func):
List.visible(self,func)
if (func == "show") and (self.populated == False):
for file in self.data.curQ:
List.insert(self,self.data.library.files[file])
self.populated = True

View File

@ -15,23 +15,32 @@ class RightPane(gtk.VBox):
gtk.VBox.__init__(self,False,0)
self.show()
self.data = data
print self.data.curSong
self.title = Label("",13000,700)
self.album = Label("",10000,400)
self.artist = Label("",10000,400)
self.setLabels()
self.pack_start(self.title,False,False,0)
self.pack_start(self.album,False,False,0)
infobox = gtk.HBox(False,0)
infobox.show()
infolabels = gtk.VBox(False,0)
infolabels.show()
infobox.pack_start(infolabels,False,False,0)
infolabels.pack_start(self.title,False,False,0)
infolabels.pack_start(self.album,False,False,0)
infolabels.pack_start(self.artist,False,False,0)
self.searchBar = gtk.Entry()
self.searchBar.connect("changed",self.textTyped)
self.searchBar.show()
artsearch = gtk.HBox(False,0)
artsearch.show()
artsearch.pack_start(self.artist,False,False,0)
artsearch.pack_end(self.searchBar,False,False,0)
self.pack_start(artsearch,False,False,0)
self.searchBar.connect("changed",self.textTyped)
searchalign = gtk.Alignment(1,1,0,0)
searchalign.show()
searchalign.add(self.searchBar)
infobox.pack_end(searchalign,False,False,0)
self.pack_start(infobox,False,False,0)
self.makeTabs()
self.makeControls()
@ -46,14 +55,14 @@ class RightPane(gtk.VBox):
self.pack_start(hbox,False,False,0)
hbox.show()
self.curTab = 0
self.changedTab(None,None,0)
self.status = ""
def setLabels(self):
title = "a"
album = "b"
artist = "c"
title = ""
album = ""
artist = ""
if self.data.song:
title = self.data.song.info.title
album = "from "+self.data.song.info.album
@ -67,22 +76,25 @@ class RightPane(gtk.VBox):
self.tabs = gtk.Notebook()
self.add(self.tabs)
self.tabs.show()
self.tabs.connect("switch-page",self.changedTab)
self.playlist = Playlist(self.data)
self.queue = Queue(self.data)
self.library = LibList(self.data)
self.queue = Queue(self.data,self.next,self.setLabels,self.plause)
self.playlist = Playlist(self.data,self.queue,self.next,self.setLabels,self.plause)
self.library = LibList(self.data,self.playlist,self.queue,self.next,self.setLabels,self.plause)
self.data.library.libview = self.library
self.tabs.append_page(self.playlist,self.playlist.label)
self.tabs.append_page(self.queue,self.queue.label)
self.tabs.append_page(self.library,self.library.label)
self.curTab = -1
self.tabs.connect("switch-page",self.changedTab)
#self.filter("")
def makeControls(self):
box = gtk.HBox(False,0)
box.show()
self.pauseImg = Image(None,gtk.STOCK_MEDIA_PAUSE)#Image(os.path.join("images","pause"))
self.pauseImg = Image(None,gtk.STOCK_MEDIA_PAUSE)
box.pack_start(CheckButton("Random",self.toggleRand,self.data.random),False,False,0)
@ -148,7 +160,21 @@ class RightPane(gtk.VBox):
def next(self,widgit,data):
print "next song"
loaded = self.queue.getNext()
if loaded == False:
loaded = self.playlist.getNext()
if not (self.status == "pafter") and (loaded==True):
self.plause(None,None)
self.data.scrobbler.nowPlaying(self.data.song.info)
self.gotoCurSong()
self.status = ""
self.data.dump()
def gotoCurSong(self):
self.playlist.gotoCurSong()
self.queue.gotoCurSong()
self.library.gotoCurSong()
def changeImg(self):
@ -158,17 +184,24 @@ class RightPane(gtk.VBox):
def changedTab(self,widgit,page,pagenum):
self.playlist.align.hide()
self.queue.align.hide()
self.library.align.hide()
self.curTab = pagenum
if pagenum == 0:
self.playlist.align.show()
elif pagenum == 1:
self.queue.align.show()
if self.curTab == pagenum:
return
if self.curTab == 0:
self.playlist.visible("hide")
elif self.curTab == 1:
self.queue.visible("hide")
else:
self.library.align.show()
self.filter(self.searchBar.get_text().lower())
self.library.visible("hide")
self.curTab = pagenum
if pagenum == 0:
self.playlist.visible("show")
elif pagenum == 1:
self.queue.visible("show")
else:
self.library.visible("show")
def dumpLib(self):
@ -180,13 +213,31 @@ class RightPane(gtk.VBox):
def textTyped(self,entry):
search = entry.get_text().lower()
self.filter(search)
#print self.curTab
def filter(self,search):
tabs = []
if self.curTab == 0:
self.playlist.filterRows(search)
#self.playlist.filterRows(search)
tabs = [0,1,2]
elif self.curTab == 1:
self.queue.filterRows(search)
#self.queue.filterRows(search)
tabs = [1,0,2]
else:
self.library.filterRows(search)
#self.library.filterRows(search)
tabs = [2,0,1]
for tab in tabs:
if tab == 0:
self.playlist.filterRows(search)
elif tab == 1:
self.queue.filterRows(search)
else:
self.library.filterRows(search)
def setStatus(self,status):
if status == "pafter":
self.status = "pafter"
else:
print status

View File

@ -7,6 +7,7 @@ import webbrowser
import hashlib
import datetime
import time
import thread
from button import Button
@ -57,14 +58,14 @@ class Scrobbler(gtk.VBox):
self.pack_start(passwd,False,False,0)
self.pack_start(password,False,False,0)
else:
#self.handshake()
thread.start_new_thread(self.handshake,("",""))
#self.labels = [gtk.Label("")]*10
self.similar = []
for i in range(10):
label = gtk.Label(" ")
label.show()
self.pack_start(label,False,False,0)
self.similar+=[label]
label.show()
def fetchSession(self,widgit,username,uname,password,passwd):
@ -91,7 +92,7 @@ class Scrobbler(gtk.VBox):
self.makegui()
def handshake(self):
def handshake(self,widgit,data):
print "shaking hands"
url = "http://post.audioscrobbler.com/?hs=true"
list = [("hs","true")]
@ -113,7 +114,9 @@ class Scrobbler(gtk.VBox):
# print line.strip()
def nowPlaying(self,info):
if self.session == None:
if self.data.lfm == "":
return
elif self.session == None:
self.handshake()
vals = {"s":self.session,
"a":info.artist.title(),
@ -133,9 +136,17 @@ class Scrobbler(gtk.VBox):
# print "Submission successful"
# Submit song and increment play count
# Playcount incremented if length < 30 seconds OR
# song played for > 240 seconds OR song played for > 1/2 total time
def submit(self,timestp):
if self.data.lfm == "":
return
elif self.session == None:
self.handshake()
info = self.data.song.info
if info.duration < 30:
info.count+=1
return
exit = True
if (self.data.song.position > 240):
@ -145,7 +156,7 @@ class Scrobbler(gtk.VBox):
if exit == True:
return
info.count+=1
vals = {"s":self.session,
"a[0]":info.artist.title(),
"t[0]":info.title.title(),
@ -160,8 +171,8 @@ class Scrobbler(gtk.VBox):
req = urllib2.Request(self.suburl,data)
req.add_header("User-Agent","Ocarina")
status = urllib2.urlopen(req)
for line in status:
print line
#for line in status:
# print line
#print status

View File

@ -15,8 +15,8 @@ class SongInfo:
self.albuml = ""
self.artist = ""
self.artistl = ""
self.single = dict()
self.double = dict()
#self.single = dict()
#self.double = dict()
def setTime(self,time):

View File

@ -4,8 +4,8 @@ import thread
from contentPane import ContentPane
from menuItem import MenuItem
from libView import LibView
from plistView import PlistView
#from libView import LibView
#from plistView import PlistView
from controlPanel import ControlPanel
#from infoView import InfoView
from scrobbler import Scrobbler
@ -51,7 +51,8 @@ class Window(gtk.Window):
# Replace first 'None' with after track functions
pafter = MenuItem("Pause After Current Track",self.setPlayStatus,"pafter",None,None)
qafter = MenuItem("Quit After Current Track",None,"qafter",None,None)
playback = MenuItem("Playback",None,None,None,[pafter,qafter])
curSong = MenuItem("Go to Current Song",self.gotoCurSong,"cursng",None,None)
playback = MenuItem("Playback",None,None,None,[pafter,qafter,curSong])
bar.append(playback)
bar.show()
@ -66,13 +67,15 @@ class Window(gtk.Window):
def clearPlist(self,widgit,data,other=None):
self.data.curList = []
#self.data.updateList = True
self.plistview.clearList(self.plistview.plist,self.plistview.ptime)
self.contentPane.right.playlist.drop()
def setPlayStatus(self,widgit,status,other):
self.plistview.setStatus(status)
self.contentPane.right.setStatus(status)
def gotoCurSong(self,widgit,status,other):
self.contentPane.right.gotoCurSong()
# Used to select a directory