7 import util.go_utils as go_utils
8 import util.misc as misc_utils
16 _moduleLogger = logging.getLogger(__name__)
19 class ScripturesWindow(windows._base.ListWindow):
21 def __init__(self, app, player, store, node):
22 windows._base.ListWindow.__init__(self, app, player, store, node)
23 self._window.set_title(self._node.title)
26 def _get_columns(cls):
27 yield gobject.TYPE_PYOBJECT, None
29 textrenderer = gtk.CellRendererText()
30 column = gtk.TreeViewColumn("Scripture")
31 column.pack_start(textrenderer, expand=True)
32 column.add_attribute(textrenderer, "text", 1)
33 yield gobject.TYPE_STRING, column
36 windows._base.ListWindow._refresh(self)
37 self._node.get_children(
42 @misc_utils.log_exception(_moduleLogger)
43 def _on_scriptures(self, programs):
45 _moduleLogger.info("Download complete but window destroyed")
49 for programNode in programs:
50 program = programNode.get_properties()
51 row = programNode, program["title"]
52 self._model.append(row)
56 @misc_utils.log_exception(_moduleLogger)
57 def _on_error(self, exception):
59 self._errorBanner.push_message(str(exception))
61 def _window_from_node(self, node):
62 booksWindow = ScriptureBooksWindow(self._app, self._player, self._store, node)
63 booksWindow.window.set_modal(True)
64 booksWindow.window.set_transient_for(self._window)
65 booksWindow.window.set_default_size(*self._window.get_size())
66 booksWindow.connect("quit", self._on_quit)
67 booksWindow.connect("home", self._on_home)
68 booksWindow.connect("jump-to", self._on_jump)
72 @misc_utils.log_exception(_moduleLogger)
73 def _on_row_activated(self, view, path, column):
74 itr = self._model.get_iter(path)
75 node = self._model.get_value(itr, 0)
76 self._window_from_node(node)
79 gobject.type_register(ScripturesWindow)
82 class ScriptureBooksWindow(windows._base.ListWindow):
84 def __init__(self, app, player, store, node):
85 windows._base.ListWindow.__init__(self, app, player, store, node)
86 self._window.set_title(self._node.title)
89 def _get_columns(cls):
90 yield gobject.TYPE_PYOBJECT, None
92 textrenderer = gtk.CellRendererText()
93 column = gtk.TreeViewColumn("Book")
94 column.pack_start(textrenderer, expand=True)
95 column.add_attribute(textrenderer, "text", 1)
96 yield gobject.TYPE_STRING, column
99 windows._base.ListWindow._refresh(self)
100 self._node.get_children(
101 self._on_scripture_books,
105 @misc_utils.log_exception(_moduleLogger)
106 def _on_scripture_books(self, programs):
107 if self._isDestroyed:
108 _moduleLogger.info("Download complete but window destroyed")
112 for programNode in programs:
113 program = programNode.get_properties()
114 row = programNode, program["title"]
115 self._model.append(row)
119 @misc_utils.log_exception(_moduleLogger)
120 def _on_error(self, exception):
122 self._errorBanner.push_message(str(exception))
124 def _window_from_node(self, node):
125 booksWindow = ScriptureChaptersWindow(self._app, self._player, self._store, node)
126 booksWindow.window.set_modal(True)
127 booksWindow.window.set_transient_for(self._window)
128 booksWindow.window.set_default_size(*self._window.get_size())
129 booksWindow.connect("quit", self._on_quit)
130 booksWindow.connect("home", self._on_home)
131 booksWindow.connect("jump-to", self._on_jump)
135 @misc_utils.log_exception(_moduleLogger)
136 def _on_row_activated(self, view, path, column):
137 itr = self._model.get_iter(path)
138 node = self._model.get_value(itr, 0)
139 self._window_from_node(node)
142 gobject.type_register(ScriptureBooksWindow)
145 class ScriptureChaptersWindow(windows._base.ListWindow):
147 def __init__(self, app, player, store, node):
148 windows._base.ListWindow.__init__(self, app, player, store, node)
149 self._window.set_title(self._node.title)
152 def _get_columns(cls):
153 yield gobject.TYPE_PYOBJECT, None
155 textrenderer = gtk.CellRendererText()
156 column = gtk.TreeViewColumn("Chapter")
157 column.pack_start(textrenderer, expand=True)
158 column.add_attribute(textrenderer, "text", 1)
159 yield gobject.TYPE_STRING, column
162 windows._base.ListWindow._refresh(self)
163 self._node.get_children(
164 self._on_scripture_chapters,
168 @misc_utils.log_exception(_moduleLogger)
169 def _on_scripture_chapters(self, programs):
170 if self._isDestroyed:
171 _moduleLogger.info("Download complete but window destroyed")
175 for programNode in programs:
176 program = programNode.get_properties()
177 row = programNode, program["title"]
178 self._model.append(row)
182 @misc_utils.log_exception(_moduleLogger)
183 def _on_error(self, exception):
185 self._errorBanner.push_message(str(exception))
187 def _window_from_node(self, node):
188 booksWindow = ScriptureChapterWindow(self._app, self._player, self._store, node)
189 booksWindow.window.set_modal(True)
190 booksWindow.window.set_transient_for(self._window)
191 booksWindow.window.set_default_size(*self._window.get_size())
192 booksWindow.connect("quit", self._on_quit)
193 booksWindow.connect("home", self._on_home)
194 booksWindow.connect("jump-to", self._on_jump)
198 @misc_utils.log_exception(_moduleLogger)
199 def _on_row_activated(self, view, path, column):
200 itr = self._model.get_iter(path)
201 node = self._model.get_value(itr, 0)
202 self._window_from_node(node)
205 gobject.type_register(ScriptureChaptersWindow)
208 class ScriptureChapterWindow(windows._base.BasicWindow):
210 def __init__(self, app, player, store, node):
211 windows._base.BasicWindow.__init__(self, app, player, store)
213 self._playerNode = self._player.node
214 self._nextSearch = None
215 self._updateSeek = None
217 self.connect_auto(self._player, "state-change", self._on_player_state_change)
218 self.connect_auto(self._player, "title-change", self._on_player_title_change)
219 self.connect_auto(self._player, "error", self._on_player_error)
221 self._loadingBanner = banners.GenericBanner()
223 self._presenter = presenter.StreamPresenter(self._store)
224 self._presenter.set_context(
225 self._store.STORE_LOOKUP["scripture_background"],
229 self._presenterNavigation = presenter.NavigationBox()
230 self._presenterNavigation.toplevel.add(self._presenter.toplevel)
231 self._presenterNavigation.connect("action", self._on_nav_action)
232 self._presenterNavigation.connect("navigating", self._on_navigating)
234 self._seekbar = hildonize.create_seekbar()
235 self._seekbar.connect("change-value", self._on_user_seek)
237 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
238 self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
239 self._layout.pack_start(self._seekbar, False, False)
241 self._window.set_title(self._node.title)
244 windows._base.BasicWindow.show(self)
245 self._window.show_all()
246 self._errorBanner.toplevel.hide()
247 self._loadingBanner.toplevel.hide()
248 self._set_context(self._player.state)
251 def jump_to(self, node):
252 assert self._node is node
256 return self._playerNode is self._node
258 def _show_loading(self):
259 animationPath = self._store.STORE_LOOKUP["loading"]
260 animation = self._store.get_pixbuf_animation_from_store(animationPath)
261 self._loadingBanner.show(animation, "Loading...")
263 def _hide_loading(self):
264 self._loadingBanner.hide()
266 def _set_context(self, state):
267 if state == self._player.STATE_PLAY:
269 self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
271 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
272 elif state == self._player.STATE_PAUSE:
273 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
274 elif state == self._player.STATE_STOP:
275 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
277 _moduleLogger.info("Unhandled player state %s" % state)
279 @misc_utils.log_exception(_moduleLogger)
280 def _on_user_seek(self, widget, scroll, value):
281 self._player.seek(value / 100.0)
283 @misc_utils.log_exception(_moduleLogger)
284 def _on_player_update_seek(self):
285 if self._isDestroyed:
287 self._seekbar.set_value(self._player.percent_elapsed * 100)
290 @misc_utils.log_exception(_moduleLogger)
291 def _on_player_state_change(self, player, newState):
292 if self._active and self._player.state == self._player.STATE_PLAY:
294 assert self._updateSeek is None
295 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
296 self._updateSeek.start(seconds=1)
299 if self._updateSeek is not None:
300 self._updateSeek.cancel()
301 self._updateSeek = None
303 if not self._presenterNavigation.is_active():
304 self._set_context(newState)
306 @misc_utils.log_exception(_moduleLogger)
307 def _on_player_title_change(self, player, node):
308 if not self._active or node in [None, self._node]:
309 self._playerNode = player.node
311 self._playerNode = player.node
312 self.emit("jump-to", node)
313 self._window.destroy()
315 @misc_utils.log_exception(_moduleLogger)
316 def _on_player_error(self, player, err, debug):
317 _moduleLogger.error("%r - %r" % (err, debug))
319 @misc_utils.log_exception(_moduleLogger)
320 def _on_navigating(self, widget, navState):
321 if navState == "clicking":
322 if self._player.state == self._player.STATE_PLAY:
324 imageName = "pause_pressed"
326 imageName = "play_pressed"
327 elif self._player.state == self._player.STATE_PAUSE:
328 imageName = "play_pressed"
329 elif self._player.state == self._player.STATE_STOP:
330 imageName = "play_pressed"
332 _moduleLogger.info("Unhandled player state %s" % self._player.state)
333 elif navState == "down":
335 elif navState == "up":
336 if self._player.state == self._player.STATE_PLAY:
341 elif self._player.state == self._player.STATE_PAUSE:
343 elif self._player.state == self._player.STATE_STOP:
346 _moduleLogger.info("Unhandled player state %s" % self._player.state)
347 elif navState == "left":
349 elif navState == "right":
352 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
354 @misc_utils.log_exception(_moduleLogger)
355 def _on_nav_action(self, widget, navState):
356 self._set_context(self._player.state)
358 if navState == "clicking":
359 if self._player.state == self._player.STATE_PLAY:
363 self._player.set_piece_by_node(self._node)
365 elif self._player.state == self._player.STATE_PAUSE:
367 elif self._player.state == self._player.STATE_STOP:
368 self._player.set_piece_by_node(self._node)
371 _moduleLogger.info("Unhandled player state %s" % self._player.state)
372 elif navState == "down":
374 self._window.destroy()
375 elif navState == "up":
377 elif navState == "left":
381 assert self._nextSearch is None
382 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
383 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
384 elif navState == "right":
388 assert self._nextSearch is None
389 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
390 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
392 @misc_utils.log_exception(_moduleLogger)
393 def _on_next_node(self, node):
394 self._nextSearch = None
395 self.emit("jump-to", node)
396 self._window.destroy()
398 @misc_utils.log_exception(_moduleLogger)
399 def _on_node_search_error(self, e):
400 self._nextSearch = None
401 self._errorBanner.push_message(str(e))
404 gobject.type_register(ScriptureChapterWindow)