Last.fm stuff, insert rows in library view
git-svn-id: file:///home/anna/Desktop/ocarina-legacy/mithos/ocarina@45 1daee41c-8060-4895-b1f0-2197c00d777a
This commit is contained in:
parent
57393a9150
commit
5b752c95e8
|
@ -1,15 +1,26 @@
|
||||||
|
|
||||||
open:
|
open:
|
||||||
geany src/GuiObjects/*.py &
|
geany &
|
||||||
|
geany src/GuiObjects/*.py
|
||||||
geany src/*.py
|
geany src/*.py
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf src/*.pyo
|
rm -rf src/*.pyo
|
||||||
rm -rf src/*~
|
rm -rf src/*~
|
||||||
|
rm -rf src/*.c
|
||||||
|
rm -rf src/*.o
|
||||||
|
rm -rf src/*.so
|
||||||
rm -rf src/GuiObjects/*.pyo
|
rm -rf src/GuiObjects/*.pyo
|
||||||
rm -rf src/GuiObjects/*~
|
rm -rf src/GuiObjects/*~
|
||||||
|
rm -rf src/GuiObjects/*.c
|
||||||
|
rm -rf src/GuiObjects/*.o
|
||||||
|
rm -rf src/GuiObjects/*.so
|
||||||
rm *~
|
rm *~
|
||||||
|
|
||||||
|
compile:
|
||||||
|
cd src && ./cythonize
|
||||||
|
cd src/GuiObjects && ./cythonize
|
||||||
|
|
||||||
install:
|
install:
|
||||||
# mkdir ~/bin/ocarina-bin
|
# mkdir ~/bin/ocarina-bin
|
||||||
rsync -avz src/ ~/bin/ocarina-bin/src
|
rsync -avz src/ ~/bin/ocarina-bin/src
|
||||||
|
|
|
@ -16,9 +16,9 @@ class ControlPanel(gtk.HBox):
|
||||||
self.next = plist.next
|
self.next = plist.next
|
||||||
self.pack_start(CheckButton("Random",self.toggleRand,self.data.random),False,False,0)
|
self.pack_start(CheckButton("Random",self.toggleRand,self.data.random),False,False,0)
|
||||||
self.makeProgressBar()
|
self.makeProgressBar()
|
||||||
(self.nextImg,self.nextBtn) = self.makeButton("next","next.png",None,self.next)
|
|
||||||
(self.stopImg,self.stopBtn) = self.makeButton("stop","stop.png",None,self.stop)
|
|
||||||
(self.playImg,self.plauseBtn) = self.makeButton("plause","play.png",None,self.plause)
|
(self.playImg,self.plauseBtn) = self.makeButton("plause","play.png",None,self.plause)
|
||||||
|
(self.stopImg,self.stopBtn) = self.makeButton("stop","stop.png",None,self.stop)
|
||||||
|
(self.nextImg,self.nextBtn) = self.makeButton("next","next.png",None,self.next)
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@ class ControlPanel(gtk.HBox):
|
||||||
if img:
|
if img:
|
||||||
image = Image(os.path.join("images",img))
|
image = Image(os.path.join("images",img))
|
||||||
button = Button(name,image,text,func)
|
button = Button(name,image,text,func)
|
||||||
self.pack_end(button,False,False,0)
|
#self.pack_end(button,False,False,0)
|
||||||
|
self.pack_start(button,False,False,0)
|
||||||
return (image,button)
|
return (image,button)
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,14 +47,13 @@ class ControlPanel(gtk.HBox):
|
||||||
event.show()
|
event.show()
|
||||||
vbox.show()
|
vbox.show()
|
||||||
pbar.show()
|
pbar.show()
|
||||||
gobject.timeout_add(1000,self.updatePBar,pbar)
|
gobject.timeout_add(500,self.updatePBar,pbar)
|
||||||
|
|
||||||
|
|
||||||
def pbarclick(self,widgit,data,pbar):
|
def pbarclick(self,widgit,data,pbar):
|
||||||
if data.button == 1:
|
if data.button == 1:
|
||||||
prcnt = float(data.x) / float(pbar.get_allocation()[2])
|
prcnt = float(data.x) / float(pbar.get_allocation()[2])
|
||||||
self.data.song.seek(int(prcnt * self.data.song.info.duration * 1000000000))
|
self.data.song.seek(int(prcnt * self.data.song.info.duration * 1000000000))
|
||||||
#print float(data.x)/float(pbar.get_allocation()[0])
|
|
||||||
|
|
||||||
|
|
||||||
# Play/Pause function
|
# Play/Pause function
|
||||||
|
@ -78,15 +78,16 @@ class ControlPanel(gtk.HBox):
|
||||||
|
|
||||||
# Update time/progress of the progress bar
|
# Update time/progress of the progress bar
|
||||||
def updatePBar(self,pbar):
|
def updatePBar(self,pbar):
|
||||||
if self.data.song and (self.data.song.playing == False):
|
time = 0
|
||||||
|
if not self.data.song:
|
||||||
return True
|
return True
|
||||||
try:
|
try:
|
||||||
(success,time) = self.data.song.curTime()
|
time = self.data.song.curTime()
|
||||||
except:
|
except:
|
||||||
success = False
|
time = 0
|
||||||
if success == True:
|
if self.data.song.info.duration > 0:
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ class InfoView(gtk.VBox):
|
||||||
album = ""
|
album = ""
|
||||||
artist = ""
|
artist = ""
|
||||||
if self.data.song:
|
if self.data.song:
|
||||||
title = self.data.song.info.title.title()
|
title = self.data.song.info.title
|
||||||
album = "from "+self.data.song.info.album.title()
|
album = "from "+self.data.song.info.album
|
||||||
artist = "by "+self.data.song.info.artist.title()
|
artist = "by "+self.data.song.info.artist
|
||||||
self.title.set_text(title)
|
self.title.set_text(title)
|
||||||
self.album.set_text(album)
|
self.album.set_text(album)
|
||||||
self.artist.set_text(artist)
|
self.artist.set_text(artist)
|
||||||
|
|
|
@ -8,10 +8,12 @@ from menuItem import MenuItem
|
||||||
class LibView(gtk.VBox):
|
class LibView(gtk.VBox):
|
||||||
def __init__(self,data):
|
def __init__(self,data):
|
||||||
gtk.VBox.__init__(self,False,0)
|
gtk.VBox.__init__(self,False,0)
|
||||||
|
data.library.libview = self
|
||||||
self.win = gtk.ScrolledWindow()
|
self.win = gtk.ScrolledWindow()
|
||||||
self.win.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
|
self.win.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
|
||||||
self.data = data
|
self.data = data
|
||||||
self.treeview = None
|
self.treeview = None
|
||||||
|
self.tree = gtk.TreeStore(str,int)
|
||||||
self.col = None
|
self.col = None
|
||||||
self.plist = None
|
self.plist = None
|
||||||
self.pbar = gtk.ProgressBar()
|
self.pbar = gtk.ProgressBar()
|
||||||
|
@ -25,38 +27,36 @@ class LibView(gtk.VBox):
|
||||||
|
|
||||||
# Use to update the library pane
|
# Use to update the library pane
|
||||||
def update(self):
|
def update(self):
|
||||||
rval = self.data.library.scanning
|
#if self.treeview:
|
||||||
if self.treeview:
|
#self.win.remove(self.treeview)
|
||||||
self.win.remove(self.treeview)
|
#self.treeview.remove_column(self.col)
|
||||||
self.treeview.remove_column(self.col)
|
#self.tree = gtk.TreeStore(str,int)
|
||||||
self.pbar.pulse()
|
#self.pbar.pulse()
|
||||||
self.pbar.set_text("Found "+str(self.data.library.count)+" files.")
|
#self.pbar.set_text("Found "+str(self.data.library.count)+" files.")
|
||||||
tree = gtk.TreeStore(str,int)
|
#for artist in self.data.library.artAlb.keys():
|
||||||
for artist in self.data.library.artAlb.keys():
|
# ariter = self.tree.append(None,[artist,-1])
|
||||||
ariter = tree.append(None,[artist.title(),-1])
|
# for album in self.data.library.artAlb[artist]:
|
||||||
for album in self.data.library.artAlb[artist]:
|
# aliter = self.tree.append(ariter,[album,-1])
|
||||||
aliter = tree.append(ariter,[album.title(),-1])
|
# for track in self.data.library.albTrk[(artist,album)]:
|
||||||
for track in self.data.library.albTrk[(artist,album)]:
|
# self.tree.append(aliter,[self.data.library.files[track].title,self.data.library.files[track].id])
|
||||||
tree.append(aliter,[self.data.library.files[track].title.title(),self.data.library.files[track].id])
|
self.tree.set_sort_column_id(0,gtk.SORT_ASCENDING)
|
||||||
tree.set_sort_column_id(0,gtk.SORT_ASCENDING)
|
self.treeview = gtk.TreeView(self.tree)
|
||||||
self.treeview = gtk.TreeView(tree)
|
#self.treeview.set_enable_search(True)
|
||||||
self.treeview.set_enable_search(True)
|
|
||||||
self.treeview.connect("button_release_event",self.clicked)
|
self.treeview.connect("button_release_event",self.clicked)
|
||||||
self.col = gtk.TreeViewColumn('Library ('+str(self.data.library.count)+')')
|
self.col = gtk.TreeViewColumn('Library ('+str(self.data.library.count)+')')
|
||||||
self.treeview.append_column(self.col)
|
self.treeview.append_column(self.col)
|
||||||
cell = gtk.CellRendererText()
|
cell = gtk.CellRendererText()
|
||||||
self.col.pack_start(cell,True)
|
self.col.pack_start(cell,True)
|
||||||
self.col.add_attribute(cell,'text',0)
|
self.col.add_attribute(cell,'text',0)
|
||||||
self.col.set_sort_column_id(0)
|
#self.col.set_sort_column_id(0)
|
||||||
self.treeview.set_rules_hint(True)
|
self.treeview.set_rules_hint(True)
|
||||||
self.treeview.show()
|
self.treeview.show()
|
||||||
self.selection = self.treeview.get_selection()
|
self.selection = self.treeview.get_selection()
|
||||||
self.selection.set_mode(gtk.SELECTION_MULTIPLE)
|
self.selection.set_mode(gtk.SELECTION_MULTIPLE)
|
||||||
self.win.add(self.treeview)
|
self.win.add(self.treeview)
|
||||||
self.updateLabel()
|
for file in self.data.library.files:
|
||||||
if rval==False:
|
self.insertSong(file)
|
||||||
self.pbar.hide()
|
#self.updateLabel()
|
||||||
return rval
|
|
||||||
|
|
||||||
|
|
||||||
def makeLabel(self):
|
def makeLabel(self):
|
||||||
|
@ -72,7 +72,22 @@ class LibView(gtk.VBox):
|
||||||
# Begin updating the library
|
# Begin updating the library
|
||||||
def updates(self):
|
def updates(self):
|
||||||
self.pbar.show()
|
self.pbar.show()
|
||||||
gobject.timeout_add(1000,self.update)
|
self.updating = True
|
||||||
|
gobject.timeout_add(500,self.updateLibview)
|
||||||
|
|
||||||
|
|
||||||
|
def updateLibview(self):
|
||||||
|
self.pbar.set_text("Found "+str(self.data.library.count)+" files.")
|
||||||
|
self.pbar.pulse()
|
||||||
|
#self.updateLabel()
|
||||||
|
self.col.set_title('Library ('+str(self.data.library.count)+')')
|
||||||
|
return self.updating
|
||||||
|
|
||||||
|
|
||||||
|
def stopUpdates(self):
|
||||||
|
self.updating = False
|
||||||
|
self.pbar.hide()
|
||||||
|
self.data.dump()
|
||||||
|
|
||||||
|
|
||||||
# Right click menu
|
# Right click menu
|
||||||
|
@ -88,6 +103,37 @@ class LibView(gtk.VBox):
|
||||||
self.rcmenu.popup(None,None,None,data.button,data.time)
|
self.rcmenu.popup(None,None,None,data.button,data.time)
|
||||||
|
|
||||||
|
|
||||||
|
def insertSong(self,song):
|
||||||
|
foundArt = False
|
||||||
|
foundAlb = False
|
||||||
|
|
||||||
|
artist = song.artist
|
||||||
|
album = song.album
|
||||||
|
track = song.title
|
||||||
|
|
||||||
|
ariter = self.tree.get_iter_root()
|
||||||
|
while ariter:
|
||||||
|
if self.tree[ariter][0]==artist:
|
||||||
|
foundArt = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
ariter = self.tree.iter_next(ariter)
|
||||||
|
|
||||||
|
aliter = self.tree.iter_children(ariter)
|
||||||
|
while aliter:
|
||||||
|
if self.tree[aliter][0]==album:
|
||||||
|
foundAlb = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
aliter = self.tree.iter_next(aliter)
|
||||||
|
|
||||||
|
if foundArt == False:
|
||||||
|
ariter = self.tree.insert(None,0,[artist,-1])
|
||||||
|
if foundAlb == False:
|
||||||
|
aliter = self.tree.insert(ariter,0,[album,-1])
|
||||||
|
self.tree.insert(aliter,0,[song.title.title(),song.id])
|
||||||
|
|
||||||
|
|
||||||
def populatePlaylist(self,widgit,func,data):
|
def populatePlaylist(self,widgit,func,data):
|
||||||
(model,pathlist) = self.selection.get_selected_rows()
|
(model,pathlist) = self.selection.get_selected_rows()
|
||||||
list = []
|
list = []
|
||||||
|
|
|
@ -112,7 +112,7 @@ class PlistView(gtk.Notebook):
|
||||||
i = len(dst)
|
i = len(dst)
|
||||||
for index in src:
|
for index in src:
|
||||||
track = self.data.library.files[index]
|
track = self.data.library.files[index]
|
||||||
dst.insert(i,[track.id,track.title.title(),track.length,track.artist.title(),track.album.title(),track.count])
|
dst.insert(i,[track.id,track.title,track.length,track.artist,track.album,track.count])
|
||||||
time+=track.duration
|
time+=track.duration
|
||||||
i+=1
|
i+=1
|
||||||
return time
|
return time
|
||||||
|
@ -220,6 +220,7 @@ class PlistView(gtk.Notebook):
|
||||||
self.data.curSong = self.pfilter[iter][0]
|
self.data.curSong = self.pfilter[iter][0]
|
||||||
self.loadSong(False)
|
self.loadSong(False)
|
||||||
self.controls.plause(None,None)
|
self.controls.plause(None,None)
|
||||||
|
self.data.scrobbler.nowPlaying(self.data.library.files[self.data.curSong])
|
||||||
|
|
||||||
|
|
||||||
# Go to the next song in the list
|
# Go to the next song in the list
|
||||||
|
@ -245,7 +246,7 @@ class PlistView(gtk.Notebook):
|
||||||
self.data.playingQ = True
|
self.data.playingQ = True
|
||||||
self.setTabText("queue")
|
self.setTabText("queue")
|
||||||
elif self.data.random == True:
|
elif self.data.random == True:
|
||||||
self.data.curSong = self.pfilter[random.randint(0,len(self.pfilter))][0]
|
self.data.curSong = self.pfilter[random.randint(0,len(self.pfilter)-1)][0]
|
||||||
else:
|
else:
|
||||||
next = self.pfilter[0][0]
|
next = self.pfilter[0][0]
|
||||||
for i in range(len(self.pfilter)-1):
|
for i in range(len(self.pfilter)-1):
|
||||||
|
@ -261,6 +262,7 @@ class PlistView(gtk.Notebook):
|
||||||
|
|
||||||
if pause == False:
|
if pause == False:
|
||||||
self.controls.plause(None,None)
|
self.controls.plause(None,None)
|
||||||
|
self.data.scrobbler.nowPlaying(self.data.library.files[self.data.curSong])
|
||||||
self.controls.changeImg()
|
self.controls.changeImg()
|
||||||
self.status = CONTINUE
|
self.status = CONTINUE
|
||||||
|
|
||||||
|
@ -270,6 +272,7 @@ class PlistView(gtk.Notebook):
|
||||||
if len(self.data.curList) == 0:
|
if len(self.data.curList) == 0:
|
||||||
return
|
return
|
||||||
if self.data.song:
|
if self.data.song:
|
||||||
|
self.data.scrobbler.submit(self.data.song.timestamp)
|
||||||
self.data.song.close()
|
self.data.song.close()
|
||||||
self.data.song = Song(self.data.library.files[self.data.curSong],self.next)
|
self.data.song = Song(self.data.library.files[self.data.curSong],self.next)
|
||||||
self.info.changeLabels()
|
self.info.changeLabels()
|
||||||
|
@ -328,13 +331,27 @@ class PlistView(gtk.Notebook):
|
||||||
|
|
||||||
|
|
||||||
def hideRows(self,list,iter):
|
def hideRows(self,list,iter):
|
||||||
if self.search != "":
|
if self.search == "":
|
||||||
file = self.data.library.files[list[iter][0]]
|
return True
|
||||||
if re.search(self.search,file.title):
|
elif len(self.search) == 1:
|
||||||
|
try:
|
||||||
|
self.data.library.files[list[iter][0]].single[self.search]
|
||||||
return True
|
return True
|
||||||
elif re.search(self.search,file.artist):
|
except:
|
||||||
|
return False
|
||||||
|
elif len(self.search) == 2:
|
||||||
|
try:
|
||||||
|
self.data.library.files[list[iter][0]].double[self.search]
|
||||||
return True
|
return True
|
||||||
elif re.search(self.search,file.album):
|
except:
|
||||||
return True
|
return False
|
||||||
return False
|
#if self.search in self.data.library.files[list[iter][0]].letters == True:
|
||||||
return True
|
# return True
|
||||||
|
file = self.data.library.files[list[iter][0]]
|
||||||
|
if re.search(self.search,file.titlel):
|
||||||
|
return True
|
||||||
|
elif re.search(self.search,file.artistl):
|
||||||
|
return True
|
||||||
|
elif re.search(self.search,file.albuml):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
import urllib
|
||||||
import urllib2
|
import urllib2
|
||||||
#import pygtk
|
#import pygtk
|
||||||
#pygtk.require('2.0')
|
#pygtk.require('2.0')
|
||||||
import gtk
|
import gtk
|
||||||
import webbrowser
|
import webbrowser
|
||||||
#import thread
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import datetime
|
||||||
|
import time
|
||||||
|
|
||||||
from button import Button
|
from button import Button
|
||||||
|
|
||||||
|
@ -20,6 +22,12 @@ class Scrobbler(gtk.VBox):
|
||||||
self.key = "2c76f85a6704efd74b5a358821284ef9"
|
self.key = "2c76f85a6704efd74b5a358821284ef9"
|
||||||
self.secret = "3a6012bfb627b60a884cf33fc044885c"
|
self.secret = "3a6012bfb627b60a884cf33fc044885c"
|
||||||
self.token = ""
|
self.token = ""
|
||||||
|
# Session ID
|
||||||
|
self.session = ""
|
||||||
|
# Now playing URL
|
||||||
|
self.npurl = ""
|
||||||
|
# Submission URL
|
||||||
|
self.suburl = ""
|
||||||
|
|
||||||
# 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
|
||||||
self.makegui()
|
self.makegui()
|
||||||
|
@ -30,66 +38,165 @@ class Scrobbler(gtk.VBox):
|
||||||
|
|
||||||
def makegui(self):
|
def makegui(self):
|
||||||
if self.data.lfm == "":
|
if self.data.lfm == "":
|
||||||
self.nosession = Button("lfm",None,"Click here to configure Ocarina for submitting songs to last.fm",self.setup)
|
uname = gtk.Label("Username:")
|
||||||
self.nosession.set_size_request(100,100)
|
username = gtk.Entry()
|
||||||
self.pack_start(self.nosession,False,False,0)
|
passwd = gtk.Label("Password:")
|
||||||
|
password = gtk.Entry()
|
||||||
|
password.set_visibility(False)
|
||||||
|
|
||||||
|
username.connect("activate",self.fetchSession,username,uname,password,passwd)
|
||||||
|
password.connect("activate",self.fetchSession,username,uname,password,passwd)
|
||||||
|
|
||||||
|
uname.show()
|
||||||
|
username.show()
|
||||||
|
passwd.show()
|
||||||
|
password.show()
|
||||||
|
|
||||||
|
self.pack_start(uname,False,False,0)
|
||||||
|
self.pack_start(username,False,False,0)
|
||||||
|
self.pack_start(passwd,False,False,0)
|
||||||
|
self.pack_start(password,False,False,0)
|
||||||
|
else:
|
||||||
|
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]
|
||||||
|
|
||||||
|
|
||||||
# One time setup (in theory)
|
def fetchSession(self,widgit,username,uname,password,passwd):
|
||||||
def setup(self,widgit,data):
|
self.data.lfmuser = username.get_text().lower()
|
||||||
self.nosession.hide()
|
self.data.lfmpass = self.md5(password.get_text())
|
||||||
self.remove(self.nosession)
|
if self.data.lfmuser=="" or self.data.lfmpass=="":
|
||||||
self.contBtn = Button("lfm",None,"Click to continue",self.fetchSession)
|
|
||||||
self.pack_start(self.contBtn,False,False,0)
|
|
||||||
self.fetchToken()
|
|
||||||
self.authorize()
|
|
||||||
|
|
||||||
|
|
||||||
# Fetch the authentication token
|
|
||||||
def fetchToken(self):
|
|
||||||
(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
|
return
|
||||||
self.token += hashlib.md5(status.firstChild.nextSibling.firstChild.data).hexdigest()
|
else:
|
||||||
|
self.token = self.md5(self.data.lfmuser+self.data.lfmpass)
|
||||||
|
(url,list) = self.addMethod(self.url,"auth.getMobileSession")
|
||||||
|
(url,list) = self.addParam(url,list,"username",self.data.lfmuser)
|
||||||
|
(url,list) = self.addParam(url,list,"authToken",self.token)
|
||||||
|
(url,list) = self.addParam(url,list,"api_key",self.key)
|
||||||
|
(url,list) = self.addParam(url,list,"api_sig",self.getSig(list))
|
||||||
|
status = self.parseRequest(url)
|
||||||
|
attr = status.getAttributeNode("status")
|
||||||
|
if attr.value != "ok":
|
||||||
|
return
|
||||||
|
self.data.lfm = status.firstChild.nextSibling.firstChild.nextSibling.nextSibling.nextSibling.firstChild.data
|
||||||
|
username.hide()
|
||||||
|
uname.hide()
|
||||||
|
password.hide()
|
||||||
|
passwd.hide()
|
||||||
|
self.makegui()
|
||||||
|
|
||||||
|
|
||||||
# Open to authorization page
|
def handshake(self):
|
||||||
def authorize(self):
|
print "shaking hands"
|
||||||
url = "http://www.last.fm/api/auth/?api_key="+self.key
|
url = "http://post.audioscrobbler.com/?hs=true"
|
||||||
#(url,list) = self.addParam(url,[],"api_key",self.key)
|
list = [("hs","true")]
|
||||||
(url,list) = self.addParam(url,[],"token",self.token)
|
(url,list) = self.addParam(url,list,"p","1.2.1")
|
||||||
print url
|
(url,list) = self.addParam(url,list,"c","tst")
|
||||||
#url+="&"+self.token
|
(url,list) = self.addParam(url,list,"v","1.0")
|
||||||
webbrowser.open(url)
|
(url,list) = self.addParam(url,list,"u",self.data.lfmuser)
|
||||||
|
tstp = self.timestamp()
|
||||||
|
(url,list) = self.addParam(url,list,"t",tstp)
|
||||||
def fetchSession(self,widgit,data):
|
(url,list) = self.addParam(url,list,"a",self.authToken(tstp))
|
||||||
(url,list) = self.addMethod("auth.getSession")
|
|
||||||
(url,list) = self.addParam(url,list,"api_key",self.key)
|
(url,list) = self.addParam(url,list,"api_key",self.key)
|
||||||
(url,list) = self.addParam(url,list,"token",self.token)
|
status = self.placeRequest(url).readlines()
|
||||||
sig = self.getSig(list)
|
if status[0].strip() != "OK":
|
||||||
(url,list) = self.addParam(url,None,"api_sig",sig)
|
return
|
||||||
print url
|
self.session = status[1].strip()
|
||||||
#status = self.placeRequest(url)
|
self.npurl = status[2].strip()#+"/?"
|
||||||
return
|
self.suburl = status[3].strip()#+"/?"
|
||||||
#attr = status.getAttributeNode("status")
|
#for line in status:
|
||||||
#if attr.value != "ok":
|
# print line.strip()
|
||||||
# return
|
|
||||||
#node = status.firstChild.firstChild
|
def nowPlaying(self,info):
|
||||||
#user = node.data
|
vals = {"s":self.session,
|
||||||
#key = node.nextSibling.data
|
"a":info.artist.title(),
|
||||||
#subscriber = node.nextSibling.nextSibling.data
|
"t":info.title.title(),
|
||||||
#print user,key,subscriber
|
"b":info.album.title(),
|
||||||
|
"l":str(info.duration),
|
||||||
|
"n":info.tnum,
|
||||||
|
"m":""}
|
||||||
|
|
||||||
|
data = urllib.urlencode(vals)
|
||||||
|
#status = self.placeRequest(url).readlines()
|
||||||
|
req = urllib2.Request(self.npurl,data)
|
||||||
|
req.add_header("User-Agent","Ocarina")
|
||||||
|
status = urllib2.urlopen(req)
|
||||||
|
self.fetchSimilar(info.artist)
|
||||||
|
#if status[0].strip() == "OK":
|
||||||
|
# print "Submission successful"
|
||||||
|
|
||||||
|
|
||||||
def addMethod(self,method):
|
def submit(self,timestp):
|
||||||
|
info = self.data.song.info
|
||||||
|
if info.duration < 30:
|
||||||
|
return
|
||||||
|
exit = True
|
||||||
|
if (self.data.song.position > 240):
|
||||||
|
exit = False
|
||||||
|
if self.data.song.position > (self.data.song.info.duration/2):
|
||||||
|
exit = False
|
||||||
|
|
||||||
|
if exit == True:
|
||||||
|
return
|
||||||
|
|
||||||
|
vals = {"s":self.session,
|
||||||
|
"a[0]":info.artist.title(),
|
||||||
|
"t[0]":info.title.title(),
|
||||||
|
"i[0]":timestp,
|
||||||
|
"o[0]":"P",
|
||||||
|
"r[0]":"",
|
||||||
|
"l[0]":str(info.duration),
|
||||||
|
"b[0]":info.album.title(),
|
||||||
|
"n[0]":info.tnum,
|
||||||
|
"m[0]":""}
|
||||||
|
data = urllib.urlencode(vals)
|
||||||
|
req = urllib2.Request(self.suburl,data)
|
||||||
|
req.add_header("User-Agent","Ocarina")
|
||||||
|
status = urllib2.urlopen(req)
|
||||||
|
for line in status:
|
||||||
|
print line
|
||||||
|
#print status
|
||||||
|
|
||||||
|
|
||||||
|
def fetchSimilar(self,artist):
|
||||||
|
(url,list) = self.addMethod(self.url,"artist.getsimilar")
|
||||||
|
(url,list) = self.addParam(url,list,"artist",artist)
|
||||||
|
(url,list) = self.addParam(url,list,"limit","10")
|
||||||
|
(url,list) = self.addParam(url,list,"api_key",self.key)
|
||||||
|
status = self.parseRequest(url)
|
||||||
|
list = status.firstChild.nextSibling.childNodes
|
||||||
|
for i in range(list.length):
|
||||||
|
node = list.item(i)
|
||||||
|
if node.hasChildNodes()==True:
|
||||||
|
nameNode = node.firstChild.nextSibling.firstChild
|
||||||
|
self.similar[i/2].set_text(nameNode.data)
|
||||||
|
#for node in status.firstChild.childNodes:
|
||||||
|
# print node
|
||||||
|
|
||||||
|
def authToken(self,t):
|
||||||
|
return self.md5(self.data.lfmpass+t)
|
||||||
|
|
||||||
|
|
||||||
|
def md5(self,string):
|
||||||
|
return hashlib.md5(string).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def timestamp(self):
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
return str(int(time.mktime(now.timetuple())))
|
||||||
|
|
||||||
|
|
||||||
|
def addMethod(self,url,method):
|
||||||
return (self.url+"?method="+method,[("method",method)])
|
return (self.url+"?method="+method,[("method",method)])
|
||||||
|
|
||||||
|
|
||||||
def addParam(self,url,list,param,val):
|
def addParam(self,url,list,param,val):
|
||||||
|
val = val.replace(" ","%20")
|
||||||
url+="&"+param+"="+val
|
url+="&"+param+"="+val
|
||||||
if list:
|
if list:
|
||||||
list += [(param,val)]
|
list += [(param,val)]
|
||||||
|
@ -102,19 +209,19 @@ class Scrobbler(gtk.VBox):
|
||||||
string = ""
|
string = ""
|
||||||
for entry in list:
|
for entry in list:
|
||||||
string+=entry[0]+entry[1]
|
string+=entry[0]+entry[1]
|
||||||
string = string + self.secret
|
#string = string + self.secret
|
||||||
m = hashlib.md5(string)
|
return self.md5(string+self.secret)
|
||||||
return m.hexdigest()
|
#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):
|
def placeRequest(self,url):
|
||||||
#print url
|
#print url
|
||||||
req = urllib2.Request(url)
|
req = urllib2.Request(url)
|
||||||
req.add_header('User-Agent','Ocarina')
|
req.add_header('User-Agent','Ocarina')
|
||||||
return minidom.parse(urllib2.urlopen(req)).documentElement
|
#return minidom.parse(urllib2.urlopen(req)).documentElement
|
||||||
|
return urllib2.urlopen(req)
|
||||||
|
|
||||||
|
|
||||||
|
def parseRequest(self,url):
|
||||||
|
return minidom.parse(self.placeRequest(url)).documentElement
|
||||||
|
|
|
@ -9,24 +9,26 @@ import thread
|
||||||
class Library:
|
class Library:
|
||||||
#def __init__(self,prnt):
|
#def __init__(self,prnt):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.goodTypes = ["ogg","mp3","wav","flac","mid"]#,"wma"]
|
self.goodTypes = ["ogg","mp3","flac"]#,"wma"]
|
||||||
self.reset()
|
self.reset()
|
||||||
self.scanning = False
|
#self.scanning = False
|
||||||
|
self.libview = None
|
||||||
#self.notAdded = open("/home/bjschuma/Desktop/notAdded.txt",'w')
|
#self.notAdded = open("/home/bjschuma/Desktop/notAdded.txt",'w')
|
||||||
|
|
||||||
|
|
||||||
# Begin a scan on dir
|
# Begin a scan on dir
|
||||||
def scan(self,thread,dir):
|
def scan(self,thread,dir):
|
||||||
self.scanning = True
|
#self.scanning = True
|
||||||
self.reset()
|
self.reset()
|
||||||
|
self.libview.updates()
|
||||||
self.path = os.path.expanduser(dir)
|
self.path = os.path.expanduser(dir)
|
||||||
if os.path.exists(self.path) == False:
|
if os.path.exists(self.path) == False:
|
||||||
#print "Directory not found: %s" % dir
|
#print "Directory not found: %s" % dir
|
||||||
return
|
return
|
||||||
#print "Scanning: "+self.path
|
#print "Scanning: "+self.path
|
||||||
self.traverse("")
|
self.traverse("")
|
||||||
self.scanning = False
|
self.libview.stopUpdates()
|
||||||
|
#self.scanning = False
|
||||||
#print "Found %s files!" % str(self.count)
|
#print "Found %s files!" % str(self.count)
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +60,7 @@ class Library:
|
||||||
song.filename = os.path.join(self.path,joined)
|
song.filename = os.path.join(self.path,joined)
|
||||||
self.files+=[song]
|
self.files+=[song]
|
||||||
thread.start_new_thread(self.add,(self.hash(joined),self.count))
|
thread.start_new_thread(self.add,(self.hash(joined),self.count))
|
||||||
|
#self.add(self.hash(joined),self.count)
|
||||||
self.count += 1
|
self.count += 1
|
||||||
#self.add(self.hash(joined),joined)
|
#self.add(self.hash(joined),joined)
|
||||||
#else:
|
#else:
|
||||||
|
@ -99,18 +102,22 @@ class Library:
|
||||||
info.album = t.album
|
info.album = t.album
|
||||||
if t.artist != "":
|
if t.artist != "":
|
||||||
info.artist = t.artist
|
info.artist = t.artist
|
||||||
|
#info.tnum = str(t.track)
|
||||||
a = f.audioProperties()
|
a = f.audioProperties()
|
||||||
info.setTime(a.length)
|
info.setTime(a.length)
|
||||||
except:
|
except:
|
||||||
print info.filename
|
print info.filename
|
||||||
|
#print "here"
|
||||||
|
|
||||||
info.title = info.title.lower()
|
#info.title = info.title.lower()
|
||||||
info.album = info.album.lower()
|
#info.album = info.album.lower()
|
||||||
info.artist = info.artist.lower()
|
#info.artist = info.artist.lower()
|
||||||
artist = info.artist
|
artist = info.artist.lower()
|
||||||
album = info.album
|
info.artistl = artist
|
||||||
|
album = info.album.lower()
|
||||||
|
info.albuml = album
|
||||||
|
title = info.title.lower()
|
||||||
|
info.titlel = title
|
||||||
|
|
||||||
if (artist in self.artAlb.keys()) == False:
|
if (artist in self.artAlb.keys()) == False:
|
||||||
self.artAlb[artist] = [album]
|
self.artAlb[artist] = [album]
|
||||||
|
@ -121,6 +128,24 @@ class Library:
|
||||||
self.albTrk[(artist,album)] = [index]
|
self.albTrk[(artist,album)] = [index]
|
||||||
else:
|
else:
|
||||||
self.albTrk[(artist,album)] += [index]
|
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 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.insertSong(info)
|
||||||
|
|
||||||
|
|
||||||
# Return true if file is in the library
|
# Return true if file is in the library
|
||||||
|
|
|
@ -11,6 +11,7 @@ class SavedData:
|
||||||
self.path = path
|
self.path = path
|
||||||
self.song = None
|
self.song = None
|
||||||
self.quit = None
|
self.quit = None
|
||||||
|
self.scrobbler = None
|
||||||
if os.path.exists(self.path) == False:
|
if os.path.exists(self.path) == False:
|
||||||
os.mkdir(self.path)
|
os.mkdir(self.path)
|
||||||
self.load(path,options)
|
self.load(path,options)
|
||||||
|
@ -19,10 +20,11 @@ class SavedData:
|
||||||
|
|
||||||
# Dump user data to a file
|
# Dump user data to a file
|
||||||
def dump(self):
|
def dump(self):
|
||||||
|
self.library.libview = None
|
||||||
self.save(self.library,"library")
|
self.save(self.library,"library")
|
||||||
self.save([self.curList,self.curQ,self.curSong,self.playingQ],"playlist")
|
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.size,self.divider,self.colSizes,self.sortedCol,self.random],"preferences")
|
||||||
self.save(self.lfm,"last.fm")
|
self.save([self.lfm,self.lfmuser,self.lfmpass],"last.fm")
|
||||||
|
|
||||||
|
|
||||||
def save(self,obj,file):
|
def save(self,obj,file):
|
||||||
|
@ -65,9 +67,15 @@ class SavedData:
|
||||||
self.sortedCol = prefs[3]
|
self.sortedCol = prefs[3]
|
||||||
self.random = prefs[4]
|
self.random = prefs[4]
|
||||||
|
|
||||||
self.lfm = self.load2("last.fm")
|
lfm = self.load2("last.fm")
|
||||||
if self.lfm == None:
|
if lfm == None:
|
||||||
self.lfm = ""
|
self.lfm = ""
|
||||||
|
self.lfmuser = ""
|
||||||
|
self.lfmpass = ""
|
||||||
|
else:
|
||||||
|
self.lfm = lfm[0]
|
||||||
|
self.lfmuser = lfm[1]
|
||||||
|
self.lfmpass = lfm[2]
|
||||||
|
|
||||||
|
|
||||||
def load2(self,file):
|
def load2(self,file):
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import datetime
|
||||||
|
import time
|
||||||
import gst
|
import gst
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +14,7 @@ class Song():
|
||||||
self.bin.set_property("uri","file://"+self.info.filename)
|
self.bin.set_property("uri","file://"+self.info.filename)
|
||||||
self.bin.set_state(gst.STATE_PAUSED)
|
self.bin.set_state(gst.STATE_PAUSED)
|
||||||
self.player.add(self.bin)
|
self.player.add(self.bin)
|
||||||
|
self.timestamp = str(int(time.mktime(datetime.datetime.now().timetuple())))
|
||||||
|
|
||||||
# initialize bus
|
# initialize bus
|
||||||
bus = self.player.get_bus()
|
bus = self.player.get_bus()
|
||||||
|
@ -52,9 +55,9 @@ class Song():
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.player.set_state(gst.STATE_PAUSED)
|
self.player.set_state(gst.STATE_PAUSED)
|
||||||
self.playing = False
|
self.playing = False
|
||||||
self.current = 0
|
self.position = 0
|
||||||
#self.player.seek_simple(self.time_format,gst.SEEK_FLAG_FLUSH,self.current)
|
#self.player.seek_simple(self.time_format,gst.SEEK_FLAG_FLUSH,self.current)
|
||||||
self.seek(current)
|
self.seek(self.position)
|
||||||
|
|
||||||
|
|
||||||
def seek(self,time):
|
def seek(self,time):
|
||||||
|
@ -68,7 +71,8 @@ class Song():
|
||||||
|
|
||||||
# Print out current running time
|
# Print out current running time
|
||||||
def curTime(self):
|
def curTime(self):
|
||||||
if self.playing == False:
|
#if self.playing == False:
|
||||||
return (False,False)
|
# return (True,self.position)
|
||||||
self.position = self.player.query_position(self.time_format,None)[0]/1000000000
|
self.position = self.player.query_position(self.time_format,None)[0]/1000000000
|
||||||
return (True, self.position)
|
#return (True, self.position)
|
||||||
|
return self.position
|
||||||
|
|
|
@ -4,13 +4,19 @@ class SongInfo:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.id = 0
|
self.id = 0
|
||||||
self.filename = ""
|
self.filename = ""
|
||||||
|
self.tnum = ""
|
||||||
self.count = 0
|
self.count = 0
|
||||||
# Length is a string, duration is an int
|
# Length is a string, duration is an int
|
||||||
self.length = ""
|
self.length = ""
|
||||||
self.duration = 0
|
self.duration = 0
|
||||||
self.title = ""
|
self.title = ""
|
||||||
|
self.titlel = ""
|
||||||
self.album = ""
|
self.album = ""
|
||||||
|
self.albuml = ""
|
||||||
self.artist = ""
|
self.artist = ""
|
||||||
|
self.artistl = ""
|
||||||
|
self.single = dict()
|
||||||
|
self.double = dict()
|
||||||
|
|
||||||
|
|
||||||
def setTime(self,time):
|
def setTime(self,time):
|
||||||
|
|
|
@ -74,6 +74,7 @@ class Window(gtk.Window):
|
||||||
|
|
||||||
# Used to select a directory
|
# Used to select a directory
|
||||||
def selectDir(self,widgit,data,func):
|
def selectDir(self,widgit,data,func):
|
||||||
|
self.deleteLib(None,None)
|
||||||
dirsel = gtk.FileChooserDialog(None,action=gtk.FILE_CHOOSER_ACTION_OPEN,buttons =(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
dirsel = gtk.FileChooserDialog(None,action=gtk.FILE_CHOOSER_ACTION_OPEN,buttons =(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
|
||||||
dirsel.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
dirsel.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
||||||
response = None
|
response = None
|
||||||
|
@ -109,6 +110,7 @@ class Window(gtk.Window):
|
||||||
scrobLabel = gtk.Label("Last.fm")
|
scrobLabel = gtk.Label("Last.fm")
|
||||||
scrobLabel.set_angle(90)
|
scrobLabel.set_angle(90)
|
||||||
leftPane.append_page(scrobbler,scrobLabel)
|
leftPane.append_page(scrobbler,scrobLabel)
|
||||||
|
self.data.scrobbler = scrobbler
|
||||||
|
|
||||||
self.divider.add1(leftPane)
|
self.divider.add1(leftPane)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue