Big threading update, most things are asynchronous now
[jamaendo] / jamaui / showalbum.py
1 #!/usr/bin/env python
2 #
3 # This file is part of Jamaendo.
4 # Copyright (c) 2010 Kristoffer Gronlund
5 #
6 # Jamaendo is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # Jamaendo is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Jamaendo.  If not, see <http://www.gnu.org/licenses/>.
18 #
19 # Player code heavily based on http://thpinfo.com/2008/panucci/:
20 #  A resuming media player for Podcasts and Audiobooks
21 #  Copyright (c) 2008-05-26 Thomas Perl <thpinfo.com>
22 #  (based on http://pygstdocs.berlios.de/pygst-tutorial/seeking.html)
23 #
24 import gtk
25 import cgi
26 try:
27     import hildon
28 except:
29     import helldon as hildon
30 import jamaendo
31 from player import Playlist
32 from playerwindow import open_playerwindow
33 from settings import settings
34 from postoffice import postoffice
35 import util
36 import logging
37 import thread
38 import gobject
39 from albumlist import TrackList
40 from playlists import add_to_playlist
41 from fetcher import Fetcher
42
43 import webbrowser
44
45 log = logging.getLogger(__name__)
46
47 class ShowAlbum(hildon.StackableWindow):
48     def __init__(self, album):
49         hildon.StackableWindow.__init__(self)
50         self.set_title(album.artist_name)
51         self.album = album
52         self.fetcher = None
53
54         self.connect('destroy', self.on_destroy)
55
56         top_hbox = gtk.HBox()
57         vbox1 = gtk.VBox()
58         self.cover = gtk.Image()
59         tmp = util.find_resource('album.png')
60         if tmp:
61             self.cover.set_from_file(tmp)
62         self.bbox = gtk.HButtonBox()
63         self.bbox.set_property('layout-style', gtk.BUTTONBOX_SPREAD)
64         self.goto_artist = self.make_imagebutton('artist', self.on_goto_artist)
65         self.download = self.make_imagebutton('download', self.on_download)
66         self.favorite = self.make_imagebutton('favorite', self.on_favorite)
67         self.license = self.make_imagebutton('license', self.on_license)
68
69         vbox2 = gtk.VBox()
70         self.albumname = gtk.Label()
71         self.albumname.set_markup('<big>%s</big>'%(cgi.escape(album.name)))
72         self.trackarea = hildon.PannableArea()
73
74         self.tracks = TrackList(numbers=True)
75         self.tracks.connect('row-activated', self.row_activated)
76
77         self.tracklist = []
78         #self.tracklist = jamaendo.get_tracks(album.ID)
79         #for track in self.tracklist:
80         # self.tracks.add_track(track)
81
82         top_hbox.pack_start(vbox1, False)
83         top_hbox.pack_start(vbox2, True)
84         vbox1.pack_start(self.cover, True)
85         vbox1.pack_start(self.bbox, False)
86         self.bbox.add(self.goto_artist)
87         self.bbox.add(self.download)
88         self.bbox.add(self.favorite)
89         self.bbox.add(self.license)
90         vbox2.pack_start(self.albumname, False)
91         vbox2.pack_start(self.trackarea, True)
92         self.trackarea.add(self.tracks)
93
94         self.add(top_hbox)
95
96         postoffice.connect('album-cover', self, self.on_album_cover)
97         postoffice.notify('request-album-cover', self.album.ID, 300)
98
99         self.create_menu()
100         self.start_track_fetcher()
101
102     def create_menu(self):
103         def on_player(*args):
104             from playerwindow import open_playerwindow
105             open_playerwindow()
106         self.menu = hildon.AppMenu()
107         player = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
108         player.set_label("Open player")
109         player.connect("clicked", on_player)
110         self.menu.append(player)
111         player = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
112         player.set_label("Add to playlist")
113         player.connect("clicked", self.on_add_to_playlist)
114         self.menu.append(player)
115         self.menu.show_all()
116         self.set_app_menu(self.menu)
117
118     def on_destroy(self, wnd):
119         postoffice.disconnect('album-cover', self)
120         if self.fetcher:
121             self.fetcher.stop()
122             self.fetcher = None
123
124     def start_track_fetcher(self):
125         if self.fetcher:
126             self.fetcher.stop()
127             self.fetcher = None
128         self.fetcher = Fetcher(lambda: jamaendo.get_tracks(self.album.ID), self,
129                                on_item = self.on_track_result,
130                                on_ok = self.on_track_complete,
131                                on_fail = self.on_track_complete)
132         self.fetcher.start()
133
134     def on_track_result(self, wnd, item):
135         if wnd is self:
136             self.tracklist.append(item)
137             self.tracks.add_track(item)
138
139     def on_track_complete(self, wnd, error=None):
140         if wnd is self:
141             self.fetcher.stop()
142             self.fetcher = None
143
144     def on_album_cover(self, albumid, size, cover):
145         if albumid == self.album.ID and size == 300:
146             self.cover.set_from_file(cover)
147
148
149     def on_add_to_playlist(self, button, user_data=None):
150         add_to_playlist(self, self.tracklist)
151
152     def make_imagebutton(self, name, cb):
153         btn = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
154         btn.set_relief(gtk.RELIEF_NONE)
155         img = util.find_resource('icon_%s.png'%(name))
156         if img:
157             btn.set_image(gtk.image_new_from_file(img))
158         else:
159             btn.set_image(gtk.image_new_from_stock(gtk.STOCK_MEDIA_STOP, gtk.ICON_SIZE_SMALL_TOOLBAR))
160         btn.set_border_width(0)
161         btn.connect('clicked', cb)
162         return btn
163
164     def on_goto_artist(self, btn):
165         def threadfun(wnd, artist_id):
166             try:
167                 artist = jamaendo.get_artist(artist_id)
168                 def oncomplete(wnd, artist):
169                     wnd.open_item(artist)
170                     hildon.hildon_gtk_window_set_progress_indicator(wnd, 0)
171                 gobject.idle_add(oncomplete, wnd, artist)
172             except:
173                 def onfail(wnd):
174                     hildon.hildon_gtk_window_set_progress_indicator(wnd, 0)
175                 gobject.idle_add(onfail, wnd)
176         hildon.hildon_gtk_window_set_progress_indicator(self, 1)
177         thread.start_new_thread(threadfun, (self, int(self.album.artist_id)))
178
179     def on_download(self, btn):
180         banner = hildon.hildon_banner_show_information(self, '', "Opening in web browser")
181         banner.set_timeout(2000)
182         url = self.album.torrent_url()
183         webbrowser.open_new(url)
184
185     def on_favorite(self, btn):
186         settings.favorite(self.album)
187         banner = hildon.hildon_banner_show_information(self, '', "Favorite added")
188         banner.set_timeout(2000)
189
190
191     def on_license(self, btn):
192         banner = hildon.hildon_banner_show_information(self, '', "Opening in web browser")
193         banner.set_timeout(2000)
194         url = self.album.license_url
195         webbrowser.open_new(url)
196
197     def on_play(self, btn):
198         self.open_item(self.album)
199
200     def row_activated(self, treeview, path, view_column):
201         # TODO: wait for all tracks to load
202         _id = self.tracks.get_track_id(path)
203         playlist = Playlist(self.tracklist)
204         playlist.jump_to(_id)
205         wnd = open_playerwindow()
206         wnd.play_tracks(playlist)
207
208     def open_item(self, item):
209         if isinstance(item, jamaendo.Album):
210             tracks = jamaendo.get_tracks(item.ID)
211             if tracks:
212                 wnd = open_playerwindow()
213                 wnd.play_tracks(tracks)
214         elif isinstance(item, jamaendo.Artist):
215             from showartist import ShowArtist
216             wnd = ShowArtist(item)
217             wnd.show_all()
218         elif isinstance(item, jamaendo.Track):
219             wnd = open_playerwindow()
220             wnd.play_tracks([item])