Another new icon from andrew, keeping track of play count, more work on last.fm
git-svn-id: file:///home/anna/Desktop/ocarina-legacy/mithos/ocarina@41 1daee41c-8060-4895-b1f0-2197c00d777a
This commit is contained in:
parent
0bf69cb3e3
commit
22c61164c1
Binary file not shown.
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 49 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
|
@ -1,3 +1,3 @@
|
|||
# Used for initializing things in the GuiObjects directory
|
||||
|
||||
__all__ = ['button','menuItem','libView','infoView','plistView']
|
||||
__all__ = ['button','check','controlPanel','image','scrobbler','menuItem','libView','infoView','plistView']
|
||||
|
|
|
@ -14,8 +14,10 @@ class Button(gtk.Button):
|
|||
#box.add(image)
|
||||
if text != None:
|
||||
label = gtk.Label(text)
|
||||
label.set_line_wrap(True)
|
||||
label.set_size_request(100,100)
|
||||
label.show()
|
||||
box.pack_start(label,False,False,0)
|
||||
box.pack_start(label,True,True,0)
|
||||
box.show()
|
||||
self.add(box)
|
||||
self.connect("clicked",func,name)
|
||||
|
|
|
@ -71,7 +71,7 @@ class ControlPanel(gtk.HBox):
|
|||
except:
|
||||
success = False
|
||||
if success == True:
|
||||
time = time/1000000000
|
||||
#time = time/1000000000
|
||||
pbar.set_fraction(float(time)/self.data.song.info.duration)
|
||||
pbar.set_text(self.data.song.info.fixTime(time) + " / " + self.data.song.info.length)
|
||||
return True
|
||||
|
|
|
@ -121,7 +121,7 @@ class PlistView(gtk.Notebook):
|
|||
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||
col.set_min_width(2)
|
||||
col.set_max_width(700)
|
||||
col.set_sort_indicator(True)
|
||||
col.set_sort_indicator(False)
|
||||
if cols[i] != "Id":
|
||||
tree.append_column(col)
|
||||
tree.set_rules_hint(True)
|
||||
|
@ -197,6 +197,15 @@ class PlistView(gtk.Notebook):
|
|||
# Go to the next song in the list
|
||||
def next(self,widgit,data):
|
||||
self.data.playingQ = False
|
||||
#print float(self.data.song.position)/float(self.data.song.info.duration)
|
||||
if (float(self.data.song.position)/float(self.data.song.info.duration)) >= 0.75:
|
||||
for row in self.plist:
|
||||
if row[0]==self.data.curSong:
|
||||
row[5]+=1
|
||||
break
|
||||
self.data.library.files[self.data.curSong].count+=1
|
||||
#if self.plist[self.data.curSong][0]==self.data.curSong:
|
||||
# self.plist[self.data.curSong][5]+=1
|
||||
if len(self.data.curQ) > 0:
|
||||
self.data.curSong = self.qlist[0][0]
|
||||
self.data.curQ.pop(self.data.curQ.index(self.data.curSong))
|
||||
|
|
|
@ -4,6 +4,9 @@ pygtk.require('2.0')
|
|||
import gtk
|
||||
import webbrowser
|
||||
import thread
|
||||
import hashlib
|
||||
|
||||
from button import Button
|
||||
|
||||
import xml.dom
|
||||
from xml.dom import minidom
|
||||
|
@ -14,40 +17,103 @@ class Scrobbler(gtk.VBox):
|
|||
gtk.VBox.__init__(self,False,0)
|
||||
self.data = data
|
||||
self.url = "http://ws.audioscrobbler.com/2.0/"
|
||||
self.key = "api_key=2c76f85a6704efd74b5a358821284ef9"
|
||||
self.token = "token="
|
||||
self.key = "2c76f85a6704efd74b5a358821284ef9"
|
||||
self.secret = "3a6012bfb627b60a884cf33fc044885c"
|
||||
self.token = ""
|
||||
|
||||
# Run these in new thread so we can keep loading other things while waiting
|
||||
thread.start_new_thread(self.setup,("setup",None))
|
||||
#self.fetchToken()
|
||||
#self.authorize()
|
||||
self.makegui()
|
||||
#thread.start_new_thread(self.setup,("setup",None))
|
||||
|
||||
#self.makeRequest()
|
||||
self.show()
|
||||
|
||||
|
||||
def makegui(self):
|
||||
if self.data.lfm == "":
|
||||
self.nosession = Button("lfm",None,"Click here to configure Ocarina for submitting songs to last.fm",self.setup)
|
||||
self.nosession.set_size_request(100,100)
|
||||
self.pack_start(self.nosession,False,False,0)
|
||||
|
||||
|
||||
# One time setup (in theory)
|
||||
def setup(self,widgit,data):
|
||||
self.nosession.hide()
|
||||
self.remove(self.nosession)
|
||||
self.contBtn = Button("lfm",None,"Click to continue",self.fetchSession)
|
||||
self.pack_start(self.contBtn,False,False,0)
|
||||
self.fetchToken()
|
||||
self.authorize()
|
||||
|
||||
|
||||
def addMethod(self,method):
|
||||
return self.url+"?method="+method
|
||||
|
||||
def authorize(self):
|
||||
url = "http://www.last.fm/api/auth/?"
|
||||
url+=self.key+"&"+self.token
|
||||
webbrowser.open(url)
|
||||
|
||||
|
||||
# Fetch the authentication token
|
||||
def fetchToken(self):
|
||||
url = self.addMethod("auth.gettoken")+"&"+self.key
|
||||
req = urllib2.Request(url)
|
||||
req.add_header('User-Agent','Ocarina')
|
||||
status = minidom.parse(urllib2.urlopen(req)).documentElement
|
||||
|
||||
(url,list) = self.addMethod("auth.gettoken")
|
||||
(url,list) = self.addParam(url,list,"api_key",self.key)
|
||||
status = self.placeRequest(url)
|
||||
attr = status.getAttributeNode("status")
|
||||
if attr.value != "ok":
|
||||
return
|
||||
self.token += status.firstChild.nextSibling.firstChild.data
|
||||
print self.token
|
||||
self.token += hashlib.md5(status.firstChild.nextSibling.firstChild.data).hexdigest()
|
||||
|
||||
|
||||
# Open to authorization page
|
||||
def authorize(self):
|
||||
url = "http://www.last.fm/api/auth/?"
|
||||
(url,list) = self.addParam(url,[],"api_key",self.key)
|
||||
(url,list) = self.addParam(url,[],"token",self.token)
|
||||
#url+="&"+self.token
|
||||
webbrowser.open(url)
|
||||
|
||||
|
||||
def fetchSession(self,widgit,data):
|
||||
(url,list) = self.addMethod("auth.getSession")
|
||||
(url,list) = self.addParam(url,list,"api_key",self.key)
|
||||
(url,list) = self.addParam(url,list,"token",self.token)
|
||||
sig = self.getSig(list)
|
||||
(url,list) = self.addParam(url,None,"api_sig",sig)
|
||||
print url
|
||||
#status = self.placeRequest(url)
|
||||
return
|
||||
attr = status.getAttributeNode("status")
|
||||
if attr.value != "ok":
|
||||
return
|
||||
node = status.firstChild.firstChild
|
||||
user = node.data
|
||||
key = node.nextSibling.data
|
||||
subscriber = node.nextSibling.nextSibling.data
|
||||
#print user,key,subscriber
|
||||
|
||||
|
||||
def addMethod(self,method):
|
||||
return (self.url+"?method="+method,[("method",method)])
|
||||
|
||||
|
||||
def addParam(self,url,list,param,val):
|
||||
url+="&"+param+"="+val
|
||||
if list:
|
||||
list += [(param,val)]
|
||||
return url,list
|
||||
#return (url+"&"+param+"="+val,list+[(param,val)])
|
||||
|
||||
|
||||
def getSig(self,list):
|
||||
list.sort()
|
||||
string = ""
|
||||
for entry in list:
|
||||
string+=entry[0]+entry[1]
|
||||
string = string + self.secret
|
||||
m = hashlib.md5(string)
|
||||
return m.hexdigest()
|
||||
|
||||
|
||||
def sendReq(self,req):
|
||||
req+=self.secret
|
||||
#hash = md5.new(req).digest()
|
||||
#return self.placeRequest(self.url+"?"+hash)
|
||||
|
||||
|
||||
def placeRequest(self,url):
|
||||
print url
|
||||
req = urllib2.Request(url)
|
||||
req.add_header('User-Agent','Ocarina')
|
||||
return minidom.parse(urllib2.urlopen(req)).documentElement
|
||||
|
|
|
@ -9,9 +9,10 @@ import thread
|
|||
class Library:
|
||||
#def __init__(self,prnt):
|
||||
def __init__(self):
|
||||
self.goodTypes = ["ogg","mp3"]#,"wma"]
|
||||
self.goodTypes = ["ogg","mp3","wav","avi","flac","mid"]#,"wma"]
|
||||
self.reset()
|
||||
self.scanning = False
|
||||
#self.notAdded = open("/home/bjschuma/Desktop/notAdded.txt",'w')
|
||||
|
||||
|
||||
# Begin a scan on dir
|
||||
|
@ -53,9 +54,14 @@ class Library:
|
|||
tSplit = entry.rsplit('.')
|
||||
type = tSplit[len(tSplit)-1].lower()
|
||||
if (type in self.goodTypes) == True:
|
||||
song = SongInfo()
|
||||
song.filename = os.path.join(self.path,joined)
|
||||
self.files+=[song]
|
||||
thread.start_new_thread(self.add,(self.hash(joined),self.count))
|
||||
self.count += 1
|
||||
thread.start_new_thread(self.add,(self.hash(joined),joined,self.count-1))
|
||||
#self.add(self.hash(joined),joined)
|
||||
#else:
|
||||
# self.notAdded.write(os.path.join(self.path,joined)+"\n")
|
||||
|
||||
|
||||
# Hash a file and return list of words
|
||||
|
@ -68,11 +74,8 @@ class Library:
|
|||
|
||||
|
||||
# Add song to library
|
||||
def add(self,words,file,index):
|
||||
#self.files+=[SongInfo()]
|
||||
self.files.insert(index,SongInfo())
|
||||
def add(self,words,index):
|
||||
info = self.files[index]
|
||||
info.filename = os.path.join(self.path,file)
|
||||
info.count = 0
|
||||
info.id = index
|
||||
split = info.filename.rsplit(os.sep)
|
||||
|
@ -87,6 +90,7 @@ class Library:
|
|||
else:
|
||||
info.artist = split[len(split)-3]
|
||||
|
||||
try:
|
||||
f = tagpy.FileRef(info.filename)
|
||||
t = f.tag()
|
||||
if t.title != "":
|
||||
|
@ -98,7 +102,8 @@ class Library:
|
|||
|
||||
a = f.audioProperties()
|
||||
info.setTime(a.length)
|
||||
|
||||
except:
|
||||
print info.filename
|
||||
artist = info.artist.lower()
|
||||
album = info.album.lower()
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ class main:
|
|||
self.data.size = self.window.get_size()
|
||||
self.data.divider = self.window.divider.get_position()
|
||||
self.window.plistview.saveCols()
|
||||
self.data.clearSong()
|
||||
#self.data.clearSong()
|
||||
self.data.dump()
|
||||
#self.library.dump()
|
||||
gtk.main_quit()
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import gobject
|
||||
import os
|
||||
import cPickle as pickle
|
||||
from library import Library
|
||||
|
@ -7,60 +8,74 @@ from song import Song
|
|||
class SavedData:
|
||||
def __init__(self,options):
|
||||
path = os.path.join(options.user,".ocarina")
|
||||
path = os.path.join(path,"ocarina-data.data")
|
||||
self.size = (800,600)
|
||||
self.divider = 150
|
||||
self.library = Library()
|
||||
self.curList = []
|
||||
self.curQ = []
|
||||
self.updateQ = False
|
||||
self.playingQ = False
|
||||
self.curSong = 0
|
||||
self.colSizes = [110,110,110,110,110]
|
||||
self.sortedCol = 3
|
||||
self.updateList = False
|
||||
self.path = path
|
||||
self.song = None
|
||||
self.random = False
|
||||
self.quit = None
|
||||
|
||||
if os.path.exists(path):
|
||||
try:
|
||||
if os.path.exists(self.path) == False:
|
||||
os.mkdir(self.path)
|
||||
self.load(path,options)
|
||||
except:
|
||||
if options.verbose == True:
|
||||
print "Error loading user data"
|
||||
#gobject.timeout_add(600000,self.dump)
|
||||
|
||||
|
||||
# Dump user data to a file
|
||||
def dump(self):
|
||||
out = open(self.path,'w')
|
||||
self.save(self.library,"library")
|
||||
self.save([self.curList,self.curQ,self.curSong,self.playingQ],"playlist")
|
||||
self.save([self.size,self.divider,self.colSizes,self.sortedCol,self.random],"preferences")
|
||||
self.save(self.lfm,"last.fm")
|
||||
|
||||
|
||||
def save(self,obj,file):
|
||||
out = open(os.path.join(self.path,file),'w')
|
||||
p = pickle.Pickler(out,1)
|
||||
p.dump(self)
|
||||
p.dump(obj)
|
||||
out.close()
|
||||
|
||||
|
||||
def clearSong(self):
|
||||
self.song.close()
|
||||
self.song = None
|
||||
return
|
||||
|
||||
|
||||
# Read user data from the file
|
||||
# Create values if files do not exist
|
||||
def load(self,path,options):
|
||||
if options.verbose == True:
|
||||
print "User data found, loading..."
|
||||
self.library = self.load2("library")
|
||||
if self.library == None:
|
||||
self.library = Library()
|
||||
|
||||
plist = self.load2("playlist")
|
||||
if plist == None:
|
||||
self.curList = []
|
||||
self.curQ = []
|
||||
self.curSong = 0
|
||||
self.playingQ = False
|
||||
else:
|
||||
self.curList = plist[0]
|
||||
self.curQ = plist[1]
|
||||
self.curSong = plist[2]
|
||||
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.sortedCol = 3
|
||||
self.random = False
|
||||
else:
|
||||
self.size = prefs [0]
|
||||
self.divider = prefs[1]
|
||||
self.colSizes = prefs[2]
|
||||
self.sortedCol = prefs[3]
|
||||
self.random = prefs[4]
|
||||
|
||||
self.lfm = self.load2("last.fm")
|
||||
if self.lfm == None:
|
||||
self.lfm = ""
|
||||
|
||||
|
||||
def load2(self,file):
|
||||
path = os.path.join(self.path,file)
|
||||
if os.path.exists(path):
|
||||
p = pickle.Unpickler(open(path))
|
||||
data = p.load()
|
||||
#self.size = data.size
|
||||
self.divider = data.divider
|
||||
self.library = data.library
|
||||
self.curList = data.curList
|
||||
self.curSong = 0
|
||||
self.colSizes = data.colSizes
|
||||
self.path = data.path
|
||||
self.random = data.random
|
||||
self.curSong = data.curSong
|
||||
self.curQ = data.curQ
|
||||
self.playingQ = data.playingQ
|
||||
|
||||
return data
|
||||
return None
|
||||
|
|
|
@ -68,4 +68,5 @@ class Song():
|
|||
def curTime(self):
|
||||
if self.playing == False:
|
||||
return (False,False)
|
||||
return (True, self.player.query_position(self.time_format,None)[0])
|
||||
self.position = self.player.query_position(self.time_format,None)[0]/1000000000
|
||||
return (True, self.position)
|
||||
|
|
|
@ -62,7 +62,7 @@ class Window(gtk.Window):
|
|||
def deleteLib(self,widgit,data,other=None):
|
||||
self.data.library.reset()
|
||||
self.libview.update()
|
||||
self.clearPlist()
|
||||
self.clearPlist(None,None)
|
||||
|
||||
|
||||
def clearPlist(self,widgit,data,other=None):
|
||||
|
|
Loading…
Reference in New Issue