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
|
# 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)
|
#box.add(image)
|
||||||
if text != None:
|
if text != None:
|
||||||
label = gtk.Label(text)
|
label = gtk.Label(text)
|
||||||
|
label.set_line_wrap(True)
|
||||||
|
label.set_size_request(100,100)
|
||||||
label.show()
|
label.show()
|
||||||
box.pack_start(label,False,False,0)
|
box.pack_start(label,True,True,0)
|
||||||
box.show()
|
box.show()
|
||||||
self.add(box)
|
self.add(box)
|
||||||
self.connect("clicked",func,name)
|
self.connect("clicked",func,name)
|
||||||
|
|
|
@ -71,7 +71,7 @@ class ControlPanel(gtk.HBox):
|
||||||
except:
|
except:
|
||||||
success = False
|
success = False
|
||||||
if success == True:
|
if success == True:
|
||||||
time = time/1000000000
|
#time = time/1000000000
|
||||||
pbar.set_fraction(float(time)/self.data.song.info.duration)
|
pbar.set_fraction(float(time)/self.data.song.info.duration)
|
||||||
pbar.set_text(self.data.song.info.fixTime(time) + " / " + self.data.song.info.length)
|
pbar.set_text(self.data.song.info.fixTime(time) + " / " + self.data.song.info.length)
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -121,7 +121,7 @@ class PlistView(gtk.Notebook):
|
||||||
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||||
col.set_min_width(2)
|
col.set_min_width(2)
|
||||||
col.set_max_width(700)
|
col.set_max_width(700)
|
||||||
col.set_sort_indicator(True)
|
col.set_sort_indicator(False)
|
||||||
if cols[i] != "Id":
|
if cols[i] != "Id":
|
||||||
tree.append_column(col)
|
tree.append_column(col)
|
||||||
tree.set_rules_hint(True)
|
tree.set_rules_hint(True)
|
||||||
|
@ -197,6 +197,15 @@ class PlistView(gtk.Notebook):
|
||||||
# Go to the next song in the list
|
# Go to the next song in the list
|
||||||
def next(self,widgit,data):
|
def next(self,widgit,data):
|
||||||
self.data.playingQ = False
|
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:
|
if len(self.data.curQ) > 0:
|
||||||
self.data.curSong = self.qlist[0][0]
|
self.data.curSong = self.qlist[0][0]
|
||||||
self.data.curQ.pop(self.data.curQ.index(self.data.curSong))
|
self.data.curQ.pop(self.data.curQ.index(self.data.curSong))
|
||||||
|
|
|
@ -4,6 +4,9 @@ pygtk.require('2.0')
|
||||||
import gtk
|
import gtk
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import thread
|
import thread
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
from button import Button
|
||||||
|
|
||||||
import xml.dom
|
import xml.dom
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
@ -14,40 +17,103 @@ class Scrobbler(gtk.VBox):
|
||||||
gtk.VBox.__init__(self,False,0)
|
gtk.VBox.__init__(self,False,0)
|
||||||
self.data = data
|
self.data = data
|
||||||
self.url = "http://ws.audioscrobbler.com/2.0/"
|
self.url = "http://ws.audioscrobbler.com/2.0/"
|
||||||
self.key = "api_key=2c76f85a6704efd74b5a358821284ef9"
|
self.key = "2c76f85a6704efd74b5a358821284ef9"
|
||||||
self.token = "token="
|
self.secret = "3a6012bfb627b60a884cf33fc044885c"
|
||||||
|
self.token = ""
|
||||||
|
|
||||||
# Run these in new thread so we can keep loading other things while waiting
|
# Run these in new thread so we can keep loading other things while waiting
|
||||||
thread.start_new_thread(self.setup,("setup",None))
|
self.makegui()
|
||||||
#self.fetchToken()
|
#thread.start_new_thread(self.setup,("setup",None))
|
||||||
#self.authorize()
|
|
||||||
|
|
||||||
#self.makeRequest()
|
|
||||||
self.show()
|
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):
|
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.fetchToken()
|
||||||
self.authorize()
|
self.authorize()
|
||||||
|
|
||||||
|
|
||||||
def addMethod(self,method):
|
# Fetch the authentication token
|
||||||
return self.url+"?method="+method
|
|
||||||
|
|
||||||
def authorize(self):
|
|
||||||
url = "http://www.last.fm/api/auth/?"
|
|
||||||
url+=self.key+"&"+self.token
|
|
||||||
webbrowser.open(url)
|
|
||||||
|
|
||||||
|
|
||||||
def fetchToken(self):
|
def fetchToken(self):
|
||||||
url = self.addMethod("auth.gettoken")+"&"+self.key
|
(url,list) = self.addMethod("auth.gettoken")
|
||||||
req = urllib2.Request(url)
|
(url,list) = self.addParam(url,list,"api_key",self.key)
|
||||||
req.add_header('User-Agent','Ocarina')
|
status = self.placeRequest(url)
|
||||||
status = minidom.parse(urllib2.urlopen(req)).documentElement
|
|
||||||
|
|
||||||
attr = status.getAttributeNode("status")
|
attr = status.getAttributeNode("status")
|
||||||
if attr.value != "ok":
|
if attr.value != "ok":
|
||||||
return
|
return
|
||||||
self.token += status.firstChild.nextSibling.firstChild.data
|
self.token += hashlib.md5(status.firstChild.nextSibling.firstChild.data).hexdigest()
|
||||||
print self.token
|
|
||||||
|
|
||||||
|
# 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:
|
class Library:
|
||||||
#def __init__(self,prnt):
|
#def __init__(self,prnt):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.goodTypes = ["ogg","mp3"]#,"wma"]
|
self.goodTypes = ["ogg","mp3","wav","avi","flac","mid"]#,"wma"]
|
||||||
self.reset()
|
self.reset()
|
||||||
self.scanning = False
|
self.scanning = False
|
||||||
|
#self.notAdded = open("/home/bjschuma/Desktop/notAdded.txt",'w')
|
||||||
|
|
||||||
|
|
||||||
# Begin a scan on dir
|
# Begin a scan on dir
|
||||||
|
@ -53,9 +54,14 @@ class Library:
|
||||||
tSplit = entry.rsplit('.')
|
tSplit = entry.rsplit('.')
|
||||||
type = tSplit[len(tSplit)-1].lower()
|
type = tSplit[len(tSplit)-1].lower()
|
||||||
if (type in self.goodTypes) == True:
|
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
|
self.count += 1
|
||||||
thread.start_new_thread(self.add,(self.hash(joined),joined,self.count-1))
|
|
||||||
#self.add(self.hash(joined),joined)
|
#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
|
# Hash a file and return list of words
|
||||||
|
@ -68,11 +74,8 @@ class Library:
|
||||||
|
|
||||||
|
|
||||||
# Add song to library
|
# Add song to library
|
||||||
def add(self,words,file,index):
|
def add(self,words,index):
|
||||||
#self.files+=[SongInfo()]
|
|
||||||
self.files.insert(index,SongInfo())
|
|
||||||
info = self.files[index]
|
info = self.files[index]
|
||||||
info.filename = os.path.join(self.path,file)
|
|
||||||
info.count = 0
|
info.count = 0
|
||||||
info.id = index
|
info.id = index
|
||||||
split = info.filename.rsplit(os.sep)
|
split = info.filename.rsplit(os.sep)
|
||||||
|
@ -87,18 +90,20 @@ class Library:
|
||||||
else:
|
else:
|
||||||
info.artist = split[len(split)-3]
|
info.artist = split[len(split)-3]
|
||||||
|
|
||||||
f = tagpy.FileRef(info.filename)
|
try:
|
||||||
t = f.tag()
|
f = tagpy.FileRef(info.filename)
|
||||||
if t.title != "":
|
t = f.tag()
|
||||||
info.title = t.title
|
if t.title != "":
|
||||||
if t.album != "":
|
info.title = t.title
|
||||||
info.album = t.album
|
if t.album != "":
|
||||||
if t.artist != "":
|
info.album = t.album
|
||||||
info.artist = t.artist
|
if t.artist != "":
|
||||||
|
info.artist = t.artist
|
||||||
a = f.audioProperties()
|
|
||||||
info.setTime(a.length)
|
|
||||||
|
|
||||||
|
a = f.audioProperties()
|
||||||
|
info.setTime(a.length)
|
||||||
|
except:
|
||||||
|
print info.filename
|
||||||
artist = info.artist.lower()
|
artist = info.artist.lower()
|
||||||
album = info.album.lower()
|
album = info.album.lower()
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class main:
|
||||||
self.data.size = self.window.get_size()
|
self.data.size = self.window.get_size()
|
||||||
self.data.divider = self.window.divider.get_position()
|
self.data.divider = self.window.divider.get_position()
|
||||||
self.window.plistview.saveCols()
|
self.window.plistview.saveCols()
|
||||||
self.data.clearSong()
|
#self.data.clearSong()
|
||||||
self.data.dump()
|
self.data.dump()
|
||||||
#self.library.dump()
|
#self.library.dump()
|
||||||
gtk.main_quit()
|
gtk.main_quit()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import gobject
|
||||||
import os
|
import os
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
from library import Library
|
from library import Library
|
||||||
|
@ -7,60 +8,74 @@ from song import Song
|
||||||
class SavedData:
|
class SavedData:
|
||||||
def __init__(self,options):
|
def __init__(self,options):
|
||||||
path = os.path.join(options.user,".ocarina")
|
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.updateQ = False
|
||||||
self.playingQ = False
|
|
||||||
self.curSong = 0
|
|
||||||
self.colSizes = [110,110,110,110,110]
|
|
||||||
self.sortedCol = 3
|
|
||||||
self.updateList = False
|
self.updateList = False
|
||||||
self.path = path
|
self.path = path
|
||||||
self.song = None
|
self.song = None
|
||||||
self.random = False
|
|
||||||
self.quit = None
|
self.quit = None
|
||||||
|
if os.path.exists(self.path) == False:
|
||||||
if os.path.exists(path):
|
os.mkdir(self.path)
|
||||||
try:
|
self.load(path,options)
|
||||||
self.load(path,options)
|
#gobject.timeout_add(600000,self.dump)
|
||||||
except:
|
|
||||||
if options.verbose == True:
|
|
||||||
print "Error loading user data"
|
|
||||||
|
|
||||||
|
|
||||||
# Dump user data to a file
|
# Dump user data to a file
|
||||||
def dump(self):
|
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 = pickle.Pickler(out,1)
|
||||||
p.dump(self)
|
p.dump(obj)
|
||||||
out.close()
|
out.close()
|
||||||
|
|
||||||
|
|
||||||
def clearSong(self):
|
|
||||||
self.song.close()
|
|
||||||
self.song = None
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
# Read user data from the file
|
# Read user data from the file
|
||||||
|
# Create values if files do not exist
|
||||||
def load(self,path,options):
|
def load(self,path,options):
|
||||||
if options.verbose == True:
|
self.library = self.load2("library")
|
||||||
print "User data found, loading..."
|
if self.library == None:
|
||||||
p = pickle.Unpickler(open(path))
|
self.library = Library()
|
||||||
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
|
|
||||||
|
|
||||||
|
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()
|
||||||
|
return data
|
||||||
|
return None
|
||||||
|
|
|
@ -68,4 +68,5 @@ class Song():
|
||||||
def curTime(self):
|
def curTime(self):
|
||||||
if self.playing == False:
|
if self.playing == False:
|
||||||
return (False,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):
|
def deleteLib(self,widgit,data,other=None):
|
||||||
self.data.library.reset()
|
self.data.library.reset()
|
||||||
self.libview.update()
|
self.libview.update()
|
||||||
self.clearPlist()
|
self.clearPlist(None,None)
|
||||||
|
|
||||||
|
|
||||||
def clearPlist(self,widgit,data,other=None):
|
def clearPlist(self,widgit,data,other=None):
|
||||||
|
|
Loading…
Reference in New Issue