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()