~ubuntu-branches/ubuntu/natty/rhythmbox/natty-proposed

« back to all changes in this revision

Viewing changes to .pc/23_no_gnome_python.patch/plugins/jamendo/jamendo/JamendoSource.py

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-12-08 21:32:48 UTC
  • Revision ID: james.westby@ubuntu.com-20101208213248-dipmvuxk0wpeb9o9
Tags: 0.13.2-0ubuntu2
* debian/control.in: 
  - don't depends on python-gnome it's not used
* debian/patches/23_no_gnome_python.patch:
  - drop the "import gnome" statements since python-gnome is not used
    in the code

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
 
 
3
# JamendoSource.py
 
4
#
 
5
# Copyright (C) 2007 - Guillaume Desmottes
 
6
#
 
7
# This program is free software; you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation; either version 2, or (at your option)
 
10
# any later version.
 
11
#
 
12
# This program is distributed in the hope that it will be useful,
 
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
# GNU General Public License for more details.
 
16
#
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with this program; if not, write to the Free Software
 
19
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
20
 
 
21
# Parts from "Magnatune Rhythmbox plugin" (stolen from rhythmbox's MagnatuneSource.py)
 
22
#     Copyright (C), 2006 Adam Zimmerman <adam_zimmerman@sfu.ca>
 
23
 
 
24
import rb, rhythmdb
 
25
from JamendoSaxHandler import JamendoSaxHandler
 
26
import JamendoConfigureDialog
 
27
 
 
28
import os
 
29
import gobject
 
30
import gtk
 
31
import gnome, gconf
 
32
import xml
 
33
import gzip
 
34
import datetime
 
35
 
 
36
# URIs
 
37
 
 
38
jamendo_song_info_uri = "http://img.jamendo.com/data/dbdump_artistalbumtrack.xml.gz"
 
39
 
 
40
mp32_uri = "http://api.jamendo.com/get2/bittorrent/file/plain/?type=archive&class=mp32&album_id="
 
41
ogg3_uri = "http://api.jamendo.com/get2/bittorrent/file/plain/?type=archive&class=ogg3&album_id="
 
42
 
 
43
 
 
44
#  MP3s for streaming : http://api.jamendo.com/get2/stream/track/redirect/?id={TRACKID}&streamencoding=mp31
 
45
# OGGs for streaming : http://api.jamendo.com/get2/stream/track/redirect/?id={TRACKID}&streamencoding=ogg2
 
46
 
 
47
# .torrent file for download (MP3 archive) : http://api.jamendo.com/get2/bittorrent/file/plain/?album_id={ALBUMID}&type=archive&class=mp32
 
48
# .torrent file for download (OGG archive) : http://api.jamendo.com/get2/bittorrent/file/plain/?album_id={ALBUMID}&type=archive&class=ogg3
 
49
 
 
50
# Album Covers are available here: http://api.jamendo.com/get2/image/album/redirect/?id={ALBUMID}&imagesize={100-600}
 
51
 
 
52
artwork_url = "http://api.jamendo.com/get2/image/album/redirect/?id=%s&imagesize=200"
 
53
artist_url = "http://www.jamendo.com/get/artist/id/album/page/plain/"
 
54
 
 
55
class JamendoSource(rb.BrowserSource):
 
56
        __gproperties__ = {
 
57
                'plugin': (rb.Plugin, 'plugin', 'plugin', gobject.PARAM_WRITABLE|gobject.PARAM_CONSTRUCT_ONLY),
 
58
        }
 
59
 
 
60
        def __init__(self):
 
61
 
 
62
                rb.BrowserSource.__init__(self, name=_("Jamendo"))
 
63
 
 
64
                # catalogue stuff
 
65
                self.__db = None
 
66
                self.__saxHandler = None
 
67
                self.__activated = False
 
68
                self.__notify_id = 0
 
69
                self.__update_id = 0
 
70
                self.__info_screen = None
 
71
                self.__updating = True
 
72
                self.__load_current_size = 0
 
73
                self.__load_total_size = 0
 
74
                self.__db_load_finished = False
 
75
 
 
76
                self.__catalogue_loader = None
 
77
                self.__catalogue_check = None
 
