import random import gtk import thread import re from menuItem import MenuItem from song import Song from list import List CONTINUE = 0 PAFTER = 1 # This is both the playlist and the queue class PlistView(gtk.Notebook): def __init__(self,data,info): gtk.Notebook.__init__(self) self.connect("switch-page",self.changedTab) self.set_scrollable(True) self.data = data self.info = info self.controls = None self.status = CONTINUE self.ptime = 0 self.qtime = 0 self.search = "" self.label = gtk.Label("") self.label.show() self.ptree = None self.pwin = gtk.ScrolledWindow() self.pwin.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.pwin.show() self.qtree = None self.makePList() self.makeQList() self.makeSearch() self.qwin.show() self.loadSong(True) #gobject.timeout_add(1000,self.checkUpdate) self.append_page(self.pwin,gtk.Label("")) self.append_page(self.qwin,gtk.Label("")) self.setTabText("plist") self.setTabText("queue") self.show() def setStatus(self,status): if status == "pafter": self.status = PAFTER def setTabText(self,tab): if tab == "plist": self.set_tab_label_text(self.pwin,"Playlist ("+str(len(self.data.curList))+")") else: self.set_tab_label_text(self.qwin,"Queue ("+str(len(self.data.curQ))+")") # Check if the playlist has been updated def checkUpdate(self): if self.data.updateList == True: self.clearList(self.plist) self.data.updateList = False self.ptime = self.popList(self.data.curList,self.plist) self.setTabText("plist") return True def makePList(self): self.plist = gtk.ListStore(int,str,str,str,str,int) if self.ptree: self.pwin.remove(self.ptree) self.ptree,self.ptreesel = self.list2Tree(self.plist) self.pwin.add(self.ptree) self.prcmenu = gtk.Menu() queue = MenuItem("Queue Song",self.enqueue,None,None,None,) 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.pfilter = self.plist.filter_new() self.pfilter.set_visible_func(self.hideRows) self.psort = gtk.TreeModelSort(self.pfilter) self.ptree.set_model(self.psort) #self.pfilter.set_child(self.ptreesel) # Populate a list def popList(self,src,dst): time = self.generateList(src,dst) return time def makeQList(self): 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.qtree,self.qtreesel = self.list2Tree(self.qlist) self.qwin.add(self.qtree) self.qtime = self.generateList(self.data.curQ,self.qlist) def generateList(self,src,dst): time = 0 i = len(dst) for index in src: track = self.data.library.files[index] dst.insert(i,[track.id,track.title,track.length,track.artist,track.album,track.count]) time+=track.duration i+=1 return time # Called by libview to add rows to list def addToList(self,src,dest): self.ptime+=self.generateList(src,dest) self.updatePTime() self.setTabText("plist") # Make the playlist and show it def list2Tree(self,list): tree = gtk.TreeView(list) cell = gtk.CellRendererText() cols = ["Id","Title","Length","Artist","Album","#"] lenSaved = len(self.data.colSizes) 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": tree.append_column(col) tree.set_rules_hint(True) tree.set_enable_search(True) tree.connect("row-activated",self.selectSong,"clicked",list) treesel = tree.get_selection() tree.show() self.resizeCols(tree) return tree,treesel # Use to save column widths def saveCols(self): cols = self.ptree.get_columns() self.data.colSizes = [] for col in cols: self.data.colSizes +=[col.get_width()] # Uses saved column settings def resizeCols(self,tree): cols = tree.get_columns() for i in range(len(self.data.colSizes)): cols[i].set_fixed_width(self.data.colSizes[i]) # Erase the entire list def clearList(self,list,time): max = len(list) if max == 0: return if max > 0: iter = list.get_iter(0) for i in range(0,max): list.remove(iter) self.ptime = 0 self.setTabText("plist") self.updatePTime() # Update the playlist time label def updatePTime(self): page = self.get_current_page() if page==0: self.label.set_text(self.makeTimeLabel(self.ptime)) # Shows total running time of the playlist def makeTimeLabel(self,sec): day = 0 hour = 0 min = 0 day = sec/86500 sec = sec-(day*86500) hour = sec/3600 sec = sec-(hour*3600) min = sec/60 sec = sec-(min*60) string = "" string = self.toStr(day,"day")+self.toStr(hour,"hour") string += self.toStr(min,"minute")+self.toStr(sec,"second") return string # Make a string for the amount of time def toStr(self,time,label): if time > 0: string=str(time) + " "+label if time > 1: string+="s" string += " " return string return "" # User selected a song with mouse click def selectSong(self,widgit,iter,path,data,list): self.data.curSong = self.pfilter[iter][0] self.loadSong(False) self.controls.plause(None,None) self.data.scrobbler.nowPlaying(self.data.library.files[self.data.curSong]) # Go to the next song in the list def next(self,widgit,data): self.data.playingQ = False #print self.pfilter[0][1] #print self.pfilter[1][1] #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)) 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") elif self.data.random == True: self.data.curSong = self.pfilter[random.randint(0,len(self.pfilter)-1)][0] else: next = self.pfilter[0][0] for i in range(len(self.pfilter)-1): if self.pfilter[i][0]==self.data.curSong: next = self.pfilter[i+1][0] break self.data.curSong = next #if self.data.curSong >= len(self.data.curList): # self.data.curSong = 0 self.loadSong(True) pause = (self.status == PAFTER) if pause == False: self.controls.plause(None,None) self.data.scrobbler.nowPlaying(self.data.library.files[self.data.curSong]) self.controls.changeImg() self.status = CONTINUE # Load a song and begin playback def loadSong(self,scroll): if len(self.data.curList) == 0: return if self.data.song: self.data.scrobbler.submit(self.data.song.timestamp) self.data.song.close() self.data.song = Song(self.data.library.files[self.data.curSong],self.next) self.info.changeLabels() if scroll == True: self.gotoCurSong() # Scroll window and select row with current song def gotoCurSong(self): if len(self.pfilter) == 0: return for i in range(len(self.pfilter)): if self.pfilter[i][0] == self.data.song.info.id: if i > 10: self.ptree.scroll_to_cell(i-10,None,True,0,0) else: self.ptree.scroll_to_cell(0,None,True,0,0) self.ptree.set_cursor_on_cell(i,None,None,False) # 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.pfilter[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)) def makeSearch(self): self.searchBar = gtk.Entry() self.searchBar.connect("changed",self.textTyped) self.searchBar.show() def textTyped(self,entry): self.search = entry.get_text().lower() self.pfilter.refilter() self.gotoCurSong() def hideRows(self,list,iter): if self.search == "": return True elif len(self.search) == 1: try: self.data.library.files[list[iter][0]].single[self.search] return True except: return False elif len(self.search) == 2: try: self.data.library.files[list[iter][0]].double[self.search] return True except: return False 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