import pygame from pygame.locals import * pygame.init() import pygst pygst.require("0.10") import gst, gtk import os, time, subprocess class ItemLeaf(object): def __init__(self, maintext, url, subtext=""): self.maintext = maintext self.subtext = subtext self.url = url self.parent = None self.surface = None def __str__(self): return self.maintext def __unicode__(self): return self.maintext class ItemList(object): def __init__(self, name, serve_sorted=False, has_all_option=True): self.list = [] self.name = name self.parent = None self.surface = None self.serve_sorted = serve_sorted self.current_item = 0 self.has_all_option = has_all_option if has_all_option: all_option = ItemLeaf("Play All", "playall://") self.list.append(all_option) def __getitem__(self, idx): return self.list[idx] def append(self, item): if not isinstance(item, ItemList) and not isinstance(item, ItemLeaf): raise "You can't put random shit in an ItemList" item.parent = self self.list.append(item) if self.serve_sorted: if self.has_all_option: all_option = self.list.pop(0) self.list.sort(lambda a,b: cmp(unicode(a).lower(), unicode(b).lower())) if self.has_all_option: self.list.insert(0, all_option) def __str__(self): return self.name def __len__(self): return len(self.list) def __unicode__(self): return self.name def dump(l, prefix=""): if hasattr(l, "url"): print " %s%s (leaf)" % (prefix, l) else: print "%s%s (parent %s)" % (prefix, l, l.parent) for sub in l: dump(sub, prefix + " ") import sqlite3 con = sqlite3.connect('/home/aquarius/.config/banshee-1/banshee.db') crs = con.cursor() media = ItemList("media", has_all_option=False) music = ItemList("Music", has_all_option=False) media.append(music) crs.execute("select t.uri, t.title, a.name, al.title from coretracks t inner join coreartists a on t.artistid = a.artistid inner join corealbums al on al.albumid=t.albumid order by a.name, al.title, t.tracknumber limit 250") byartist = ItemList("By artist", serve_sorted=True, has_all_option=False) music.append(byartist) allsongs = ItemList("All songs", serve_sorted=True) music.append(allsongs) current_artist = None current_album = None for relative_uri, song, artist, album in crs: uri = "/home/aquarius/.gvfs/sftp on tara.local/home/aquarius/Music/" + relative_uri if artist != current_artist: current_artist = artist artist_itemlist = ItemList(artist, serve_sorted=True, has_all_option=False) byartist.append(artist_itemlist) allsongs_album_itemlist = ItemList("All songs", serve_sorted=True) artist_itemlist.append(allsongs_album_itemlist) current_album = None if album != current_album: current_album = album album_itemlist = ItemList(album) artist_itemlist.append(album_itemlist) song_itemleaf = ItemLeaf(song, uri) album_itemlist.append(song_itemleaf) song_itemleaf2 = ItemLeaf(song, uri, artist) allsongs.append(song_itemleaf2) song_itemleaf3 = ItemLeaf(song, uri) allsongs_album_itemlist.append(song_itemleaf3) playlists = ItemList("Playlists", serve_sorted=True, has_all_option=False) music.append(playlists) crs.execute("select p.name, t.title, t.uri, a.name from coresmartplaylists p inner join coresmartplaylistentries e on p.smartplaylistid = e.smartplaylistid inner join coretracks t on e.trackid = t.trackid inner join coreartists a on t.artistid = a.artistid limit 250") current_playlist = None for playlist, song, relative_uri, artist in crs: uri = "/home/aquarius/.gvfs/sftp on tara.local/home/aquarius/Music/" + relative_uri if playlist != current_playlist: current_playlist = playlist playlist_itemlist = ItemList(playlist) playlists.append(playlist_itemlist) song_itemleaf = ItemLeaf("%s - %s" % (song, artist), uri) playlist_itemlist.append(song_itemleaf) crs.close() con.close() ixCurrentItem = 0 screen = pygame.display.set_mode((800,600)) pygame.display.set_caption('Monkey Fever') pygame.mouse.set_visible(0) background = pygame.Surface(screen.get_size()) background = background.convert() background.fill((20,0,0)) def surfaceFromText(tText=None, cColour=(255, 255, 255), fsSize=36): font = pygame.font.Font(None, fsSize) sText = font.render(unicode(tText), 1, cColour) return sText def render(lsItems, ixCurrentItem): screen.blit(background, (0, 0)) fsSize = 30 parents = [lsItems.name] parent = lsItems.parent while parent is not None: parents.insert(0, parent.name) parent = parent.parent for i in range(-3, 10): ixThisItem = ixCurrentItem + i if ixThisItem >= len(lsItems) or ixThisItem < 0: continue if i == 0: col = (255, 255, 255) else: col = (160,160,160) sThisSurface = surfaceFromText(lsItems[ixThisItem], cColour=col, fsSize=fsSize) y = 100 + (i * fsSize) # XXX change screen.blit(sThisSurface, (150, y)) for i in range(len(parents)): txt = parents[i] if len(txt) > 12: txt = txt[:9] + "..." sParentSurface = surfaceFromText(txt, fsSize=fsSize) y = 100 + (i * fsSize) # XXX change screen.blit(sParentSurface, (10, y)) pygame.display.flip() def on_sync_message(bus, message): if message.structure is None: return message_name = message.structure.get_name() if message_name == 'prepare-xwindow-id': imagesink = message.src #imagesink.set_property('force-aspect-ratio', True) imagesink.set_xwindow_id(XWINDOWID) def on_bus_message(bus, message): """receives message posted on the GstBus""" print "got a bus message" pygame.key.set_repeat(300, 1) onstep = 1 repeat_count = 0 lsItems = media mode = "BROWSING" XWINDOWID = pygame.display.get_wm_info()["window"] pygame.event.set_allowed([KEYDOWN, KEYUP, QUIT]) while 1: gtk.main_iteration(block=False) event = pygame.event.poll() if event.type != NOEVENT: render(lsItems, ixCurrentItem) if event.type == QUIT: break elif event.type == KEYDOWN and event.key == K_ESCAPE: break if mode == "BROWSING": if event.type == KEYDOWN and event.key == K_UP: ixCurrentItem -= onstep if ixCurrentItem < 0: ixCurrentItem = 0 lsItems.current_item = ixCurrentItem repeat_count += 1 if repeat_count > 20: onstep = 5 if repeat_count > 40: onstep = 20 if repeat_count > 60: onstep = 50 elif event.type == KEYDOWN and event.key == K_DOWN: ixCurrentItem += onstep if ixCurrentItem > len(lsItems) - 1: ixCurrentItem = len(lsItems) - 1 lsItems.current_item = ixCurrentItem repeat_count += 1 if repeat_count > 20: onstep = 5 if repeat_count > 40: onstep = 20 if repeat_count > 60: onstep = 50 elif event.type == KEYDOWN and event.key == K_RIGHT: if not hasattr(lsItems[ixCurrentItem], "url"): # can't descend into a leaf lsItems = lsItems[ixCurrentItem] ixCurrentItem = lsItems.current_item elif event.type == KEYDOWN and event.key == K_LEFT and lsItems.parent: lsItems = lsItems.parent ixCurrentItem = lsItems.current_item elif event.type == KEYUP and event.key == K_RETURN: # keyup so it's the last if hasattr(lsItems[ixCurrentItem], "url"): url = lsItems[ixCurrentItem].url if url == "playall://": fp = open("/tmp/playlist.m3u", "w") for item in lsItems: if hasattr(item, "url") and item.url != "playall://": fp.write(item.url + "\n") fp.close() os.environ["TOTEM_QUIT_ON_FINISH"] = "yes" subprocess.call(["totem", "--fullscreen", "/tmp/playlist.m3u"]) os.remove("/tmp/playlist.m3u") else: import urllib pipeline = gst.parse_launch("playbin uri=file://%s" % urllib.quote(url)) vis = gst.element_factory_make("goom", "goom") pipeline.set_property("vis-plugin", vis) sink = gst.element_factory_make("xvimagesink", "xvimagesink") pipeline.set_property("video-sink", sink) sink.set_xwindow_id(XWINDOWID) bus = pipeline.get_bus() bus.add_signal_watch() bus.enable_sync_message_emission() # #bus.connect('sync-message::element', on_sync_message) pipeline.set_state(gst.STATE_PLAYING) #os.environ["TOTEM_QUIT_ON_FINISH"] = "yes" #subprocess.call(["totem", "--fullscreen", url]) elif event.type == KEYUP: repeat_count = 0 onstep = 1 pygame.key.set_repeat(30, 50) if mode == "PLAYING": if event.type == KEYUP and event.key == K_RIGHT: subprocess.call(["totem", "--seek-fwd"]) if event.type == KEYUP and event.key == K_LEFT: subprocess.call(["totem", "--seek-bwd"]) elif event.type == USEREVENT and event.totemquit: pygame.event.set_grab(False) mode = "BROWSING"