78
 
 
79
                self.__jamendo_dir = rb.find_user_cache_file("jamendo")
 
80
                if os.path.exists(self.__jamendo_dir) is False:
 
81
                        os.makedirs(self.__jamendo_dir, 0700)
 
82
 
 
83
                self.__local_catalogue_path = os.path.join(self.__jamendo_dir, "dbdump.xml")
 
84
                self.__local_catalogue_temp = os.path.join(self.__jamendo_dir, "dbdump.xml.tmp")
 
85
 
 
86
        def do_set_property(self, property, value):
 
87
                if property.name == 'plugin':
 
88
                        self.__plugin = value
 
89
                else:
 
90
                        raise AttributeError, 'unknown property %s' % property.name
 
91
 
 
92
        def do_impl_get_browser_key (self):
 
93
                return "/apps/rhythmbox/plugins/jamendo/show_browser"
 
94
 
 
95
        def do_impl_get_paned_key (self):
 
96
                return "/apps/rhythmbox/plugins/jamendo/paned_position"
 
97
 
 
98
        def do_impl_can_delete (self):
 
99
                return False
 
100
 
 
101
        def do_impl_pack_paned (self, paned):
 
102
                self.__paned_box = gtk.VBox(False, 5)
 
103
                self.pack_start(self.__paned_box)
 
104
                self.__paned_box.pack_start(paned)
 
105
 
 
106
        #
 
107
        # RBSource methods
 
108
        #
 
109
 
 
110
        def do_impl_show_entry_popup(self):
 
111
                self.show_source_popup ("/JamendoSourceViewPopup")
 
112
 
 
113
        def do_impl_get_ui_actions(self):
 
114
                return ["JamendoDownloadAlbum","JamendoDonateArtist"]
 
115
 
 
116
 
 
117
        def do_impl_get_status(self):
 
118
                if self.__updating:
 
119
                        if self.__load_total_size > 0:
 
120
                                progress = min (float(self.__load_current_size) / self.__load_total_size, 1.0)
 
121
                        else:
 
122
                                progress = -1.0
 
123
                        return (_("Loading Jamendo catalog"), None, progress)
 
124
                else:
 
125
                        qm = self.get_property("query-model")
 
126
                        return (qm.compute_status_normal("%d song", "%d songs"), None, 2.0)
 
127
 
 
128
        def do_impl_activate(self):
 
129
                if not self.__activated:
 
130
                        shell = self.get_property('shell')
 
131
                        self.__db = shell.get_property('db')
 
132
                        self.__entry_type = self.get_property('entry-type')
 
133
 
 
134
                        self.__activated = True
 
135
                        self.__show_loading_screen (True)
 
136
 
 
137
                        # start our catalogue updates
 
138
                        self.__update_id = gobject.timeout_add_seconds(6 * 60 * 60, self.__update_catalogue)
 
139
                        self.__update_catalogue()
 
140
 
 
141
                        sort_key = gconf.client_get_default().get_string(JamendoConfigureDialog.gconf_keys['sorting'])
 
142
                        if not sort_key:
 
143
                                sort_key = "Artist,ascending"
 
144
                        self.get_entry_view().set_sorting_type(sort_key)
 
145
 
 
146
                rb.BrowserSource.do_impl_activate (self)
 
147
 
 
148
        def do_impl_delete_thyself(self):
 
149
                if self.__update_id != 0:
 
150
                        gobject.source_remove (self.__update_id)
 
151
                        self.__update_id = 0
 
152
 
 
153
                if self.__notify_id != 0:
 
154
                        gobject.source_remove (self.__notify_id)
 
155
                        self.__notify_id = 0
 
156
 
 
157
                if self.__catalogue_loader:
 
158
                        self.__catalogue_loader.cancel()
 
159
                        self.__catalogue_loader = None
 
160
 
 
161
                if self.__catalogue_check:
 
162
                        self.__catalogue_check.cancel()
 
163
                        self.__catalogue_check = None
 
164
 
 
165
                gconf.client_get_default().set_string(JamendoConfigureDialog.gconf_keys['sorting'], self.get_entry_view().get_sorting_type())
 
166
                rb.BrowserSource.do_impl_delete_thyself (self)
 
167
 
 
168
 
 
169
        #
 
