369 lines
9.3 KiB
Python
369 lines
9.3 KiB
Python
import gtk
|
|
import gobject
|
|
import os
|
|
import thread
|
|
|
|
from label import Label
|
|
from queue import Queue
|
|
from playlist import Playlist
|
|
from liblist import LibList
|
|
from image import Image
|
|
from check import CheckButton
|
|
from button import Button
|
|
from scrobbler import Scrobbler
|
|
from controlPanel import ControlPanel
|
|
|
|
|
|
# This is the main content area
|
|
class ContentPane(gtk.HBox):
|
|
def __init__(self,data):
|
|
gtk.HBox.__init__(self,False,0)
|
|
self.data = data
|
|
|
|
self.divider = gtk.HPaned()
|
|
self.divider.set_position(self.data.divider)
|
|
self.divider.connect("notify",self.moveDivider)
|
|
self.divider.show()
|
|
self.add(self.divider)
|
|
|
|
self.makeLeftSide()
|
|
self.makeRightSide()
|
|
|
|
self.show()
|
|
# Load up the last saved song
|
|
try:
|
|
self.library.loadSong(self.data.library.files[self.data.curSong])
|
|
except:
|
|
True == True
|
|
self.gotoCurSong()
|
|
|
|
|
|
# Left side is scrobbler, album art, maybe others at some point?
|
|
def makeLeftSide(self):
|
|
vbox = gtk.VBox(False,0)
|
|
vbox.show()
|
|
self.albumArt = Image(None,None)
|
|
vbox.pack_start(self.albumArt,False,False,0)
|
|
self.data.scrobbler = Scrobbler(self.data)
|
|
vbox.pack_start(self.data.scrobbler,False,False,0)
|
|
self.divider.add(vbox)
|
|
|
|
|
|
# Right side has tabs, current song info, controls, and more
|
|
def makeRightSide(self):
|
|
vbox = gtk.VBox(False,0)
|
|
vbox.show()
|
|
self.divider.add2(vbox)
|
|
|
|
self.makeInfoArea(vbox)
|
|
self.makeTabs(vbox)
|
|
self.makeControls(vbox)
|
|
|
|
hbox = gtk.HBox(False,0)
|
|
|
|
hbox.pack_start(self.library.pbaralign,False,False,0)
|
|
hbox.pack_end(self.playlist.align,False,False,0)
|
|
hbox.pack_end(self.queue.align,False,False,0)
|
|
hbox.pack_end(self.library.align,False,False,0)
|
|
|
|
vbox.pack_start(hbox,False,False,0)
|
|
hbox.show()
|
|
|
|
#self.changedTab(None,None,0)
|
|
self.status = ""
|
|
self.filterCount = 0
|
|
|
|
|
|
def setLabels(self):
|
|
title = ""
|
|
album = ""
|
|
artist = ""
|
|
if self.data.song:
|
|
title = self.data.song.info.title
|
|
album = "from "+self.data.song.info.album
|
|
artist = "by "+self.data.song.info.artist
|
|
self.title.set_text(title)
|
|
self.album.set_text(album)
|
|
self.artist.set_text(artist)
|
|
|
|
|
|
# This is the upper end of the right side of the divider
|
|
# Current song labels, and the filter entry
|
|
def makeInfoArea(self,box):
|
|
# Make the labels
|
|
self.title = Label("",13000,700)
|
|
self.album = Label("",10000,400)
|
|
self.artist = Label("",10000,400)
|
|
self.setLabels()
|
|
|
|
infobox = gtk.HBox(False,0)
|
|
infobox.show()
|
|
infolabels = gtk.VBox(False,0)
|
|
infolabels.show()
|
|
infobox.pack_start(infolabels,False,False,0)
|
|
|
|
# Pack the labels into a vbox
|
|
infolabels.pack_start(self.title,False,False,0)
|
|
infolabels.pack_start(self.album,False,False,0)
|
|
infolabels.pack_start(self.artist,False,False,0)
|
|
|
|
# Make the filter bar
|
|
self.searchBar = gtk.Entry()
|
|
self.searchBar.show()
|
|
self.searchBar.connect("changed",self.textTyped)
|
|
searchalign = gtk.Alignment(1,1,0,0)
|
|
searchalign.show()
|
|
searchalign.add(self.searchBar)
|
|
infobox.pack_end(searchalign,False,False,0)
|
|
|
|
# Pack it all in
|
|
box.pack_start(infobox,False,False,0)
|
|
|
|
|
|
# Makes the playlist/queue/library tabs
|
|
def makeTabs(self,box):
|
|
self.tabs = gtk.Notebook()
|
|
box.add(self.tabs)
|
|
self.tabs.show()
|
|
|
|
# Ann array of function pointers that gets passed to List
|
|
funcs = (self.next,self.setLabels,self.plause,self.setAlbumArt)
|
|
|
|
self.queue = Queue(self.data,funcs)
|
|
self.playlist = Playlist(self.data,self.queue,funcs)
|
|
self.playlist.visible("show")
|
|
self.library = LibList(self.data,self.playlist,self.queue,funcs)
|
|
self.data.library.libview = self.library
|
|
|
|
self.tabs.append_page(self.playlist,self.playlist.label)
|
|
self.tabs.append_page(self.queue,self.queue.label)
|
|
self.tabs.append_page(self.library,self.library.label)
|
|
|
|
self.curTab = 0
|
|
self.tabs.connect("switch-page",self.changedTab)
|
|
#self.filter("")
|
|
|
|
|
|
# Makes buttons and progress bar
|
|
def makeControls(self,vbox):
|
|
box = gtk.HBox(False,0)
|
|
box.show()
|
|
self.pauseImg = Image(None,gtk.STOCK_MEDIA_PAUSE)
|
|
|
|
box.pack_start(CheckButton("Random",self.toggleRand,self.data.random),False,False,0)
|
|
|
|
hbox = gtk.VBox()
|
|
hbox.show()
|
|
pbar = gtk.ProgressBar()
|
|
pbar.show()
|
|
pbar.set_fraction(0)
|
|
event = gtk.EventBox()
|
|
event.show()
|
|
event.add(pbar)
|
|
hbox.pack_start(event,True,False,0)
|
|
event.connect("button_release_event",self.pbarclick,pbar)
|
|
box.pack_start(hbox,True,True,0)
|
|
gobject.timeout_add(500,self.updatePBar,pbar)
|
|
|
|
(self.playImg,self.plauseBtn) = self.makeButton("plause",gtk.STOCK_MEDIA_PLAY,self.plause,box)
|
|
(self.stopImg,self.stopBtn) = self.makeButton("stop",gtk.STOCK_MEDIA_STOP,self.stop,box)
|
|
(self.nextImg,self.nextBtn) = self.makeButton("next",gtk.STOCK_MEDIA_NEXT,self.next,box)
|
|
|
|
vbox.pack_start(box,False,False,0)
|
|
|
|
|
|
def makeButton(self,name,img,func,box):
|
|
image = Image(None,img)
|
|
button = Button(name,image,None,func)
|
|
box.pack_start(button,False,False,0)
|
|
return image,button
|
|
|
|
|
|
# Turn shuffle on/off
|
|
def toggleRand(self,widgit):
|
|
self.data.random = not self.data.random
|
|
|
|
|
|
# A callback for when the user seeks into the song
|
|
def pbarclick(self,widgit,data,pbar):
|
|
if data.button==1:
|
|
prcnt = float(data.x) / float(pbar.get_allocation()[2])
|
|
self.data.song.seek(int(prcnt * self.data.song.info.duration * 1000000000))
|
|
|
|
|
|
# Updates the progress bar to the current % of song
|
|
def updatePBar(self,pbar):
|
|
time = 0
|
|
if not self.data.song:
|
|
return True
|
|
try:
|
|
time = self.data.song.curTime()
|
|
except:
|
|
time = 0
|
|
if self.data.song.info.duration > 0:
|
|
pbar.set_fraction(float(time)/self.data.song.info.duration)
|
|
pbar.set_text(self.data.song.info.fixTime(time) + " / " + self.data.song.info.length)
|
|
return True
|
|
|
|
|
|
# Called when the play/pause button is clicked
|
|
def plause(self,widgit,data):
|
|
self.data.song.plause()
|
|
self.changeImg()
|
|
|
|
|
|
# Stop the song, change plause button
|
|
def stop(self,widgit,data):
|
|
self.data.song.stop()
|
|
self.changeImg()
|
|
|
|
|
|
# Advance to the next song, save updates
|
|
def next(self,widgit,data):
|
|
loaded = self.queue.getNext()
|
|
#print loaded
|
|
if loaded == False:
|
|
loaded = self.playlist.getNext()
|
|
if not (self.status == "pafter") and (loaded==True):
|
|
self.plause(None,None)
|
|
self.data.scrobbler.nowPlaying(self.data.song.info)
|
|
#self.gotoCurSong()
|
|
self.changeImg()
|
|
self.status = ""
|
|
self.data.dump(True)
|
|
|
|
|
|
# Scroll to the current song
|
|
def gotoCurSong(self):
|
|
self.playlist.gotoCurSong()
|
|
self.queue.gotoCurSong()
|
|
self.library.gotoCurSong()
|
|
|
|
|
|
# Change the state of the play/pause button
|
|
def changeImg(self):
|
|
self.plauseBtn.set_image(self.playImg)
|
|
if self.data.song.playing == True:
|
|
self.plauseBtn.set_image(self.pauseImg)
|
|
|
|
|
|
# Load album art
|
|
def setAlbumArt(self,file):
|
|
file = file.rsplit(os.path.sep,1)[0]
|
|
file = os.path.join(file,"AlbumArt.jpg")
|
|
self.albumArt.hide()
|
|
# Fetch album art if we don't have it yet
|
|
if not os.path.exists(file):
|
|
info = self.data.song.info
|
|
thread.start_new_thread(self.fetchAlbumArt,(info.artist,info.album,file))
|
|
else:
|
|
self.albumArt.set(file)
|
|
self.resizeAlbumArt()
|
|
self.albumArt.show()
|
|
|
|
|
|
def fetchAlbumArt(self,artist,album,file):
|
|
info = self.data.song.info
|
|
self.data.scrobbler.fetchAlbumArt(artist,album,file)
|
|
if os.path.exists(file):
|
|
self.albumArt.set(file)
|
|
self.resizeAlbumArt()
|
|
self.albumArt.show()
|
|
|
|
|
|
def resizeAlbumArt(self):
|
|
self.albumArt.scale(self.data.divider)
|
|
|
|
|
|
# This is called when a user changes tabs
|
|
# Do nothing if the user selects the same tab
|
|
# Otherwise, hide objects on the old visible tab and show the new visible tab
|
|
# Also updates self.curTab
|
|
def changedTab(self,widgit,page,pagenum):
|
|
if self.curTab == pagenum:
|
|
return
|
|
|
|
if self.curTab == 0:
|
|
self.playlist.visible("hide")
|
|
elif self.curTab == 1:
|
|
self.queue.visible("hide")
|
|
else:
|
|
self.library.visible("hide")
|
|
|
|
self.curTab = pagenum
|
|
|
|
if pagenum == 0:
|
|
self.playlist.visible("show")
|
|
elif pagenum == 1:
|
|
self.queue.visible("show")
|
|
else:
|
|
self.library.visible("show")
|
|
self.textTyped(self.searchBar)
|
|
|
|
|
|
def dumpLib(self):
|
|
self.library.drop()
|
|
self.playlist.drop()
|
|
self.queue.drop()
|
|
|
|
|
|
# text was typed, refilter rows
|
|
# Arrange to filter rows in 250ms, as long as no additional text has been typed
|
|
def textTyped(self,entry):
|
|
search = entry.get_text().lower()
|
|
self.filterCount+=1
|
|
gobject.timeout_add(250,self.filter,search)
|
|
|
|
|
|
# Filter the rows of the current tab
|
|
# Do a quickFilter on nonvisible tabs
|
|
# Decrements self.filterCount
|
|
def filter(self,search):
|
|
# If filterCount is 0, no additional text has been typed
|
|
self.filterCount -= 1
|
|
if self.filterCount > 0:
|
|
return
|
|
# It is ok to filter rows
|
|
if self.curTab == 0:
|
|
self.playlist.filterRows(search)
|
|
tabs = [1,2]
|
|
elif self.curTab == 1:
|
|
self.queue.filterRows(search)
|
|
tabs = [0,2]
|
|
else:
|
|
self.library.filterRows(search)
|
|
tabs = [0,1]
|
|
|
|
for tab in tabs:
|
|
if tab == 0:
|
|
self.playlist.filterQuick(search)
|
|
elif tab == 1:
|
|
self.queue.filterQuick(search)
|
|
else:
|
|
self.library.filterQuick(search)
|
|
|
|
|
|
# Coose to pause after the current song or not
|
|
def setStatus(self,status):
|
|
if status == "pafter":
|
|
self.status = "pafter"
|
|
else:
|
|
print status
|
|
|
|
|
|
# Store the width of the current tabs columns
|
|
def storeCols(self):
|
|
if self.curTab == 0:
|
|
self.playlist.storeCols()
|
|
elif self.curTab == 1:
|
|
self.queue.storeCols()
|
|
else:
|
|
self.library.storeCols()
|
|
|
|
|
|
# This is called whenever the divider changes
|
|
def moveDivider(self,pane,event):
|
|
if event.name=="position":
|
|
self.data.divider = pane.get_position()
|
|
self.resizeAlbumArt()
|