7 import util.go_utils as go_utils
8 import util.misc as misc_utils
16 _moduleLogger = logging.getLogger(__name__)
19 class MagazinesWindow(windows._base.ListWindow):
21 def __init__(self, player, store, node):
22 windows._base.ListWindow.__init__(self, player, store, node)
23 self._window.set_title(self._node.title)
26 def _get_columns(cls):
27 yield gobject.TYPE_PYOBJECT, None
29 pixrenderer = gtk.CellRendererPixbuf()
30 column = gtk.TreeViewColumn("Covers")
31 column.pack_start(pixrenderer, expand=True)
32 column.add_attribute(pixrenderer, "pixbuf", 1)
33 yield gobject.TYPE_OBJECT, column
35 textrenderer = gtk.CellRendererText()
36 column = gtk.TreeViewColumn("Magazine")
37 column.pack_start(textrenderer, expand=True)
38 column.add_attribute(textrenderer, "text", 2)
39 yield gobject.TYPE_STRING, column
42 windows._base.ListWindow._refresh(self)
43 self._node.get_children(
48 @misc_utils.log_exception(_moduleLogger)
49 def _on_magazines(self, programs):
51 _moduleLogger.info("Download complete but window destroyed")
55 for programNode in programs:
56 program = programNode.get_properties()
57 img = self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["nomagazineimage"])
58 row = programNode, img, program["title"]
59 self._model.append(row)
63 @misc_utils.log_exception(_moduleLogger)
64 def _on_error(self, exception):
66 self._errorBanner.push_message(str(exception))
68 def _window_from_node(self, node):
69 issuesWindow = MagazineIssuesWindow(self._player, self._store, node)
70 issuesWindow.window.set_modal(True)
71 issuesWindow.window.set_transient_for(self._window)
72 issuesWindow.window.set_default_size(*self._window.get_size())
73 issuesWindow.connect("quit", self._on_quit)
74 issuesWindow.connect("home", self._on_home)
75 issuesWindow.connect("jump-to", self._on_jump)
79 @misc_utils.log_exception(_moduleLogger)
80 def _on_row_activated(self, view, path, column):
81 itr = self._model.get_iter(path)
82 node = self._model.get_value(itr, 0)
83 self._window_from_node(node)
86 gobject.type_register(MagazinesWindow)
89 class MagazineIssuesWindow(windows._base.ListWindow):
91 def __init__(self, player, store, node):
92 windows._base.ListWindow.__init__(self, player, store, node)
93 self._window.set_title(self._node.title)
96 def _get_columns(cls):
97 yield gobject.TYPE_PYOBJECT, None
99 pixrenderer = gtk.CellRendererPixbuf()
100 column = gtk.TreeViewColumn("Covers")
101 column.pack_start(pixrenderer, expand=True)
102 column.add_attribute(pixrenderer, "pixbuf", 1)
103 yield gobject.TYPE_OBJECT, column
105 textrenderer = gtk.CellRendererText()
106 column = gtk.TreeViewColumn("Issue")
107 column.pack_start(textrenderer, expand=True)
108 column.add_attribute(textrenderer, "text", 2)
109 yield gobject.TYPE_STRING, column
112 windows._base.ListWindow._refresh(self)
113 self._node.get_children(
114 self._on_magazine_issues,
118 @misc_utils.log_exception(_moduleLogger)
119 def _on_magazine_issues(self, programs):
120 if self._isDestroyed:
121 _moduleLogger.info("Download complete but window destroyed")
125 for programNode in programs:
126 program = programNode.get_properties()
127 img = self._store.get_pixbuf_from_store(self._store.STORE_LOOKUP["nomagazineimage"])
128 row = programNode, img, program["title"]
129 self._model.append(row)
133 @misc_utils.log_exception(_moduleLogger)
134 def _on_error(self, exception):
136 self._errorBanner.push_message(str(exception))
138 def _window_from_node(self, node):
139 issuesWindow = MagazineArticlesWindow(self._player, self._store, node)
140 issuesWindow.window.set_modal(True)
141 issuesWindow.window.set_transient_for(self._window)
142 issuesWindow.window.set_default_size(*self._window.get_size())
143 issuesWindow.connect("quit", self._on_quit)
144 issuesWindow.connect("home", self._on_home)
145 issuesWindow.connect("jump-to", self._on_jump)
149 @misc_utils.log_exception(_moduleLogger)
150 def _on_row_activated(self, view, path, column):
151 itr = self._model.get_iter(path)
152 node = self._model.get_value(itr, 0)
153 self._window_from_node(node)
156 gobject.type_register(MagazineIssuesWindow)
159 class MagazineArticlesWindow(windows._base.ListWindow):
161 def __init__(self, player, store, node):
162 windows._base.ListWindow.__init__(self, player, store, node)
163 self._window.set_title(self._node.title)
166 def _get_columns(cls):
167 yield gobject.TYPE_PYOBJECT, None
169 textrenderer = gtk.CellRendererText()
170 column = gtk.TreeViewColumn("Article")
171 column.pack_start(textrenderer, expand=True)
172 column.add_attribute(textrenderer, "text", 1)
173 yield gobject.TYPE_STRING, column
176 windows._base.ListWindow._refresh(self)
177 self._node.get_children(
178 self._on_magazine_articles,
182 @misc_utils.log_exception(_moduleLogger)
183 def _on_magazine_articles(self, programs):
184 if self._isDestroyed:
185 _moduleLogger.info("Download complete but window destroyed")
189 for programNode in programs:
190 program = programNode.get_properties()
191 row = programNode, "%s\n%s" % (program["title"], program["author"])
192 self._model.append(row)
196 @misc_utils.log_exception(_moduleLogger)
197 def _on_error(self, exception):
199 self._errorBanner.push_message(str(exception))
201 def _window_from_node(self, node):
202 issuesWindow = MagazineArticleWindow(self._player, self._store, node)
203 issuesWindow.window.set_modal(True)
204 issuesWindow.window.set_transient_for(self._window)
205 issuesWindow.window.set_default_size(*self._window.get_size())
206 issuesWindow.connect("quit", self._on_quit)
207 issuesWindow.connect("home", self._on_home)
208 issuesWindow.connect("jump-to", self._on_jump)
212 @misc_utils.log_exception(_moduleLogger)
213 def _on_row_activated(self, view, path, column):
214 itr = self._model.get_iter(path)
215 node = self._model.get_value(itr, 0)
216 self._window_from_node(node)
219 gobject.type_register(MagazineArticlesWindow)
222 class MagazineArticleWindow(windows._base.BasicWindow):
224 def __init__(self, player, store, node):
225 windows._base.BasicWindow.__init__(self, player, store)
227 self._playerNode = self._player.node
228 self._nextSearch = None
229 self._updateSeek = None
231 self.connect_auto(self._player, "state-change", self._on_player_state_change)
232 self.connect_auto(self._player, "title-change", self._on_player_title_change)
233 self.connect_auto(self._player, "error", self._on_player_error)
235 self._loadingBanner = banners.GenericBanner()
237 self._presenter = presenter.StreamPresenter(self._store)
238 self._presenter.set_context(
239 self._store.STORE_LOOKUP["magazine_background"],
243 self._presenterNavigation = presenter.NavigationBox()
244 self._presenterNavigation.toplevel.add(self._presenter.toplevel)
245 self._presenterNavigation.connect("action", self._on_nav_action)
246 self._presenterNavigation.connect("navigating", self._on_navigating)
248 self._seekbar = hildonize.create_seekbar()
249 self._seekbar.connect("change-value", self._on_user_seek)
251 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
252 self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
253 self._layout.pack_start(self._seekbar, False, False)
255 self._window.set_title(self._node.title)
258 windows._base.BasicWindow.show(self)
259 self._window.show_all()
260 self._errorBanner.toplevel.hide()
261 self._loadingBanner.toplevel.hide()
262 self._set_context(self._player.state)
265 def jump_to(self, node):
266 assert self._node is node
270 return self._playerNode is self._node
272 def _show_loading(self):
273 animationPath = self._store.STORE_LOOKUP["loading"]
274 animation = self._store.get_pixbuf_animation_from_store(animationPath)
275 self._loadingBanner.show(animation, "Loading...")
277 def _hide_loading(self):
278 self._loadingBanner.hide()
280 def _set_context(self, state):
281 if state == self._player.STATE_PLAY:
283 self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
285 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
286 elif state == self._player.STATE_PAUSE:
287 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
288 elif state == self._player.STATE_STOP:
289 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
291 _moduleLogger.info("Unhandled player state %s" % state)
293 @misc_utils.log_exception(_moduleLogger)
294 def _on_user_seek(self, widget, scroll, value):
295 self._player.seek(value / 100.0)
297 @misc_utils.log_exception(_moduleLogger)
298 def _on_player_update_seek(self):
299 self._seekbar.set_value(self._player.percent_elapsed * 100)
300 return True if not self._isDestroyed else False
302 @misc_utils.log_exception(_moduleLogger)
303 def _on_player_state_change(self, player, newState):
304 if self._active and self._player.state == self._player.STATE_PLAY:
306 assert self._updateSeek is None
307 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
308 self._updateSeek.start(seconds=1)
311 self._updateSeek.cancel()
312 self._updateSeek = None
314 if not self._presenterNavigation.is_active():
315 self._set_context(newState)
317 @misc_utils.log_exception(_moduleLogger)
318 def _on_player_title_change(self, player, node):
319 if not self._active or node in [None, self._node]:
320 self._playerNode = player.node
322 self._playerNode = player.node
323 self.emit("jump-to", node)
324 self._window.destroy()
326 @misc_utils.log_exception(_moduleLogger)
327 def _on_player_error(self, player, err, debug):
328 _moduleLogger.error("%r - %r" % (err, debug))
330 @misc_utils.log_exception(_moduleLogger)
331 def _on_navigating(self, widget, navState):
332 if navState == "clicking":
333 if self._player.state == self._player.STATE_PLAY:
335 imageName = "pause_pressed"
337 imageName = "play_pressed"
338 elif self._player.state == self._player.STATE_PAUSE:
339 imageName = "play_pressed"
340 elif self._player.state == self._player.STATE_STOP:
341 imageName = "play_pressed"
343 _moduleLogger.info("Unhandled player state %s" % self._player.state)
344 elif navState == "down":
346 elif navState == "up":
347 if self._player.state == self._player.STATE_PLAY:
352 elif self._player.state == self._player.STATE_PAUSE:
354 elif self._player.state == self._player.STATE_STOP:
357 _moduleLogger.info("Unhandled player state %s" % self._player.state)
358 elif navState == "left":
360 elif navState == "right":
363 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
365 @misc_utils.log_exception(_moduleLogger)
366 def _on_nav_action(self, widget, navState):
367 self._set_context(self._player.state)
369 if navState == "clicking":
370 if self._player.state == self._player.STATE_PLAY:
374 self._player.set_piece_by_node(self._node)
376 elif self._player.state == self._player.STATE_PAUSE:
378 elif self._player.state == self._player.STATE_STOP:
379 self._player.set_piece_by_node(self._node)
382 _moduleLogger.info("Unhandled player state %s" % self._player.state)
383 elif navState == "down":
385 self._window.destroy()
386 elif navState == "up":
388 elif navState == "left":
392 assert self._nextSearch is None
393 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
394 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
395 elif navState == "right":
399 assert self._nextSearch is None
400 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
401 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
403 @misc_utils.log_exception(_moduleLogger)
404 def _on_next_node(self, node):
405 self._nextSearch = None
406 self.emit("jump-to", node)
407 self._window.destroy()
409 @misc_utils.log_exception(_moduleLogger)
410 def _on_node_search_error(self, e):
411 self._nextSearch = None
412 self._errorBanner.push_message(str(e))
415 gobject.type_register(MagazineArticleWindow)