diff --git a/trunk/images/ocarina.png b/trunk/images/ocarina.png index 7835d24c..e8ec8879 100644 Binary files a/trunk/images/ocarina.png and b/trunk/images/ocarina.png differ diff --git a/trunk/src/GuiObjects/controlPanel.py b/trunk/src/GuiObjects/controlPanel.py index b08b8dc4..35196549 100644 --- a/trunk/src/GuiObjects/controlPanel.py +++ b/trunk/src/GuiObjects/controlPanel.py @@ -41,7 +41,7 @@ class ControlPanel(gtk.HBox): self.pack_start(vbox,True,True,0) vbox.show() pbar.show() - gobject.timeout_add(1000,self.updatePBar,pbar) + gobject.timeout_add(100,self.updatePBar,pbar) # Play/Pause function @@ -61,6 +61,7 @@ class ControlPanel(gtk.HBox): self.plauseBtn.set_image(self.playImg) if self.data.song.playing == True: self.plauseBtn.set_image(self.pauseImg) + self.plauseBtn.show() # Update time/progress of the progress bar diff --git a/trunk/src/GuiObjects/infoView.py b/trunk/src/GuiObjects/infoView.py index 4ffdfa77..a3debf19 100644 --- a/trunk/src/GuiObjects/infoView.py +++ b/trunk/src/GuiObjects/infoView.py @@ -21,7 +21,7 @@ class InfoView(gtk.VBox): title = "" album = "" artist = "" - if self.data.song.info: + if self.data.song: title = self.data.song.info.title album = "from "+self.data.song.info.album artist = "by "+self.data.song.info.artist diff --git a/trunk/src/GuiObjects/plistView.py b/trunk/src/GuiObjects/plistView.py index 1e622c6c..5990011c 100644 --- a/trunk/src/GuiObjects/plistView.py +++ b/trunk/src/GuiObjects/plistView.py @@ -5,6 +5,7 @@ pygtk.require('2.0') import gtk from menuItem import MenuItem +from song import Song CONTINUE = 0 PAFTER = 1 @@ -13,11 +14,18 @@ PAFTER = 1 class PlistView(gtk.Notebook): def __init__(self,data): gtk.Notebook.__init__(self) + self.connect("switch-page",self.changedTab) self.set_scrollable(True) self.data = data - self.data.song.next = self.next + self.controls = None self.status = CONTINUE + + self.ptime = 0 + self.qtime = 0 + + self.label = gtk.Label("") + self.label.show() self.ptree = None self.pwin = gtk.ScrolledWindow() @@ -54,7 +62,7 @@ class PlistView(gtk.Notebook): if self.data.updateList == True: self.clearList(self.plist) self.data.updateList = False - self.ptime = self.popList(self.data.curList,self.plist,self.plabel) + self.ptime = self.popList(self.data.curList,self.plist) self.setTabText("plist") return True @@ -63,7 +71,6 @@ class PlistView(gtk.Notebook): self.plist = gtk.ListStore(int,str,str,str,str,int) if self.ptree: self.pwin.remove(self.ptree) - self.plabel = gtk.Label("") self.ptree,self.ptreesel = self.list2Tree(self.plist) self.pwin.add(self.ptree) self.prcmenu = gtk.Menu() @@ -71,13 +78,12 @@ class PlistView(gtk.Notebook): self.prcmenu.append(queue) self.plist.set_sort_column_id(self.data.sortedCol,gtk.SORT_ASCENDING) self.ptree.connect("button_release_event",self.clicked) - self.ptime = self.popList(self.data.curList,self.plist,self.plabel) + self.ptime = self.popList(self.data.curList,self.plist) # Populate a list - def popList(self,src,dst,label): + def popList(self,src,dst): time = self.generateList(src,dst) - label = self.makeTimeLabel(time) return time @@ -85,11 +91,9 @@ class PlistView(gtk.Notebook): self.qwin = gtk.ScrolledWindow() self.qwin.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.qlist = gtk.ListStore(int,str,str,str,str,int) - self.qlabel = gtk.Label("") self.qtree,self.qtreesel = self.list2Tree(self.qlist) self.qwin.add(self.qtree) self.qtime = self.generateList(self.data.curQ,self.qlist) - self.qlabel = self.makeTimeLabel(self.qtime) def generateList(self,src,dst): @@ -97,7 +101,6 @@ class PlistView(gtk.Notebook): i = len(dst) for index in src: track = self.data.library.files[index] - #dst.append([track.id,track.title,track.length,track.artist,track.album,track.count]) dst.insert(i,[track.id,track.title,track.length,track.artist,track.album,track.count]) time+=track.duration i+=1 @@ -118,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(False) + col.set_sort_indicator(True) if cols[i] != "Id": tree.append_column(col) tree.set_rules_hint(True) @@ -170,9 +173,7 @@ class PlistView(gtk.Notebook): string = "" string = self.toStr(day,"day")+self.toStr(hour,"hour") string += self.toStr(min,"minute")+self.toStr(sec,"second") - label = gtk.Label(string) - label.show() - return label + return string # Make a string for the amount of time @@ -188,11 +189,9 @@ class PlistView(gtk.Notebook): # User selected a song with mouse click def selectSong(self,widgit,iter,path,data,list): - #self.data.curSong = self.data.curList.index(list[iter][0]) self.data.curSong = self.plist[iter][0] self.loadSong(False) - if self.data.song.playing == False: - self.controls.plause(None,None) + self.controls.plause(None,None) # Go to the next song in the list @@ -201,6 +200,8 @@ class PlistView(gtk.Notebook): if len(self.data.curQ) > 0: self.data.curSong = self.qlist[0][0] self.data.curQ.pop(self.data.curQ.index(self.data.curSong)) + self.qtime -= self.data.library.files[self.data.curSong].duration + self.changedTab(None,None,1) self.qlist.remove(self.qlist.get_iter(0)) self.data.playingQ = True self.setTabText("queue") @@ -208,7 +209,6 @@ class PlistView(gtk.Notebook): self.data.curSong = random.randint(0,len(self.data.curList)) else: next = self.plist[0][0] - #self.data.curSong = self.plist[0][0] for i in range(len(self.plist)-1): if self.plist[i][0]==self.data.curSong: next = self.plist[i+1][0] @@ -216,9 +216,13 @@ class PlistView(gtk.Notebook): self.data.curSong = next if self.data.curSong >= len(self.data.curList): self.data.curSong = 0 + self.loadSong(True) - if not((self.data.song.playing==False) ^ (self.status==PAFTER)): + pause = (self.status == PAFTER) + + if pause == False: self.controls.plause(None,None) + self.controls.changeImg() self.status = CONTINUE @@ -228,7 +232,7 @@ class PlistView(gtk.Notebook): return if self.data.song: self.data.song.close() - self.data.song.passInfo(self.data.library.files[self.data.curSong]) + self.data.song = Song(self.data.library.files[self.data.curSong],self.next) if scroll == True: self.gotoCurSong() @@ -246,17 +250,26 @@ class PlistView(gtk.Notebook): self.ptreesel.select_path(i) - - + # A callback to show the right click menu def clicked(self,widget,data): if data.button == 3: self.prcmenu.popup(None,None,None,data.button,data.time) + # Called when songs are queued def enqueue(self,widgit,func,data): (model,pathlist) = self.ptreesel.get_selected_rows() for path in pathlist: q = self.plist[path] self.data.curQ+=[q[0]] self.qlist.append([q[0],q[1],q[2],q[3],q[4],q[5]]) + self.qtime+=self.data.library.files[q[0]].duration self.setTabText("queue") + + + # Update the total time label when a tab is changed + def changedTab(self,widgit,page,pagenum): + if pagenum == 0: + self.label.set_text(self.makeTimeLabel(self.ptime)) + else: + self.label.set_text(self.makeTimeLabel(self.qtime)) diff --git a/trunk/src/GuiObjects/scrobbler.py b/trunk/src/GuiObjects/scrobbler.py new file mode 100644 index 00000000..fbaf6bab --- /dev/null +++ b/trunk/src/GuiObjects/scrobbler.py @@ -0,0 +1,53 @@ +import urllib2 +import pygtk +pygtk.require('2.0') +import gtk +import webbrowser +import thread + +import xml.dom +from xml.dom import minidom + + +class Scrobbler(gtk.VBox): + def __init__(self,data): + 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=" + + # 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.makeRequest() + self.show() + + + def setup(self,widgit,data): + 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) + + + 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 + + attr = status.getAttributeNode("status") + if attr.value != "ok": + return + self.token += status.firstChild.nextSibling.firstChild.data + print self.token diff --git a/trunk/src/ocarina.py b/trunk/src/ocarina.py index ae39d3ab..b387bdd7 100644 --- a/trunk/src/ocarina.py +++ b/trunk/src/ocarina.py @@ -24,7 +24,8 @@ class main: self.options.verbose = True # Load saved data (or create new data) self.data = SavedData(self.options) - self.data.song = Song(self.quit) + #self.data.song = Song(self.quit) + self.data.quit = None self.window = Window(self.quit,self.options,self.data) gtk.main() diff --git a/trunk/src/saveddata.py b/trunk/src/saveddata.py index 12ffd49b..0b2347d5 100644 --- a/trunk/src/saveddata.py +++ b/trunk/src/saveddata.py @@ -22,6 +22,7 @@ class SavedData: self.path = path self.song = None self.random = False + self.quit = None if os.path.exists(path): try: diff --git a/trunk/src/song.py b/trunk/src/song.py index 1f164c15..d7411a99 100644 --- a/trunk/src/song.py +++ b/trunk/src/song.py @@ -7,13 +7,13 @@ import gst class Song(): #def __init__(self,info,exitFunc,prnt): - def __init__(self,exitFunc): - self.quit=exitFunc - # initialize player pipeline - self.next = None - self.info = None + def __init__(self,info,next): + self.next = next + self.info = info self.player = gst.Pipeline("player") self.bin = gst.element_factory_make("playbin",None) + self.bin.set_property("uri","file://"+self.info.filename) + self.bin.set_state(gst.STATE_PAUSED) self.player.add(self.bin) # initialize bus @@ -43,8 +43,6 @@ class Song(): # Toggle between play and pause def plause(self): - if self.hasFile == False: - return if self.playing == False: self.player.set_state(gst.STATE_PLAYING) self.playing = True @@ -55,8 +53,6 @@ class Song(): # Stop playback def stop(self): - if self.hasFile == False: - return self.player.set_state(gst.STATE_PAUSED) self.playing = False self.current = 0 @@ -65,7 +61,6 @@ class Song(): # Close the song def close(self): - self.playing = False self.player.set_state(gst.STATE_NULL) @@ -74,10 +69,3 @@ class Song(): if self.playing == False: return (False,False) return (True, self.player.query_position(self.time_format,None)[0]) - - - # Use to load a file path - def passInfo(self,info): - self.info = info - self.bin.set_property("uri","file://"+self.info.filename) - self.hasFile = True diff --git a/trunk/src/window.py b/trunk/src/window.py index 28387132..139d1355 100644 --- a/trunk/src/window.py +++ b/trunk/src/window.py @@ -9,6 +9,7 @@ from GuiObjects.libView import LibView from GuiObjects.plistView import PlistView from GuiObjects.controlPanel import ControlPanel from GuiObjects.infoView import InfoView +from GuiObjects.scrobbler import Scrobbler class Window(gtk.Window): @@ -96,10 +97,23 @@ class Window(gtk.Window): self.contentPane.add(self.divider) self.divider.show() + leftPane = gtk.Notebook() + leftPane.show() + leftPane.set_tab_pos(gtk.POS_LEFT) + self.libview = LibView(self.data) self.libview.show() - self.divider.add1(self.libview) + libLabel = gtk.Label("Library") + libLabel.set_angle(90) + leftPane.append_page(self.libview,libLabel) + scrobbler = Scrobbler(self.data) + scrobLabel = gtk.Label("Last.fm") + scrobLabel.set_angle(90) + leftPane.append_page(scrobbler,scrobLabel) + + self.divider.add1(leftPane) + rightPane=gtk.VBox(False,0) infoview = InfoView(self.data) @@ -117,12 +131,11 @@ class Window(gtk.Window): def makeBottomRow(self,vbox): box = gtk.HBox(False,0) - #box.pack_end(self.libview.label,False,False,10) + box.show() controls = ControlPanel(self.data,self.plistview) self.plistview.controls = controls vbox.pack_start(controls,False,False,0) - box.pack_end(self.plistview.plabel) - box.show() + box.pack_end(self.plistview.label) align = gtk.Alignment(1,1,0,0) align.add(box) align.show()