_GET2 = '''http://api.jamendo.com/get2/'''
_MP3URL = _GET2+'stream/track/redirect/?id=%d&streamencoding=mp31'
_OGGURL = _GET2+'stream/track/redirect/?id=%d&streamencoding=ogg2'
-
+_TORRENTURL = _GET2+'bittorrent/file/redirect/?album_id=%d&type=archive&class=mp32'
def set_cache_dir(cachedir):
global _CACHEDIR
if json:
self.set_from_json(json)
+ def torrent_url(self):
+ return _TORRENTURL%(self.ID)
+
+
def _needs_load(self):
return self._needs_load_impl('name', 'image', 'artist_name', 'artist_id', 'license_url', 'tracks')
self.cond.wait()
self.cond.release()
+ multi = len(work) > 1
for albumid, size, cb in work:
cover = self._fetch_cover(albumid, size)
cb(albumid, size, cover)
+ if multi:
+ time.sleep(1.0)
class CoverCache(object):
"""
def get_async(self, albumid, size, cb):
cover = self._covers.get((albumid, size), None)
if cover:
- cb(cover)
+ cb(albumid, size, cover)
else:
self._fetcher.request_cover(albumid, size, cb)
_cover_cache = CoverCache()
-def get_album_cover(albumid, size=200):
+def get_album_cover(albumid, size=100):
return _cover_cache.get_cover(albumid, size)
-def get_album_cover_async(cb, albumid, size=200):
+def get_album_cover_async(cb, albumid, size=100):
_cover_cache.get_async(albumid, size, cb)
class CustomQuery(Query):
--- /dev/null
+import gtk
+import hildon
+import jamaendo
+from settings import settings
+from postoffice import postoffice
+import logging
+
+log = logging.getLogger(__name__)
+
+class AlbumList(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)
+
+ self.__show_artist = True
+
+ def add_album(self, album):
+ if self.__show_artist:
+ txt = "%s - %s" % (album.artist_name, album.name)
+ else:
+ txt = album.name
+ self.__store.append([txt, album.ID])
+
+ def get_album_id(self, path):
+ treeiter = self.__store.get_iter(path)
+ _, _id = self.__store.get(treeiter, 0, 1)
+ return _id
+
+ def show_artist(self, show):
+ self.__show_artist = show
+
+class TrackList(gtk.TreeView):
+ def __init__(self, numbers = True):
+ gtk.TreeView.__init__(self)
+ self.track_numbers = numbers
+ self.__store = gtk.ListStore(int, str, int)
+ self.set_model(self.__store)
+
+ if numbers:
+ col0 = gtk.TreeViewColumn('Num')
+ self.append_column(col0)
+ cell0 = gtk.CellRendererText()
+ col0.pack_start(cell0, True)
+ col0.add_attribute(cell0, 'text', 0)
+
+ col = gtk.TreeViewColumn('Name')
+ self.append_column(col)
+ cell = gtk.CellRendererText()
+ col.pack_start(cell, True)
+ col.add_attribute(cell, 'text', 1)
+
+ self.set_search_column(1 if numbers else 0)
+ col.set_sort_column_id(0)
+
+ def add_track(self, track):
+ self.__store.append([track.numalbum, track.name, track.ID])
+
+ def get_track_id(self, path):
+ treeiter = self.__store.get_iter(path)
+ _, _id = self.__store.get(treeiter, 0, 1)
+ return _id
from settings import settings
import logging
+from albumlist import AlbumList
+
log = logging.getLogger(__name__)
def _alist(l, match):
if settings.user:
# 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.panarea.add(self.result_view)
+ self.results = AlbumList()
+ self.results.connect('row-activated', self.row_activated)
+ self.panarea.add(self.results)
self.idmap = {}
+
+ def add_album(ID, album_factory):
+ if ID not in self.idmap:
+ album = album_factory()
+ self.idmap[ID] = album
+ self.results.add_album(album)
+
try:
for item in jamaendo.favorite_albums(settings.user):
- self.idmap[item.ID] = item
- self.result_store.append([self.get_item_text(item), item.ID])
+ add_album(item.ID, lambda: item)
except jamaendo.JamendoAPIException, e:
msg = "Query failed, is the user name '%s' correct?" % (settings.user)
banner = hildon.hildon_banner_show_information(self, '',
msg)
banner.set_timeout(3000)
-
- def add_album(albumid):
- album = jamaendo.get_album(albumid)
- self.idmap[albumid] = album
- self.result_store.append([self.get_item_text(album), albumid])
-
for item in settings.favorites:
try:
if isinstance(item, tuple) and len(item) == 2:
ftype, fid = item
if ftype == 'album':
- add_album(fid)
+ add_album(fid, lambda: jamaendo.get_album(fid))
except jamaendo.JamendoAPIException, e:
log.exception("jamaendo.get_album(%s)"%(fid))
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.results.get_album_id(path)
item = self.idmap[_id]
print _id, item
self.open_item(item)
import jamaendo
from settings import settings
+from postoffice import postoffice
log = logging.getLogger(__name__)
self.volume_multiplier = 1.
self.volume_property = None
self.eos_callback = lambda: self.stop()
+ postoffice.connect('settings-changed', self.on_settings_changed)
+
+ def on_settings_changed(self, key, value):
+ if key == 'volume':
+ self._set_volume_level(value)
+ #postoffice.disconnect(self.on_settings_changed)
+
def play_url(self, filetype, uri):
if None in (filetype, uri):
#
import gtk
import hildon
-import jamaendo
from settings import settings
+from postoffice import postoffice
from player import Playlist, the_player
-_player_window = None
-
-def album_cover_receiver(albumid, size, cover):
- if _player_window:
- playing = _player_window.get_album_id()
- if int(playing) == int(albumid):
- _player_window.set_album_cover(cover)
-
class PlayerWindow(hildon.StackableWindow):
def __init__(self, playlist=None):
hildon.StackableWindow.__init__(self)
self.set_title("jamaendo")
- global _player_window
- _player_window = self
-
- self.connect('hide', self.on_hide)
self.connect('destroy', self.on_destroy)
self.playlist = Playlist(playlist)
hbox = gtk.HBox()
self.cover = gtk.Image()
- self.cover.set_size_request(200, 200)
self.cover.set_from_stock(gtk.STOCK_CDROM, gtk.ICON_SIZE_DIALOG)
vbox2 = gtk.VBox()
hbox.pack_start(self.volume, False)
self.add(vbox)
+ postoffice.connect('album-cover', self.set_album_cover)
+
print "Created player window, playlist: %s" % (self.playlist)
def get_album_id(self):
return self.playlist.current().album_id
return None
- def on_hide(self, wnd):
- print "Hiding player window"
-
def on_destroy(self, wnd):
- print "Destroying player window"
- global _player_window
- _player_window = None
- if self.player:
- self.player.stop()
+ postoffice.disconnect('album-cover', self.set_album_cover)
def add_stock_button(self, btns, stock, cb):
btn = hildon.GtkButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
print "current:", item
self.set_labels(item.name, item.artist_name, item.album_name,
self.playlist.current_index(), self.playlist.size())
- jamaendo.get_album_cover_async(album_cover_receiver, int(item.album_id), size=200)
+ 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)
- def set_album_cover(self, cover):
- self.cover.set_from_file(cover)
+ def set_album_cover(self, albumid, size, cover):
+ if size == 300:
+ playing = self.get_album_id()
+ if int(playing) == int(albumid):
+ self.cover.set_from_file(cover)
def play_tracks(self, tracks):
self.playlist = Playlist(tracks)
#
# message central
+import logging
+
+log = logging.getLogger(__name__)
+
class PostOffice(object):
- class Client(object):
- def __init__(self):
- self.tags = {}
- def has_tag(self, tag):
- return tag in self.tags
- def notify(self, tags, data):
- for tag in tags:
- cb = self.tags.get(tag)
- if cb:
- cb(data)
- def register(self, tag, callback):
- self.tags[tag] = callback
def __init__(self):
- self.clients = {}
-
- def notify(self, tags, data):
- if not isinstance(tags, list):
- tags = [tags]
- for client in clients:
- client.notify(tags, data)
-
- def register(self, client_id, tag, callback):
- client = self.clients.get(client_id)
- if not client:
- client = Client()
- self.clients[client_id] = client
- client.register(tag, callback)
+ self.tags = {} # tag -> [callback]
+
+ 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(str(x) for x in clients))
+ for client in clients:
+ client(*data)
+
+ def connect(self, tag, callback):
+ if tag not in self.tags:
+ self.tags[tag] = []
+ clients = self.tags[tag]
+ if callback not in clients:
+ clients.append(callback)
+
+ def disconnect(self, tag, callback):
+ if tag not in self.tags:
+ self.tags[tag] = []
+ clients = self.tags[tag]
+ if callback in clients:
+ clients.remove(callback)
postoffice = PostOffice()
self.idmap = {}
def mode_changed(self, selector, user_data):
- current_selection = selector.get_current_text()
- print current_selection
+ pass
+ #current_selection = selector.get_current_text()
def on_search(self, w):
mode = self.mode.get_active()
treeiter = self.result_store.get_iter(path)
title, _id = self.result_store.get(treeiter, 0, 1)
item = self.idmap[_id]
- print _id, item
+ #print _id, item
self.open_item(item)
def open_item(self, item):
import cPickle, os
import logging
+from postoffice import postoffice
+
VERSION = 1
log = logging.getLogger(__name__)
for k,v in self.defaults.iteritems():
setattr(self, k, v)
+ def __setattr__(self, key, value):
+ object.__setattr__(self, key, value)
+ if key in self.defaults.keys():
+ postoffice.notify('settings-changed', key, value)
+
def set_filename(self, savename):
self.__savename = savename
import jamaendo
from playerwindow import open_playerwindow
from settings import settings
+from postoffice import postoffice
import util
+import logging
+from albumlist import TrackList
+import webbrowser
-_instance = None
-
-def album_cover_receiver(albumid, size, cover):
- if _instance:
- playing = _instance.get_album_id()
- if int(playing) == int(albumid):
- _instance.set_album_cover(cover)
+log = logging.getLogger(__name__)
class ShowAlbum(hildon.StackableWindow):
def __init__(self, album):
hildon.StackableWindow.__init__(self)
- self.set_title("Album")
+ self.set_title(album.artist_name)
self.album = album
- global _instance
- _instance = self
self.connect('destroy', self.on_destroy)
- top_vbox = gtk.VBox()
top_hbox = gtk.HBox()
vbox1 = gtk.VBox()
self.cover = gtk.Image()
self.playbtn.connect('clicked', self.on_play)
vbox2 = gtk.VBox()
- self.albumtitle = gtk.Label()
- self.albumtitle.set_markup('<big>%s</big>' % (album.name))
- self.artist = gtk.Label()
- self.artist.set_markup('<span color="#cccccc">%s</span>'%(album.artist_name))
+ self.albumname = gtk.Label()
+ self.albumname.set_markup('<big>%s</big>'%(album.name))
self.trackarea = hildon.PannableArea()
- self.album_store = gtk.ListStore(int, str, int)
- self.album_view = gtk.TreeView(self.album_store)
- col0 = gtk.TreeViewColumn('Num')
- col = gtk.TreeViewColumn('Name')
- self.album_view.append_column(col0)
- self.album_view.append_column(col)
- cell0 = gtk.CellRendererText()
- col0.pack_start(cell0, True)
- col0.add_attribute(cell0, 'text', 0)
- cell = gtk.CellRendererText()
- col.pack_start(cell, True)
- col.add_attribute(cell, 'text', 1)
- self.album_view.set_search_column(1)
- col.set_sort_column_id(0)
- self.album_view.connect('row-activated', self.row_activated)
+ self.tracks = TrackList(numbers=True)
+ self.tracks.connect('row-activated', self.row_activated)
for track in jamaendo.get_tracks(album.ID):
- self.album_store.append([track.numalbum, track.name, track.ID])
+ self.tracks.add_track(track)
- top_vbox.pack_start(self.albumtitle, False)
- top_vbox.pack_start(top_hbox)
top_hbox.pack_start(vbox1, False)
top_hbox.pack_start(vbox2, True)
vbox1.pack_start(self.cover, True)
self.bbox.add(self.download)
self.bbox.add(self.favorite)
self.bbox.add(self.license)
- vbox2.pack_start(self.artist, False)
+ vbox2.pack_start(self.albumname, False)
vbox2.pack_start(self.trackarea, True)
- self.trackarea.add(self.album_view)
+ self.trackarea.add(self.tracks)
- self.add(top_vbox)
+ self.add(top_hbox)
- # here it's probably ok to get the cover synchronously..
- coverfile = jamaendo.get_album_cover(self.album.ID, size=200)
- self.cover.set_from_file(coverfile)
+ postoffice.connect('album-cover', self.on_album_cover)
+ postoffice.notify('request-album-cover', self.album.ID, 300)
self.show_all()
def on_destroy(self, wnd):
- global _instance
- _instance = None
+ postoffice.disconnect('album-cover', self.on_album_cover)
+
+ def on_album_cover(self, albumid, size, cover):
+ if albumid == self.album.ID and size == 300:
+ self.cover.set_from_file(cover)
def make_imagebutton(self, name, cb):
btn = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
self.open_item(artist)
def on_download(self, btn):
- banner = hildon.hildon_banner_show_information(self, '', "Downloads disabled in this version")
+ banner = hildon.hildon_banner_show_information(self, '', "Opening in web browser")
banner.set_timeout(2000)
+ url = self.album.torrent_url()
+ webbrowser.open_new(url)
def on_favorite(self, btn):
settings.favorite(self.album)
def on_license(self, btn):
+ banner = hildon.hildon_banner_show_information(self, '', "Opening in web browser")
+ banner.set_timeout(2000)
url = self.album.license_url
- import webbrowser
webbrowser.open_new(url)
def on_play(self, btn):
self.open_item(self.album)
def row_activated(self, treeview, path, view_column):
- pass
+ _id = self.tracks.get_track_id(path)
+ log.debug("clicked %s", _id)
def open_item(self, item):
if isinstance(item, jamaendo.Album):
import hildon
import jamaendo
from playerwindow import open_playerwindow
+from albumlist import AlbumList
class ShowArtist(hildon.StackableWindow):
def __init__(self, artist):
hildon.StackableWindow.__init__(self)
- self.set_title("Artist")
+ self.set_title(artist.name)
self.artist = artist
self.panarea = hildon.PannableArea()
vbox = gtk.VBox(False, 0)
- name = gtk.Label()
- name.set_markup('<big>%s</big>'%(artist.name))
- vbox.pack_start(name, False)
+ self.albums = AlbumList()
+ self.albums.show_artist(False)
+ self.albums.connect('row-activated', self.row_activated)
- self.album_store = gtk.ListStore(str, int)
- self.album_view = gtk.TreeView(self.album_store)
- col = gtk.TreeViewColumn('Name')
- self.album_view.append_column(col)
- cell = gtk.CellRendererText()
- col.pack_start(cell, True)
- col.add_attribute(cell, 'text', 0)
- self.album_view.set_search_column(0)
- col.set_sort_column_id(0)
- self.album_view.connect('row-activated', self.row_activated)
-
-
- self.panarea.add(self.album_view)
+ self.panarea.add(self.albums)
vbox.pack_start(self.panarea, True, True, 0)
self.add(vbox)
for album in jamaendo.get_albums(artist.ID):
- self.album_store.append([album.name, album.ID])
+ self.albums.add_album(album)
def row_activated(self, treeview, path, view_column):
- treeiter = self.album_store.get_iter(path)
- title, _id = self.album_store.get(treeiter, 0, 1)
+ _id = self.albums.get_album_id(path)
album = jamaendo.get_album(_id)
if isinstance(album, list):
album = album[0]
import jamaendo
+from postoffice import postoffice
from playerwindow import open_playerwindow
from search import SearchWindow
from featured import FeaturedWindow
settings.set_filename(os.path.join(self.CONFDIR, 'ui_settings'))
settings.load()
+ postoffice.connect('request-album-cover', self.on_request_cover)
+
def save_settings(self):
settings.save()
btn.connect('clicked', callback)
self.bbox.add(btn)
+ def on_request_cover(self, albumid, size):
+ jamaendo.get_album_cover_async(self.got_album_cover, int(albumid), size)
+
+ def got_album_cover(self, albumid, size, cover):
+ postoffice.notify('album-cover', albumid, size, cover)
+
#def add_featured_button(self):
# self.featured_sel = hildon.TouchSelector(text=True)
# self.featured_sel.append_text("Albums of the week")
# self.bbox.add(btn)
def destroy(self, widget):
+ postoffice.disconnect('request-album-cover', self.on_request_cover)
gtk.main_quit()
def show_about(self, w, win):