3 # This file is part of Jamaendo.
4 # Copyright (c) 2010 Kristoffer Gronlund
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.
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.
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/>.
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)
24 # Jamaendo jamendo.com API wrapper licensed under the New BSD License;
25 # see module for details.
33 from settings import settings
37 gobject.threads_init()
39 log = logging.getLogger(__name__)
46 if util.platform == 'maemo':
47 log.critical('Using GTK widgets, install "python2.5-hildon" '
48 'for this to work properly.')
50 log.critical('This ui (probably) only works in maemo')
51 import helldon as hildon
53 from dbus.mainloop.glib import DBusGMainLoop
55 DBusGMainLoop(set_as_default=True)
59 from postoffice import postoffice
60 from playerwindow import open_playerwindow
61 from search import SearchWindow
62 from featured import FeaturedWindow
63 from radios import RadiosWindow
64 from favorites import FavoritesWindow
65 from playlists import PlaylistsWindow
66 from listbox import ButtonListDialog
74 def create_window(self):
75 log.debug("Creating main window...")
76 self.app = hildon.Program()
77 self.window = hildon.StackableWindow()
78 self.app.add_window(self.window)
80 self.window.set_title("jamaendo")
82 self.window.connect("destroy", self.destroy)
84 self.CONFDIR = os.path.expanduser('~/MyDocs/.jamaendo')
85 jamaendo.set_cache_dir(self.CONFDIR)
86 settings.set_filename(os.path.join(self.CONFDIR, 'ui_settings'))
89 postoffice.connect('request-album-cover', self, self.on_request_cover)
90 postoffice.connect('request-images', self, self.on_request_images)
91 log.debug("Created main window.")
93 def create_menu(self):
94 self.menu = hildon.AppMenu()
96 player = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
97 player.set_label("Open player")
98 player.connect("clicked", self.on_player)
99 self.menu.append(player)
101 player = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
102 player.set_label("Favorites")
103 player.connect("clicked", self.on_favorites)
104 self.menu.append(player)
106 player = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
107 player.set_label("Playlists")
108 player.connect("clicked", self.on_playlists)
109 self.menu.append(player)
111 player = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
112 player.set_label("Settings")
113 player.connect("clicked", self.on_settings)
114 self.menu.append(player)
116 menu_about = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
117 menu_about.set_label("About")
118 menu_about.connect("clicked", self.show_about, self.window)
119 self.menu.append(menu_about)
120 gtk.about_dialog_set_url_hook(self.open_link, None)
123 self.window.set_app_menu(self.menu)
126 def setup_widgets(self):
127 bgimg = util.find_resource('bg.png')
129 background, mask = gtk.gdk.pixbuf_new_from_file(bgimg).render_pixmap_and_mask()
130 self.window.realize()
131 self.window.window.set_back_pixmap(background, False)
133 bbox = gtk.HButtonBox()
134 alignment = gtk.Alignment(xalign=0.2, yalign=0.4, xscale=1.0)
136 bbox.set_property('layout-style', gtk.BUTTONBOX_SPREAD)
138 self.window.add(alignment)
140 self.add_mainscreen_button("Featured", "Most listened to", self.on_featured)
141 self.add_mainscreen_button("Radios", "The best in free music", self.on_radios)
142 self.add_mainscreen_button("Search", "Search for artists/albums", self.on_search)
144 self.window.show_all()
146 def add_mainscreen_button(self, title, subtitle, callback):
147 btn = hildon.Button(gtk.HILDON_SIZE_THUMB_HEIGHT,
148 hildon.BUTTON_ARRANGEMENT_VERTICAL)
149 btn.set_text(title, subtitle)
150 btn.set_property('width-request', 225)
151 btn.connect('clicked', callback)
154 def on_request_cover(self, albumid, size):
155 jamaendo.get_album_cover_async(self.got_album_cover, int(albumid), size)
157 def on_request_images(self, urls):
158 jamaendo.get_images_async(self.got_images, urls)
160 def got_album_cover(self, albumid, size, cover):
161 gtk.gdk.threads_enter()
162 postoffice.notify('album-cover', albumid, size, cover)
163 gtk.gdk.threads_leave()
165 def got_images(self, images):
166 gtk.gdk.threads_enter()
167 postoffice.notify('images', images)
168 gtk.gdk.threads_leave()
170 def destroy(self, widget):
171 postoffice.disconnect(['request-album-cover', 'request-images'], self)
173 from player import the_player
178 def show_about(self, w, win):
179 dialog = gtk.AboutDialog()
180 dialog.set_program_name("jamaendo")
181 dialog.set_website("http://jamaendo.garage.maemo.org/")
182 dialog.set_website_label("http://jamaendo.garage.maemo.org/")
183 dialog.set_version(VERSION)
184 dialog.set_license("""Copyright (c) 2010, Kristoffer Gronlund
187 Redistribution and use in source and binary forms, with or without
188 modification, are permitted provided that the following conditions are met:
189 * Redistributions of source code must retain the above copyright
190 notice, this list of conditions and the following disclaimer.
191 * Redistributions in binary form must reproduce the above copyright
192 notice, this list of conditions and the following disclaimer in the
193 documentation and/or other materials provided with the distribution.
194 * Neither the name of Jamaendo nor the
195 names of its contributors may be used to endorse or promote products
196 derived from this software without specific prior written permission.
198 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
199 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
200 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
201 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
202 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
203 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
204 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
205 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
206 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
207 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
209 dialog.set_authors(("Kristoffer Gronlund <kristoffer.gronlund@purplescout.se>",
210 "Based on Panucci, written by Thomas Perl <thpinfo.com>",
211 "Icons by Joseph Wain <http://glyphish.com/>"))
212 dialog.set_comments("""Jamaendo plays music from the music catalog of JAMENDO.
214 JAMENDO is an online platform that distributes musical works under Creative Commons licenses.""")
215 gtk.about_dialog_set_email_hook(self.open_link, dialog)
216 gtk.about_dialog_set_url_hook(self.open_link, dialog)
217 dialog.connect( 'response', lambda dlg, response: dlg.destroy())
218 for parent in dialog.vbox.get_children():
219 for child in parent.get_children():
220 if isinstance(child, gtk.Label):
221 child.set_selectable(False)
222 child.set_alignment(0.0, 0.5)
226 def open_link(self, d, url, data):
228 webbrowser.open_new(url)
230 def on_featured(self, button):
231 dialog = ButtonListDialog('Featured', self.window)
232 def fn(btn, feature):
233 self.featuredwnd = FeaturedWindow(feature)
234 self.featuredwnd.show_all()
235 dialog.response(gtk.RESPONSE_OK)
236 for feature, _ in FeaturedWindow.features:
237 dialog.add_button(feature, fn, feature)
242 def on_radios(self, button):
243 self.radioswnd = RadiosWindow()
244 self.radioswnd.show_all()
246 def on_search(self, button):
247 self.searchwnd = SearchWindow()
248 self.searchwnd.show_all()
250 def on_playlists(self, button):
251 self.playlistswnd = PlaylistsWindow()
252 self.playlistswnd.show_all()
254 def on_settings(self, button):
255 dialog = gtk.Dialog()
256 dialog.set_title("Settings")
257 dialog.add_button( gtk.STOCK_OK, gtk.RESPONSE_OK )
259 hboxinner = gtk.HBox()
260 hboxinner.pack_start(gtk.Label("Username:"), False, False, 0)
261 entry = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
262 entry.set_placeholder("jamendo.com username")
264 entry.set_text(settings.user)
265 hboxinner.pack_start(entry, True, True, 0)
266 vbox.pack_start(hboxinner, True, True, 0)
268 result = dialog.run()
269 val = entry.get_text()
271 if val and result == gtk.RESPONSE_OK:
276 def on_favorites(self, button):
277 self.favoriteswnd = FavoritesWindow()
278 self.favoriteswnd.show_all()
280 def on_player(self, button):
284 ossohelper.application_init('org.jamaendo', '0.1')
288 self.window.show_all()
290 ossohelper.application_exit()
292 if __name__=="__main__":