From facd2a5710fb05ac80d55ed8e1af8184fb496c02 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristoffer=20Gr=C3=B6nlund?= Date: Sat, 2 Jan 2010 02:26:23 +0100 Subject: [PATCH] Tons of fixes/tweaks/changes in general --- jamaendo/api.py | 111 +++++++++++++++++++++++++++++++++++--- jamaui/__init__.py | 6 ++- jamaui/albumlist.py | 31 +++++++++++ jamaui/favorites.py | 16 +++--- jamaui/featured.py | 2 +- jamaui/player.py | 5 ++ jamaui/playerwindow.py | 139 ++++++++++++++++++++++++++++++++---------------- jamaui/postoffice.py | 26 ++++----- jamaui/radios.py | 36 +++---------- jamaui/search.py | 2 +- jamaui/settings.py | 2 +- jamaui/showalbum.py | 10 ++-- jamaui/songposition.py | 92 ++++++++++++++++++++++++++++++++ 13 files changed, 365 insertions(+), 113 deletions(-) create mode 100644 jamaui/songposition.py diff --git a/jamaendo/api.py b/jamaendo/api.py index 44a47e1..4c94cac 100644 --- a/jamaendo/api.py +++ b/jamaendo/api.py @@ -59,7 +59,7 @@ def set_cache_dir(cachedir): _ARTIST_FIELDS = ['id', 'name', 'image'] _ALBUM_FIELDS = ['id', 'name', 'image', 'artist_name', 'artist_id', 'license_url'] -_TRACK_FIELDS = ['id', 'name', 'image', 'artist_name', 'album_name', 'album_id', 'numalbum', 'duration'] +_TRACK_FIELDS = ['id', 'name', 'image', 'artist_id', 'artist_name', 'album_name', 'album_id', 'numalbum', 'duration'] _RADIO_FIELDS = ['id', 'name', 'idstr', 'image'] class LazyQuery(object): @@ -152,6 +152,7 @@ class Track(LazyQuery): self.ID = int(ID) self.name = None self.image = None + self.artist_id = None self.artist_name = None self.album_name = None self.album_id = None @@ -167,10 +168,10 @@ class Track(LazyQuery): return _OGGURL%(self.ID) def _needs_load(self): - return self._needs_load_impl('name', 'artist_name', 'album_name', 'album_id', 'numalbum', 'duration') + return self._needs_load_impl('name', 'artist_name', 'artist_id', 'album_name', 'album_id', 'numalbum', 'duration') def _set_from(self, other): - return self._set_from_impl(other, 'name', 'image', 'artist_name', 'album_name', 'album_id', 'numalbum', 'duration') + return self._set_from_impl(other, 'name', 'image', 'artist_name', 'artist_id', 'album_name', 'album_id', 'numalbum', 'duration') class Radio(LazyQuery): def __init__(self, ID, json=None): @@ -217,7 +218,7 @@ class Query(object): pass def _geturl(self, url): - #print "*** %s" % (url) + print "*** %s" % (url) Query._ratelimit() try: f = urllib.urlopen(url) @@ -347,11 +348,21 @@ class GetQuery(Query): 'params' : 'artist_id=%d', 'constructor' : Artist }, + 'artist_list' : { + 'url' : _GET2+'+'.join(_ALBUM_FIELDS)+'/artist/json/?', + 'params' : 'artist_id=%s', + 'constructor' : Album + }, 'album' : { 'url' : _GET2+'+'.join(_ALBUM_FIELDS)+'/album/json/?', 'params' : 'album_id=%d', 'constructor' : Album }, + 'album_list' : { + 'url' : _GET2+'+'.join(_ALBUM_FIELDS)+'/album/json/?', + 'params' : 'album_id=%s', + 'constructor' : Album + }, 'albums' : { 'url' : _GET2+'+'.join(_ALBUM_FIELDS)+'/album/json/?', 'params' : 'artist_id=%d', @@ -362,6 +373,11 @@ class GetQuery(Query): 'params' : 'id=%d', 'constructor' : Track }, + 'track_list' : { + 'url' : _GET2+'+'.join(_TRACK_FIELDS)+'/track/json/track_album+album_artist?', + 'params' : 'id=%s', + 'constructor' : Track + }, 'tracks' : { 'url' : _GET2+'+'.join(_TRACK_FIELDS)+'/track/json/track_album+album_artist?', 'params' : 'order=numalbum_asc&album_id=%d', @@ -449,6 +465,12 @@ def _update_cache(cache, new_items): old._set_from(item) else: cache[item.ID] = item + if isinstance(item, Artist) and item.albums: + for album in item.albums: + _update_cache(_albums, album) + elif isinstance(item, Album) and item.tracks: + for track in item.tracks: + _update_cache(_tracks, track) def get_artist(artist_id): """Returns: Artist""" @@ -463,8 +485,56 @@ def get_artist(artist_id): a = a[0] return a -def get_albums(artist_id): +def get_artists(artist_ids): + """Returns: [Artist]""" + assert(isinstance(artist_ids, list)) + found = [] + lookup = [] + for artist_id in artist_ids: + a = _artists.get(artist_id, None) + if not a: + lookup.append(artist_id) + else: + found.append(a) + if lookup: + q = GetQuery('artist_list', '+'.join(str(x) for x in lookup)) + a = q.execute() + if not a: + raise JamendoAPIException(str(q)) + _update_cache(_artists, a) + lookup = a + return found + lookup + +def get_album_list(album_ids): """Returns: [Album]""" + assert(isinstance(album_ids, list)) + found = [] + lookup = [] + for album_id in album_ids: + a = _albums.get(album_id, None) + if not a: + lookup.append(album_id) + else: + found.append(a) + if lookup: + q = GetQuery('album_list', '+'.join(str(x) for x in lookup)) + a = q.execute() + if not a: + raise JamendoAPIException(str(q)) + _update_cache(_albums, a) + lookup = a + return found + lookup + +def get_albums(artist_id): + """Returns: [Album] + Parameter can either be an artist_id or a list of album ids. + """ + if isinstance(artist_id, list): + return get_album_list(artist_id) + a = _artists.get(artist_id, None) + if a and a.albums: + return a.albums + q = GetQuery('albums', artist_id) a = q.execute() if not a: @@ -485,8 +555,36 @@ def get_album(album_id): a = a[0] return a -def get_tracks(album_id): +def get_track_list(track_ids): """Returns: [Track]""" + assert(isinstance(track_ids, list)) + found = [] + lookup = [] + for track_id in track_ids: + a = _tracks.get(track_id, None) + if not a: + lookup.append(track_id) + else: + found.append(a) + if lookup: + q = GetQuery('track_list', '+'.join(str(x) for x in lookup)) + a = q.execute() + if not a: + raise JamendoAPIException(str(q)) + _update_cache(_tracks, a) + lookup = a + return found + lookup + +def get_tracks(album_id): + """Returns: [Track] + Parameter can either be an album_id or a list of track ids. + """ + if isinstance(album_id, list): + return get_track_list(album_id) + a = _albums.get(album_id, None) + if a and a.tracks: + return a.tracks + q = GetQuery('tracks', album_id) a = q.execute() if not a: @@ -602,6 +700,7 @@ def favorite_albums(user): def _artist_loader(self): if self._needs_load(): artist = get_artist(self.ID) + artist.albums = get_albums(self.ID) self._set_from(artist) Artist.load = _artist_loader diff --git a/jamaui/__init__.py b/jamaui/__init__.py index 7e847ff..505bc11 100644 --- a/jamaui/__init__.py +++ b/jamaui/__init__.py @@ -26,6 +26,8 @@ import logging import sys LOG_FILENAME = '/tmp/jamaendo.log' -LOG_LEVEL = logging.INFO +LOG_LEVEL = logging.DEBUG + +# +logging.basicConfig(filename=LOG_FILENAME, level=LOG_LEVEL, format="%(name)-15s: [%(lineno)4d] %(levelname)-8s %(message)s") -logging.basicConfig(filename=LOG_FILENAME,level=LOG_LEVEL, format="%(name)-15s: [%(lineno)4d] %(levelname)-8s %(message)s") diff --git a/jamaui/albumlist.py b/jamaui/albumlist.py index e851cdb..ce1671a 100644 --- a/jamaui/albumlist.py +++ b/jamaui/albumlist.py @@ -66,5 +66,36 @@ class TrackList(gtk.TreeView): def get_track_id(self, path): treeiter = self.__store.get_iter(path) + _, _, _id = self.__store.get(treeiter, 0, 1, 2) + return _id + +class RadioList(gtk.TreeView): + def __init__(self): + gtk.TreeView.__init__(self) + self.__store = gtk.ListStore(str, int) + self.set_model(self.__store) + + col = gtk.TreeViewColumn('Name') + self.append_column(col) + cell = gtk.CellRendererText() + col.pack_start(cell, True) + col.add_attribute(cell, 'text', 0) + + self.set_search_column(0) + col.set_sort_column_id(0) + + def add_radio(self, radio): + self.__store.append([self.radio_name(radio), radio.ID]) + + def get_radio_id(self, path): + treeiter = self.__store.get_iter(path) _, _id = self.__store.get(treeiter, 0, 1) return _id + + def radio_name(self, radio): + if radio.idstr: + return radio.idstr.capitalize() + elif radio.name: + return radio.name + else: + return "Radio #%s" % (radio.ID) diff --git a/jamaui/favorites.py b/jamaui/favorites.py index 6eb07b6..5a0474c 100644 --- a/jamaui/favorites.py +++ b/jamaui/favorites.py @@ -69,15 +69,13 @@ class FavoritesWindow(hildon.StackableWindow): msg) banner.set_timeout(3000) - for item in settings.favorites: - try: - if isinstance(item, tuple) and len(item) == 2: - ftype, fid = item - if ftype == 'album': - add_album(fid, lambda: jamaendo.get_album(fid)) - - except jamaendo.JamendoAPIException, e: - log.exception("jamaendo.get_album(%s)"%(fid)) + favorite_albums = [f[1] for f in settings.favorites if isinstance(f, tuple) and len(f) == 2 and f[0] == 'album' and f[1] not in self.idmap] + try: + for album in jamaendo.get_albums(favorite_albums): + add_album(album.ID, lambda: album) + + except jamaendo.JamendoAPIException, e: + log.exception("jamaendo.get_albums(%s)"%(favorite_albums)) self.add(self.panarea) diff --git a/jamaui/featured.py b/jamaui/featured.py index b7b14fd..010ce23 100644 --- a/jamaui/featured.py +++ b/jamaui/featured.py @@ -72,7 +72,7 @@ class FeaturedWindow(hildon.StackableWindow): self.create_menu() def create_menu(self): - def on_player(): + def on_player(*args): from playerwindow import open_playerwindow open_playerwindow() self.menu = hildon.AppMenu() diff --git a/jamaui/player.py b/jamaui/player.py index 24ec4f2..65cc549 100644 --- a/jamaui/player.py +++ b/jamaui/player.py @@ -359,12 +359,15 @@ class Player(object): entry = self.playlist.next() self.backend.play_url('mp3', entry.mp3_url()) log.debug("playing %s", entry) + postoffice.notify('play', entry) def pause(self): self.backend.pause() + postoffice.notify('pause', self.playlist.current()) def stop(self): self.backend.stop() + postoffice.notify('stop', self.playlist.current()) def playing(self): return self.backend.playing() @@ -375,6 +378,7 @@ class Player(object): entry = self.playlist.next() self.backend.play_url('mp3', entry.mp3_url()) log.debug("playing %s", entry) + postoffice.notify('next', entry) else: self.stop() @@ -384,6 +388,7 @@ class Player(object): entry = self.playlist.prev() self.backend.play_url('mp3', entry.mp3_url()) log.debug("playing %s", entry) + postoffice.notify('prev', entry) def _on_eos(self): log.debug("EOS!") diff --git a/jamaui/playerwindow.py b/jamaui/playerwindow.py index 01df496..ce13494 100644 --- a/jamaui/playerwindow.py +++ b/jamaui/playerwindow.py @@ -24,10 +24,15 @@ import gtk import gobject import hildon +import util +import pango from settings import settings from postoffice import postoffice from player import Playlist, the_player import logging +import cgi + +from songposition import SongPosition log = logging.getLogger(__name__) @@ -43,32 +48,38 @@ class PlayerWindow(hildon.StackableWindow): vbox = gtk.VBox() - hbox = gtk.HBox() + hbox = gtk.HBox(False, 8) self.cover = gtk.Image() - self.cover.set_from_stock(gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG) + tmp = util.find_resource('album.png') + if tmp: + self.cover.set_from_file(tmp) vbox2 = gtk.VBox() self.playlist_pos = gtk.Label() + self.playlist_pos.set_alignment(1.0,0) self.track = gtk.Label() - self.progress = hildon.GtkHScale() - self.progress.set_draw_value(False) - self.progress.set_range(0.0, 1.0) + self.track.set_alignment(0,0) + self.track.set_ellipsize(pango.ELLIPSIZE_END) self.artist = gtk.Label() + self.artist.set_alignment(0,0) + self.artist.set_ellipsize(pango.ELLIPSIZE_END) self.album = gtk.Label() + self.album.set_alignment(0,0) + self.album.set_ellipsize(pango.ELLIPSIZE_END) + self.progress = SongPosition() self.set_labels('', '', '', 0, 0) self._position_timer = None - vbox2.pack_start(self.track, True) - vbox2.pack_start(self.artist, False) - vbox2.pack_start(self.album, False) vbox2.pack_start(self.playlist_pos, False) - vbox2.pack_start(self.progress, False) + vbox2.pack_start(self.track, True) + vbox2.pack_start(self.artist, True) + vbox2.pack_start(self.album, True) - hbox.pack_start(self.cover, True, True, 0) + hbox.pack_start(self.cover, False, True, 0) hbox.pack_start(vbox2, True, True, 0) vbox.pack_start(hbox, True, True, 0) @@ -76,37 +87,84 @@ class PlayerWindow(hildon.StackableWindow): btns = gtk.HButtonBox() btns.set_property('layout-style', gtk.BUTTONBOX_SPREAD) - vbox.pack_end(btns, False, True, 0) + vbox.pack_start(btns, False, True, 0) + + vbox.pack_start(self.progress, False) self.add_stock_button(btns, gtk.STOCK_MEDIA_PREVIOUS, self.on_prev) self.add_play_button(btns) self.add_stock_button(btns, gtk.STOCK_MEDIA_STOP, self.on_stop) self.add_stock_button(btns, gtk.STOCK_MEDIA_NEXT, self.on_next) - self.volume = hildon.VVolumebar() - self.volume.set_property('can-focus', False) - self.volume.connect('level_changed', self.volume_changed_hildon) - self.volume.connect('mute_toggled', self.mute_toggled) - #self.__gui_root.main_window.connect( 'key-press-event', - # self.on_key_press ) - hbox.pack_start(self.volume, False) + #self.volume = hildon.VVolumebar() + #self.volume.set_property('can-focus', False) + #self.volume.connect('level_changed', self.volume_changed_hildon) + #self.volume.connect('mute_toggled', self.mute_toggled) + #hbox.pack_start(self.volume, False) self.add(vbox) postoffice.connect('album-cover', self, self.set_album_cover) + postoffice.connect(['next', 'prev', 'play', 'pause', 'stop'], self, self.on_state_changed) #print "Created player window, playlist: %s" % (self.playlist) + self.on_state_changed() + + self.create_menu() + + def create_menu(self): + self.menu = hildon.AppMenu() + + def to_artist(*args): + import jamaendo + from showartist import ShowArtist + track = self.playlist.current() + artist = jamaendo.get_artist(int(track.artist_id)) + wnd = ShowArtist(artist) + wnd.show_all() + def to_album(*args): + import jamaendo + from showalbum import ShowAlbum + track = self.playlist.current() + album = jamaendo.get_album(int(track.album_id)) + wnd = ShowAlbum(album) + wnd.show_all() + + b = hildon.GtkButton(gtk.HILDON_SIZE_AUTO) + b.set_label("Artist") + b.connect("clicked", to_artist) + self.menu.append(b) + + b = hildon.GtkButton(gtk.HILDON_SIZE_AUTO) + b.set_label("Album") + b.connect("clicked", to_album) + self.menu.append(b) + + self.menu.show_all() + self.set_app_menu(self.menu) + + def on_state_changed(self, *args): self.update_state() self.update_play_button() + if self.player.playing(): + self.start_position_timer() + else: + self.stop_position_timer() + + def get_album_id(self): - if self.playlist and self.playlist.current_index() > -1: - return self.playlist.current().album_id + if self.player.playlist and self.player.playlist.current(): + c = self.player.playlist.current() + if not c.album_id: + c.load() + if c.album_id: + return c.album_id return None def on_destroy(self, wnd): self.stop_position_timer() - postoffice.disconnect('album-cover', self) + postoffice.disconnect(['album-cover', 'next', 'prev', 'play', 'stop'], self) def add_stock_button(self, btns, stock, cb): btn = hildon.GtkButton(gtk.HILDON_SIZE_FINGER_HEIGHT) @@ -141,10 +199,10 @@ class PlayerWindow(hildon.StackableWindow): self.playbtn.set_data('state', 'play') def set_labels(self, track, artist, album, playlist_pos, playlist_size): - self.playlist_pos.set_markup('%s/%s songs'%(playlist_pos, playlist_size)) - self.track.set_markup('%s'%(track)) - self.artist.set_markup('%s'%(artist)) - self.album.set_markup('%s'%(album)) + self.playlist_pos.set_markup('Track %s of %s'%(int(playlist_pos)+1, playlist_size)) + self.track.set_markup('%s'%(cgi.escape(track))) + self.artist.set_markup('%s'%(cgi.escape(artist))) + self.album.set_markup('%s'%(cgi.escape(album))) def volume_changed_hildon(self, widget): @@ -174,63 +232,52 @@ class PlayerWindow(hildon.StackableWindow): self._position_timer = None def clear_position(self): - self.progress.set_value(0) + self.progress.set_position(0) def set_song_position(self, time_elapsed, total_time): value = (float(time_elapsed) / float(total_time)) if total_time else 0 - self.progress.set_value( value ) + self.progress.set_position(value) def update_state(self): item = self.playlist.current() if item: if not item.name: item.load() - #print "current:", item self.set_labels(item.name, item.artist_name, item.album_name, self.playlist.current_index(), self.playlist.size()) postoffice.notify('request-album-cover', int(item.album_id), 300) - #jamaendo.get_album_cover_async(album_cover_receiver, int(item.album_id), size=200) - #coverfile = jamaendo.get_album_cover(int(item.album_id), size=200) - #print "coverfile:", coverfile - #self.cover.set_from_file(coverfile) + else: + self.set_labels('', '', '', 0, 0) + tmp = util.find_resource('album.png') + if tmp: + self.cover.set_from_file(tmp) def set_album_cover(self, albumid, size, cover): if size == 300: playing = self.get_album_id() - if int(playing) == int(albumid): + if playing and albumid and (int(playing) == int(albumid)): self.cover.set_from_file(cover) def play_tracks(self, tracks): - self.stop_position_timer() self.clear_position() self.playlist = Playlist(tracks) self.player.stop() self.player.play(self.playlist) - self.update_state() - self.update_play_button() def on_play(self, button): if not self.player.playing(): self.player.play(self.playlist) - self.start_position_timer() - self.update_state() - self.update_play_button() else: - self.stop_position_timer() self.player.pause() - self.update_state() - self.update_play_button() def on_prev(self, button): self.player.prev() - self.update_state() + def on_next(self, button): self.player.next() - self.update_state() + def on_stop(self, button): - self.stop_position_timer() self.clear_position() self.player.stop() - self.update_play_button() def open_playerwindow(): player = PlayerWindow() diff --git a/jamaui/postoffice.py b/jamaui/postoffice.py index 9453176..078316c 100644 --- a/jamaui/postoffice.py +++ b/jamaui/postoffice.py @@ -35,24 +35,26 @@ class PostOffice(object): def notify(self, tag, *data): clients = self.tags.get(tag) if clients: - #log.debug("(%s %s) -> [%s]", - # tag, - # " ".join(str(x) for x in data), - # " ".join(repr(x) for x,_ in clients)) for ref, client in clients: client(*data) def connect(self, tag, ref, callback): - if tag not in self.tags: - self.tags[tag] = [] - clients = self.tags[tag] - if callback not in clients: - clients.append((ref, callback)) + if not isinstance(tag, list): + tag = [tag] + for t in tag: + if t not in self.tags: + self.tags[t] = [] + clients = self.tags[t] + if callback not in clients: + clients.append((ref, callback)) def disconnect(self, tag, ref): - if tag not in self.tags: - self.tags[tag] = [] - self.tags[tag] = [(_ref, cb) for _ref, cb in self.tags[tag] if _ref != ref] + if not isinstance(tag, list): + tag = [tag] + for t in tag: + if t not in self.tags: + self.tags[t] = [] + self.tags[t] = [(_ref, cb) for _ref, cb in self.tags[t] if _ref != ref] postoffice = PostOffice() diff --git a/jamaui/radios.py b/jamaui/radios.py index 11c6a07..2068b82 100644 --- a/jamaui/radios.py +++ b/jamaui/radios.py @@ -25,6 +25,7 @@ import gtk import hildon import jamaendo from playerwindow import open_playerwindow +from albumlist import RadioList class RadiosWindow(hildon.StackableWindow): def __init__(self): @@ -33,39 +34,20 @@ class RadiosWindow(hildon.StackableWindow): # Results list self.panarea = hildon.PannableArea() - self.result_store = gtk.ListStore(str, int) - #self.result_store.append(['red']) - self.result_view = gtk.TreeView(self.result_store) - col = gtk.TreeViewColumn('Name') - self.result_view.append_column(col) - cell = gtk.CellRendererText() - col.pack_start(cell, True) - col.add_attribute(cell, 'text', 0) - self.result_view.set_search_column(0) - col.set_sort_column_id(0) - self.result_view.connect('row-activated', self.row_activated) + self.radiolist = RadioList() + self.radiolist.connect('row-activated', self.row_activated) - self.panarea.add(self.result_view) + self.panarea.add(self.radiolist) self.radios = {} hildon.hildon_gtk_window_set_progress_indicator(self, 1) for item in jamaendo.starred_radios(): self.radios[item.ID] = item - self.result_store.append([self.radio_text(item), item.ID]) + self.radiolist.add_radio(item) hildon.hildon_gtk_window_set_progress_indicator(self, 0) self.add(self.panarea) - def radio_text(self, radio): - if radio.name and radio.idstr: - return "%s (%s)" % (radio.name, radio.idstr) - elif radio.name: - return radio.name - elif radio.idstr: - return radio.idstr - else: - return "Radio #%s" % (radio.ID) - def make_button(self, text, subtext, callback): button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL) @@ -74,17 +56,11 @@ class RadiosWindow(hildon.StackableWindow): if callback: button.connect('clicked', callback) - #image = gtk.image_new_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON) - #button.set_image(image) - #button.set_image_position(gtk.POS_RIGHT) - return button def row_activated(self, treeview, path, view_column): - treeiter = self.result_store.get_iter(path) - title, _id = self.result_store.get(treeiter, 0, 1) + _id = self.radiolist.get_radio_id(path) item = self.radios[_id] - #print _id, item self.open_item(item) def open_item(self, item): diff --git a/jamaui/search.py b/jamaui/search.py index dd33b94..e487765 100644 --- a/jamaui/search.py +++ b/jamaui/search.py @@ -87,7 +87,7 @@ class SearchWindow(hildon.StackableWindow): self.create_menu() def create_menu(self): - def on_player(): + def on_player(*args): from playerwindow import open_playerwindow open_playerwindow() self.menu = hildon.AppMenu() diff --git a/jamaui/settings.py b/jamaui/settings.py index f141c69..04dce11 100644 --- a/jamaui/settings.py +++ b/jamaui/settings.py @@ -31,7 +31,7 @@ log = logging.getLogger(__name__) class Settings(object): defaults = { - 'volume':0.5, + 'volume':0.1, 'user':None, 'favorites':set([]) # local favorites - until we can sync back } diff --git a/jamaui/showalbum.py b/jamaui/showalbum.py index bfe6e8f..4325622 100644 --- a/jamaui/showalbum.py +++ b/jamaui/showalbum.py @@ -22,6 +22,7 @@ # (based on http://pygstdocs.berlios.de/pygst-tutorial/seeking.html) # import gtk +import cgi import hildon import jamaendo from playerwindow import open_playerwindow @@ -61,7 +62,7 @@ class ShowAlbum(hildon.StackableWindow): vbox2 = gtk.VBox() self.albumname = gtk.Label() - self.albumname.set_markup('%s'%(album.name)) + self.albumname.set_markup('%s'%(cgi.escape(album.name))) self.trackarea = hildon.PannableArea() self.tracks = TrackList(numbers=True) @@ -90,10 +91,8 @@ class ShowAlbum(hildon.StackableWindow): self.create_menu() - self.show_all() - def create_menu(self): - def on_player(): + def on_player(*args): from playerwindow import open_playerwindow open_playerwindow() self.menu = hildon.AppMenu() @@ -150,7 +149,8 @@ class ShowAlbum(hildon.StackableWindow): def row_activated(self, treeview, path, view_column): _id = self.tracks.get_track_id(path) - log.debug("clicked %s", _id) + track = jamaendo.get_track(_id) + self.open_item(track) def open_item(self, item): if isinstance(item, jamaendo.Album): diff --git a/jamaui/songposition.py b/jamaui/songposition.py new file mode 100644 index 0000000..705962c --- /dev/null +++ b/jamaui/songposition.py @@ -0,0 +1,92 @@ +import logging +import gtk +import cairo + +log = logging.getLogger(__name__) + +# shows the current song position (looking a bit nicer than a default widget, hopefully) +class SongPosition(gtk.DrawingArea): + WIDTH = 8.0 + HEIGHT = 8.0 + + def __init__(self): + gtk.DrawingArea.__init__(self) + self.connect('expose-event', self.on_expose) + self.set_size_request(24, 8) + self.pos = 0.0 + + orange0 = self.hex_to_flt(0xec, 0xac, 0x1f) + orange1 = self.hex_to_flt(0xea, 0x86, 0x1d, 0.25) + purple0 = self.hex_to_flt(0x81, 0x3e, 0x82) + purple1 = self.hex_to_flt(0x56, 0x2d, 0x5a, 0.25) + + lightclr = cairo.LinearGradient(0.0, 0.0, 0.0, self.HEIGHT) + lightclr.add_color_stop_rgba(0.0, *purple1) + lightclr.add_color_stop_rgba(1.0, *purple0) + + darkclr = cairo.LinearGradient(0.0, 0.0, 0.0, self.HEIGHT) + darkclr.add_color_stop_rgba(0.0, 0.0, 0.0, 0.0, 0.0) + darkclr.add_color_stop_rgba(1.0, 0.25, 0.25, 0.25, 1.0) + + markerclr = cairo.LinearGradient(0.0, 0.0, 0.0, self.HEIGHT) + markerclr.add_color_stop_rgba(0.0, *orange1) + markerclr.add_color_stop_rgba(0.5, *orange0) + markerclr.add_color_stop_rgba(1.0, *orange0) + + self.lightclr = lightclr + self.darkclr = darkclr + self.markerclr = markerclr + + def on_expose(self, widget, event): + context = self.window.cairo_create() + context.rectangle(event.area.x, event.area.y, + event.area.width, event.area.height) + context.clip() + self.draw(context) + return True + + #ecac1f - light orange + #ea861d - dark orange + + #813e82 - light purple + #562d5a - dark purple + + def hex_to_flt(self, r, g, b, a = 255.0): + return float(r)/255.0, float(g)/255.0, float(b)/255.0, float(a)/255.0 + + def draw(self, context): + rect = self.get_allocation() + + + #context.set_source_rgb(1.0, 0.5, 0.0) + lowx = rect.width*self.pos - self.WIDTH*0.5 + hix = rect.width*self.pos + self.WIDTH*0.5 + + if lowx < 0.0: + lowx = 0.0 + hix = self.WIDTH + elif hix > rect.width: + lowx = rect.width - self.WIDTH + hix = rect.width + + if lowx > 0.01: + context.rectangle(0, 0, lowx, rect.height) + context.set_source(self.lightclr) + context.fill() + + if hix < rect.width-0.01: + context.rectangle(hix, 0, rect.width-hix, rect.height) + context.set_source(self.darkclr) + context.fill() + + context.rectangle(lowx, 0, self.WIDTH, rect.height) + context.set_source(self.markerclr) + context.fill() + + def set_position(self, pos): + assert 0 <= pos <= 1 + self.pos = pos + self.invalidate() + + def invalidate(self): + self.queue_draw() -- 1.7.9.5