170
        # internal catalogue downloading and loading
 
171
        #
 
172
 
 
173
        def __catalogue_chunk_cb(self, result, total):
 
174
                if not result or isinstance (result, Exception):
 
175
                        if result:
 
176
                                # report error somehow?
 
177
                                print "error loading catalogue: %s" % result
 
178
 
 
179
                        self.__parser.close()
 
180
                        self.__db_load_finished = True
 
181
                        self.__updating = False
 
182
                        self.__saxHandler = None
 
183
                        self.__show_loading_screen (False)
 
184
                        self.__catalogue_loader = None
 
185
                        return
 
186
 
 
187
                self.__parser.feed(result)
 
188
                self.__load_current_size += len(result)
 
189
                self.__load_total_size = total
 
190
                self.__notify_status_changed()
 
191
 
 
192
        def __load_catalogue(self):
 
193
                print "loading catalogue %s" % self.__local_catalogue_path
 
194
                self.__notify_status_changed()
 
195
                self.__db_load_finished = False
 
196
 
 
197
                self.__saxHandler = JamendoSaxHandler(self.__db, self.__entry_type)
 
198
                self.__parser = xml.sax.make_parser()
 
199
                self.__parser.setContentHandler(self.__saxHandler)
 
200
 
 
201
                self.__catalogue_loader = rb.ChunkLoader()
 
202
                self.__catalogue_loader.get_url_chunks(self.__local_catalogue_path, 64*1024, True, self.__catalogue_chunk_cb)
 
203
 
 
204
 
 
205
        def __download_catalogue_chunk_cb (self, result, total, out):
 
206
                if not result:
 
207
                        # done downloading, unzip to real location
 
208
                        out.close()
 
209
                        catalog = gzip.open(self.__local_catalogue_temp)
 
210
                        out = open(self.__local_catalogue_path, 'w')
 
211
 
 
212
                        while True:
 
213
                                s = catalog.read(4096)
 
214
                                if s == "":
 
215
                                        break
 
216
                                out.write(s)
 
217
 
 
218
                        out.close()
 
219
                        catalog.close()
 
220
                        os.unlink(self.__local_catalogue_temp)
 
221
 
 
222
                        self.__db_load_finished = True
 
223
                        self.__show_loading_screen (False)
 
224
                        self.__catalogue_loader = None
 
225
 
 
226
                        self.__load_catalogue ()
 
227
 
 
228
                elif isinstance(result, Exception):
 
229
                        # complain
 
230
                        pass
 
231
                else:
 
232
                        out.write(result)
 
233
                        self.__load_current_size += len(result)
 
234
                        self.__load_total_size = total
 
235
 
 
236
                self.__notify_status_changed()
 
237
 
 
238
        def __download_catalogue(self):
 
239
                print "downloading catalogue"
 
240
                self.__updating = True
 
241
                out = open(self.__local_catalogue_temp, 'w')
 
242
 
 
243
                self.__catalogue_loader = rb.ChunkLoader()
 
244
                self.__catalogue_loader.get_url_chunks(jamendo_song_info_uri, 4*1024, True, self.__download_catalogue_chunk_cb, out)
 
245
 
 
246
        def __update_catalogue(self):
 
247
                def update_cb (result):
 
248
                        self.__catalogue_check = None
 
249
                        if result is True:
 
250
                                self.__download_catalogue()
 
251
                        elif self.__db_load_finished is False:
 
252
                                self.__load_catalogue()
 
253
 
 
254
                self.__catalogue_check = rb.UpdateCheck()
 
255
                self.__catalogue_check.check_for_update(self.__local_catalogue_path, jamendo_song_info_uri, update_cb)
 
256
 
 
257
 
 
258
        def __show_loading_screen(self, show):
 
259
                if self.__info_screen is None:
 
260
                        # load the builder stuff
 
261
                        builder = gtk.Builder()
 
262
                        builder.add_from_file(self.__plugin.find_file("jamendo-loading.ui"))
 
263
 
 
264
                        self.__info_screen = builder.get_object("jamendo_loading_scrolledwindow")
 
265
                        self.pack_start(self.__info_screen)
 
266
                        self.get_entry_view().set_no_show_all (True)
 
