| Server IP : 182.53.201.61 / Your IP : 216.73.217.175 Web Server : Apache/2.2.15 (Fedora) System : Linux km10.dyndns.org 2.6.31.5-127.fc12.i686.PAE #1 SMP Sat Nov 7 21:25:57 EST 2009 i686 User : apache ( 48) PHP Version : 5.3.3 Disable Function : NONE MySQL : ON | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /usr/lib/rhythmbox/plugins/jamendo/ |
Upload File : |
# -*- coding: utf-8 -*-
# JamendoSource.py
#
# Copyright (C) 2007 - Guillaume Desmottes
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Parts from "Magnatune Rhythmbox plugin" (stolen from rhythmbox's MagnatuneSource.py)
# Copyright (C), 2006 Adam Zimmerman <adam_zimmerman@sfu.ca>
import rb, rhythmdb
from JamendoSaxHandler import JamendoSaxHandler
import JamendoConfigureDialog
import os
import gobject
import gtk
import gnome, gconf
import xml
import gzip
import datetime
# URIs
jamendo_song_info_uri = "http://img.jamendo.com/data/dbdump_artistalbumtrack.xml.gz"
mp32_uri = "http://api.jamendo.com/get2/bittorrent/file/plain/?type=archive&class=mp32&album_id="
ogg3_uri = "http://api.jamendo.com/get2/bittorrent/file/plain/?type=archive&class=ogg3&album_id="
# MP3s for streaming : http://api.jamendo.com/get2/stream/track/redirect/?id={TRACKID}&streamencoding=mp31
# OGGs for streaming : http://api.jamendo.com/get2/stream/track/redirect/?id={TRACKID}&streamencoding=ogg2
# .torrent file for download (MP3 archive) : http://api.jamendo.com/get2/bittorrent/file/plain/?album_id={ALBUMID}&type=archive&class=mp32
# .torrent file for download (OGG archive) : http://api.jamendo.com/get2/bittorrent/file/plain/?album_id={ALBUMID}&type=archive&class=ogg3
# Album Covers are available here: http://api.jamendo.com/get2/image/album/redirect/?id={ALBUMID}&imagesize={100-600}
artwork_url = "http://api.jamendo.com/get2/image/album/redirect/?id=%s&imagesize=200"
artist_url = "http://www.jamendo.com/get/artist/id/album/page/plain/"
class JamendoSource(rb.BrowserSource):
__gproperties__ = {
'plugin': (rb.Plugin, 'plugin', 'plugin', gobject.PARAM_WRITABLE|gobject.PARAM_CONSTRUCT_ONLY),
}
def __init__(self):
rb.BrowserSource.__init__(self, name=_("Jamendo"))
# catalogue stuff
self.__db = None
self.__saxHandler = None
self.__activated = False
self.__notify_id = 0
self.__update_id = 0
self.__info_screen = None
self.__updating = True
self.__load_current_size = 0
self.__load_total_size = 0
self.__db_load_finished = False
self.__catalogue_loader = None
self.__catalogue_check = None
self.__jamendo_dir = rb.find_user_cache_file("jamendo")
if os.path.exists(self.__jamendo_dir) is False:
os.makedirs(self.__jamendo_dir, 0700)
self.__local_catalogue_path = os.path.join(self.__jamendo_dir, "dbdump.xml")
self.__local_catalogue_temp = os.path.join(self.__jamendo_dir, "dbdump.xml.tmp")
def do_set_property(self, property, value):
if property.name == 'plugin':
self.__plugin = value
else:
raise AttributeError, 'unknown property %s' % property.name
def do_impl_get_browser_key (self):
return "/apps/rhythmbox/plugins/jamendo/show_browser"
def do_impl_get_paned_key (self):
return "/apps/rhythmbox/plugins/jamendo/paned_position"
def do_impl_pack_paned (self, paned):
self.__paned_box = gtk.VBox(False, 5)
self.pack_start(self.__paned_box)
self.__paned_box.pack_start(paned)
#
# RBSource methods
#
def do_impl_show_entry_popup(self):
self.show_source_popup ("/JamendoSourceViewPopup")
def do_impl_get_ui_actions(self):
return ["JamendoDownloadAlbum","JamendoDonateArtist"]
def do_impl_get_status(self):
if self.__updating:
if self.__load_total_size > 0:
progress = min (float(self.__load_current_size) / self.__load_total_size, 1.0)
else:
progress = -1.0
return (_("Loading Jamendo catalog"), None, progress)
else:
qm = self.get_property("query-model")
return (qm.compute_status_normal("%d song", "%d songs"), None, 0.0)
def do_impl_activate(self):
if not self.__activated:
shell = self.get_property('shell')
self.__db = shell.get_property('db')
self.__entry_type = self.get_property('entry-type')
self.__activated = True
self.__show_loading_screen (True)
# start our catalogue updates
self.__update_id = gobject.timeout_add(6 * 60 * 60 * 1000, self.__update_catalogue)
self.__update_catalogue()
sort_key = gconf.client_get_default().get_string(JamendoConfigureDialog.gconf_keys['sorting'])
if not sort_key:
sort_key = "Artist,ascending"
self.get_entry_view().set_sorting_type(sort_key)
rb.BrowserSource.do_impl_activate (self)
def do_impl_delete_thyself(self):
if self.__update_id != 0:
gobject.source_remove (self.__update_id)
self.__update_id = 0
if self.__notify_id != 0:
gobject.source_remove (self.__notify_id)
self.__notify_id = 0
if self.__catalogue_loader:
self.__catalogue_loader.cancel()
self.__catalogue_loader = None
if self.__catalogue_check:
self.__catalogue_check.cancel()
self.__catalogue_check = None
gconf.client_get_default().set_string(JamendoConfigureDialog.gconf_keys['sorting'], self.get_entry_view().get_sorting_type())
rb.BrowserSource.do_impl_delete_thyself (self)
#
# internal catalogue downloading and loading
#
def __catalogue_chunk_cb(self, result, total):
if not result or isinstance (result, Exception):
if result:
# report error somehow?
print "error loading catalogue: %s" % result
self.__parser.close()
self.__db_load_finished = True
self.__updating = False
self.__saxHandler = None
self.__show_loading_screen (False)
self.__catalogue_loader = None
return
self.__parser.feed(result)
self.__load_current_size += len(result)
self.__load_total_size = total
self.__notify_status_changed()
def __load_catalogue(self):
print "loading catalogue %s" % self.__local_catalogue_path
self.__notify_status_changed()
self.__db_load_finished = False
self.__saxHandler = JamendoSaxHandler(self.__db, self.__entry_type)
self.__parser = xml.sax.make_parser()
self.__parser.setContentHandler(self.__saxHandler)
self.__catalogue_loader = rb.ChunkLoader()
self.__catalogue_loader.get_url_chunks(self.__local_catalogue_path, 64*1024, True, self.__catalogue_chunk_cb)
def __download_catalogue_chunk_cb (self, result, total, out):
if not result:
# done downloading, unzip to real location
out.close()
catalog = gzip.open(self.__local_catalogue_temp)
out = open(self.__local_catalogue_path, 'w')
while True:
s = catalog.read(4096)
if s == "":
break
out.write(s)
out.close()
catalog.close()
os.unlink(self.__local_catalogue_temp)
self.__db_load_finished = True
self.__show_loading_screen (False)
self.__catalogue_loader = None
self.__load_catalogue ()
elif isinstance(result, Exception):
# complain
pass
else:
out.write(result)
self.__load_current_size += len(result)
self.__load_total_size = total
self.__notify_status_changed()
def __download_catalogue(self):
print "downloading catalogue"
self.__updating = True
out = open(self.__local_catalogue_temp, 'w')
self.__catalogue_loader = rb.ChunkLoader()
self.__catalogue_loader.get_url_chunks(jamendo_song_info_uri, 4*1024, True, self.__download_catalogue_chunk_cb, out)
def __update_catalogue(self):
def update_cb (result):
self.__catalogue_check = None
if result is True:
self.__download_catalogue()
elif self.__db_load_finished is False:
self.__load_catalogue()
self.__catalogue_check = rb.UpdateCheck()
self.__catalogue_check.check_for_update(self.__local_catalogue_path, jamendo_song_info_uri, update_cb)
def __show_loading_screen(self, show):
if self.__info_screen is None:
# load the builder stuff
builder = gtk.Builder()
builder.add_from_file(self.__plugin.find_file("jamendo-loading.ui"))
self.__info_screen = builder.get_object("jamendo_loading_scrolledwindow")
self.pack_start(self.__info_screen)
self.get_entry_view().set_no_show_all (True)
self.__info_screen.set_no_show_all (True)
self.__info_screen.set_property("visible", show)
self.__paned_box.set_property("visible", not show)
def __notify_status_changed(self):
def change_idle_cb():
self.notify_status_changed()
self.__notify_id = 0
return False
if self.__notify_id == 0:
self.__notify_id = gobject.idle_add(change_idle_cb)
# Download album
def download_album (self):
tracks = self.get_entry_view().get_selected_entries()
format = gconf.client_get_default().get_string(JamendoConfigureDialog.gconf_keys['format'])
if not format or format not in JamendoConfigureDialog.format_list:
format = 'ogg3'
#TODO: this should work if the album was selected in the browser
#without any track selected
if len(tracks) == 1:
track = tracks[0]
albumid = self.__db.entry_get(track, rhythmdb.PROP_MUSICBRAINZ_ALBUMID)
formats = {}
formats["mp32"] = mp32_uri + albumid
formats["ogg3"] = ogg3_uri + albumid
p2plink = formats[format]
l = rb.Loader()
l.get_url(p2plink, self.__download_p2plink, albumid)
def __download_p2plink (self, result, albumid):
if result is None:
emsg = _("Error looking up p2plink for album %s on jamendo.com") % (albumid)
gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, emsg).run()
return
rb.show_uri(result)
# Donate to Artist
def launch_donate (self):
tracks = self.get_entry_view().get_selected_entries()
#TODO: this should work if the artist was selected in the browser
#without any track selected
if len(tracks) == 1:
track = tracks[0]
# The Album ID can be used to lookup the artist, and issue a clean redirect.
albumid = self.__db.entry_get(track, rhythmdb.PROP_MUSICBRAINZ_ALBUMID)
artist = self.__db.entry_get(track, rhythmdb.PROP_ARTIST)
url = artist_url + albumid.__str__() + "/"
l = rb.Loader()
l.get_url(url, self.__open_donate, artist)
def __open_donate (self, result, artist):
if result is None:
emsg = _("Error looking up artist %s on jamendo.com") % (artist)
gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, emsg).run()
return
rb.show_uri(result + "donate/")
def playing_entry_changed (self, entry):
if not self.__db or not entry:
return
if entry.get_entry_type() != self.__db.entry_type_get_by_name("JamendoEntryType"):
return
gobject.idle_add(self.emit_cover_art_uri, entry)
def emit_cover_art_uri (self, entry):
stream = self.__db.entry_get (entry, rhythmdb.PROP_LOCATION)
albumid = self.__db.entry_get (entry, rhythmdb.PROP_MUSICBRAINZ_ALBUMID)
url = artwork_url % albumid
self.__db.emit_entry_extra_metadata_notify (entry, "rb:coverArt-uri", str(url))
return False
gobject.type_register(JamendoSource)