276 lines
7.0 KiB
Python
276 lines
7.0 KiB
Python
import random
|
|
import gobject
|
|
import pygtk
|
|
pygtk.require('2.0')
|
|
import gtk
|
|
|
|
from menuItem import MenuItem
|
|
from song import Song
|
|
|
|
CONTINUE = 0
|
|
PAFTER = 1
|
|
|
|
# This is both the playlist and the queue
|
|
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.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()
|
|
self.pwin.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
|
|
self.pwin.show()
|
|
|
|
self.qtree = None
|
|
self.makePList()
|
|
self.makeQList()
|
|
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)
|
|
|
|
|
|
# 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
|
|
|
|
|
|
# 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(True)
|
|
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):
|
|
max = len(list)
|
|
if max == 0:
|
|
return
|
|
if max > 0:
|
|
iter = list.get_iter(0)
|
|
for i in range(0,max):
|
|
list.remove(iter)
|
|
|
|
|
|
# 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.plist[iter][0]
|
|
self.loadSong(False)
|
|
self.controls.plause(None,None)
|
|
|
|
|
|
# Go to the next song in the list
|
|
def next(self,widgit,data):
|
|
self.data.playingQ = False
|
|
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 = random.randint(0,len(self.data.curList))
|
|
else:
|
|
next = 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]
|
|
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.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.song.close()
|
|
self.data.song = Song(self.data.library.files[self.data.curSong],self.next)
|
|
if scroll == True:
|
|
self.gotoCurSong()
|
|
|
|
|
|
# Scroll window and select row with current song
|
|
def gotoCurSong(self):
|
|
if len(self.data.curList) == 0:
|
|
return
|
|
for i in range(len(self.data.curList)):
|
|
if self.plist[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.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))
|