267
                        self.__info_screen.set_no_show_all (True)
 
268
 
 
269
                self.__info_screen.set_property("visible", show)
 
270
                self.__paned_box.set_property("visible", not show)
 
271
 
 
272
 
 
273
        def __notify_status_changed(self):
 
274
                def change_idle_cb():
 
275
                        self.notify_status_changed()
 
276
                        self.__notify_id = 0
 
277
                        return False
 
278
 
 
279
                if self.__notify_id == 0:
 
280
                        self.__notify_id = gobject.idle_add(change_idle_cb)
 
281
 
 
282
 
 
283
        # Download album
 
284
        def download_album (self):
 
285
                tracks = self.get_entry_view().get_selected_entries()
 
286
                format = gconf.client_get_default().get_string(JamendoConfigureDialog.gconf_keys['format'])
 
287
                if not format or format not in JamendoConfigureDialog.format_list:
 
288
                        format = 'ogg3'
 
289
 
 
290
                #TODO: this should work if the album was selected in the browser
 
291
                #without any track selected
 
292
                if len(tracks) == 1:
 
293
                        track = tracks[0]
 
294
                        albumid = self.__db.entry_get(track, rhythmdb.PROP_MUSICBRAINZ_ALBUMID)
 
295
 
 
296
                        formats = {}
 
297
                        formats["mp32"] = mp32_uri + albumid
 
298
                        formats["ogg3"] = ogg3_uri + albumid
 
299
 
 
300
                        p2plink = formats[format]
 
301
                        l = rb.Loader()
 
302
                        l.get_url(p2plink, self.__download_p2plink, albumid)
 
303
 
 
304
        def __download_p2plink (self, result, albumid):
 
305
                if result is None:
 
306
                        emsg = _("Error looking up p2plink for album %s on jamendo.com") % (albumid)
 
307
                        gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, emsg).run()
 
308
                        return
 
309
 
 
310
                gtk.show_uri(self.props.shell.props.window.get_screen(), result, gtk.gdk.CURRENT_TIME)
 
311
 
 
312
        # Donate to Artist
 
313
        def launch_donate (self):
 
314
                tracks = self.get_entry_view().get_selected_entries()
 
315
 
 
316
                #TODO: this should work if the artist was selected in the browser
 
317
                #without any track selected
 
318
                if len(tracks) == 1:
 
319
                        track = tracks[0]
 
320
                        # The Album ID can be used to lookup the artist, and issue a clean redirect.
 
321
                        albumid = self.__db.entry_get(track, rhythmdb.PROP_MUSICBRAINZ_ALBUMID)
 
322
                        artist = self.__db.entry_get(track, rhythmdb.PROP_ARTIST)
 
323
                        url = artist_url + albumid.__str__() + "/"
 
324
 
 
325
                        l = rb.Loader()
 
326
                        l.get_url(url, self.__open_donate, artist)
 
327
 
 
328
        def __open_donate (self, result, artist):
 
329
                if result is None:
 
330
                        emsg = _("Error looking up artist %s on jamendo.com") % (artist)
 
331
                        gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_OK, emsg).run()
 
332
                        return
 
333
                gtk.show_uri(self.props.shell.props.window.get_screen(), result + "donate/", gtk.gdk.CURRENT_TIME)
 
334
 
 
335
        def playing_entry_changed (self, entry):
 
336
                if not self.__db or not entry:
 
337
                        return
 
338
 
 
339
                if entry.get_entry_type() != self.__db.entry_type_get_by_name("JamendoEntryType"):
 
340
                        return
 
341
 
 
342
                gobject.idle_add(self.emit_cover_art_uri, entry)
 
343
 
 
344
        def emit_cover_art_uri (self, entry):
 
345
                stream = self.__db.entry_get (entry, rhythmdb.PROP_LOCATION)
 
346
                albumid = self.__db.entry_get (entry, rhythmdb.PROP_MUSICBRAINZ_ALBUMID)
 
347
                url = artwork_url % albumid
 
348
 
 
349
                self.__db.emit_entry_extra_metadata_notify (entry, "rb:coverArt-uri", str(url))
 
350
                return False
 
351
 
 
352
gobject.type_register(JamendoSource)
 
353