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 hildonize.set_cell_thumb_selectable(textrenderer)
31 column = gtk.TreeViewColumn("Scripture")
32 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
33 column.pack_start(textrenderer, expand=True)
34 column.add_attribute(textrenderer, "text", 1)
35 yield gobject.TYPE_STRING, column
38 windows._base.ListWindow._refresh(self)
39 self._node.get_children(
44 @misc_utils.log_exception(_moduleLogger)
45 def _on_scriptures(self, programs):
47 _moduleLogger.info("Download complete but window destroyed")
51 for programNode in programs:
52 program = programNode.get_properties()
53 row = programNode, program["title"]
54 self._model.append(row)
58 @misc_utils.log_exception(_moduleLogger)
59 def _on_error(self, exception):
61 self._errorBanner.push_message(str(exception))
63 def _window_from_node(self, node):
64 booksWindow = ScriptureBooksWindow(self._app, self._player, self._store, node)
65 booksWindow.window.set_modal(True)
66 booksWindow.window.set_transient_for(self._window)
67 booksWindow.window.set_default_size(*self._window.get_size())
68 booksWindow.connect("quit", self._on_quit)
69 booksWindow.connect("home", self._on_home)
70 booksWindow.connect("jump-to", self._on_jump)
74 @misc_utils.log_exception(_moduleLogger)
75 def _on_row_activated(self, view, path, column):
76 itr = self._model.get_iter(path)
77 node = self._model.get_value(itr, 0)
78 self._window_from_node(node)
81 gobject.type_register(ScripturesWindow)
84 class ScriptureBooksWindow(windows._base.ListWindow):
86 def __init__(self, app, player, store, node):
87 windows._base.ListWindow.__init__(self, app, player, store, node)
88 self._window.set_title(self._node.title)
91 def _get_columns(cls):
92 yield gobject.TYPE_PYOBJECT, None
94 textrenderer = gtk.CellRendererText()
95 hildonize.set_cell_thumb_selectable(textrenderer)
96 column = gtk.TreeViewColumn("Book")
97 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
98 column.pack_start(textrenderer, expand=True)
99 column.add_attribute(textrenderer, "text", 1)
100 yield gobject.TYPE_STRING, column
103 windows._base.ListWindow._refresh(self)
104 self._node.get_children(
105 self._on_scripture_books,
109 @misc_utils.log_exception(_moduleLogger)
110 def _on_scripture_books(self, programs):
111 if self._isDestroyed:
112 _moduleLogger.info("Download complete but window destroyed")
116 for programNode in programs:
117 program = programNode.get_properties()
118 row = programNode, program["title"]
119 self._model.append(row)
123 @misc_utils.log_exception(_moduleLogger)
124 def _on_error(self, exception):
126 self._errorBanner.push_message(str(exception))
128 def _window_from_node(self, node):
129 booksWindow = ScriptureChaptersWindow(self._app, self._player, self._store, node)
130 booksWindow.window.set_modal(True)
131 booksWindow.window.set_transient_for(self._window)
132 booksWindow.window.set_default_size(*self._window.get_size())
133 booksWindow.connect("quit", self._on_quit)
134 booksWindow.connect("home", self._on_home)
135 booksWindow.connect("jump-to", self._on_jump)
139 @misc_utils.log_exception(_moduleLogger)
140 def _on_row_activated(self, view, path, column):
141 itr = self._model.get_iter(path)
142 node = self._model.get_value(itr, 0)
143 self._window_from_node(node)
146 gobject.type_register(ScriptureBooksWindow)
149 class ScriptureChaptersWindow(windows._base.ListWindow):
151 def __init__(self, app, player, store, node):
152 windows._base.ListWindow.__init__(self, app, player, store, node)
153 self._window.set_title(self._node.title)
156 def _get_columns(cls):
157 yield gobject.TYPE_PYOBJECT, None
159 textrenderer = gtk.CellRendererText()
160 hildonize.set_cell_thumb_selectable(textrenderer)
161 column = gtk.TreeViewColumn("Chapter")
162 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
163 column.pack_start(textrenderer, expand=True)
164 column.add_attribute(textrenderer, "text", 1)
165 yield gobject.TYPE_STRING, column
168 windows._base.ListWindow._refresh(self)
169 self._node.get_children(
170 self._on_scripture_chapters,
174 @misc_utils.log_exception(_moduleLogger)
175 def _on_scripture_chapters(self, programs):
176 if self._isDestroyed:
177 _moduleLogger.info("Download complete but window destroyed")
181 for programNode in programs:
182 program = programNode.get_properties()
183 row = programNode, program["title"]
184 self._model.append(row)
188 @misc_utils.log_exception(_moduleLogger)
189 def _on_error(self, exception):
191 self._errorBanner.push_message(str(exception))
193 def _window_from_node(self, node):
194 booksWindow = ScriptureChapterWindow(self._app, self._player, self._store, node)
195 booksWindow.window.set_modal(True)
196 booksWindow.window.set_transient_for(self._window)
197 booksWindow.window.set_default_size(*self._window.get_size())
198 booksWindow.connect("quit", self._on_quit)
199 booksWindow.connect("home", self._on_home)
200 booksWindow.connect("jump-to", self._on_jump)
204 @misc_utils.log_exception(_moduleLogger)
205 def _on_row_activated(self, view, path, column):
206 itr = self._model.get_iter(path)
207 node = self._model.get_value(itr, 0)
208 self._window_from_node(node)
211 gobject.type_register(ScriptureChaptersWindow)
214 class ScriptureChapterWindow(windows._base.BasicWindow):
216 def __init__(self, app, player, store, node):
217 windows._base.BasicWindow.__init__(self, app, player, store)
219 self._playerNode = self._player.node
220 self._nextSearch = None
221 self._updateSeek = None
223 self.connect_auto(self._player, "state-change", self._on_player_state_change)
224 self.connect_auto(self._player, "title-change", self._on_player_title_change)
225 self.connect_auto(self._player, "error", self._on_player_error)
227 self._loadingBanner = banners.GenericBanner()
229 self._presenter = presenter.StreamPresenter(self._store)
230 self._presenter.set_context(
231 self._store.STORE_LOOKUP["scripture_background"],
235 self._presenterNavigation = presenter.NavigationBox()
236 self._presenterNavigation.toplevel.add(self._presenter.toplevel)
237 self._presenterNavigation.connect("action", self._on_nav_action)
238 self._presenterNavigation.connect("navigating", self._on_navigating)
240 self._seekbar = hildonize.create_seekbar()
241 self._seekbar.connect("change-value", self._on_user_seek)
243 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
244 self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
245 self._layout.pack_start(self._seekbar, False, False)
247 self._window.set_title(self._node.title)
250 windows._base.BasicWindow.show(self)
251 self._window.show_all()
252 self._errorBanner.toplevel.hide()
253 self._loadingBanner.toplevel.hide()
254 self._set_context(self._player.state)
257 def jump_to(self, node):
258 assert self._node is node
262 return self._playerNode is self._node
264 def _show_loading(self):
265 animationPath = self._store.STORE_LOOKUP["loading"]
266 animation = self._store.get_pixbuf_animation_from_store(animationPath)
267 self._loadingBanner.show(animation, "Loading...")
269 def _hide_loading(self):
270 self._loadingBanner.hide()
272 def _set_context(self, state):
273 if state == self._player.STATE_PLAY:
275 self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
277 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
278 elif state == self._player.STATE_PAUSE:
279 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
280 elif state == self._player.STATE_STOP:
281 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
283 _moduleLogger.info("Unhandled player state %s" % state)
285 @misc_utils.log_exception(_moduleLogger)
286 def _on_user_seek(self, widget, scroll, value):
287 self._player.seek(value / 100.0)
289 @misc_utils.log_exception(_moduleLogger)
290 def _on_player_update_seek(self):
291 if self._isDestroyed:
293 self._seekbar.set_value(self._player.percent_elapsed * 100)
296 @misc_utils.log_exception(_moduleLogger)
297 def _on_player_state_change(self, player, newState):
298 if self._active and self._player.state == self._player.STATE_PLAY:
300 assert self._updateSeek is None
301 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
302 self._updateSeek.start(seconds=1)
305 if self._updateSeek is not None:
306 self._updateSeek.cancel()
307 self._updateSeek = None
309 if not self._presenterNavigation.is_active():
310 self._set_context(newState)
312 @misc_utils.log_exception(_moduleLogger)
313 def _on_player_title_change(self, player, node):
314 if not self._active or node in [None, self._node]:
315 self._playerNode = player.node
317 self._playerNode = player.node
318 self.emit("jump-to", node)
319 self._window.destroy()
321 @misc_utils.log_exception(_moduleLogger)
322 def _on_player_error(self, player, err, debug):
323 _moduleLogger.error("%r - %r" % (err, debug))
325 @misc_utils.log_exception(_moduleLogger)
326 def _on_navigating(self, widget, navState):
327 if navState == "clicking":
328 if self._player.state == self._player.STATE_PLAY:
330 imageName = "pause_pressed"
332 imageName = "play_pressed"
333 elif self._player.state == self._player.STATE_PAUSE:
334 imageName = "play_pressed"
335 elif self._player.state == self._player.STATE_STOP:
336 imageName = "play_pressed"
338 _moduleLogger.info("Unhandled player state %s" % self._player.state)
339 elif navState == "down":
341 elif navState == "up":
342 if self._player.state == self._player.STATE_PLAY:
347 elif self._player.state == self._player.STATE_PAUSE:
349 elif self._player.state == self._player.STATE_STOP:
352 _moduleLogger.info("Unhandled player state %s" % self._player.state)
353 elif navState == "left":
355 elif navState == "right":
358 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
360 @misc_utils.log_exception(_moduleLogger)
361 def _on_nav_action(self, widget, navState):
362 self._set_context(self._player.state)
364 if navState == "clicking":
365 if self._player.state == self._player.STATE_PLAY:
369 self._player.set_piece_by_node(self._node)
371 elif self._player.state == self._player.STATE_PAUSE:
373 elif self._player.state == self._player.STATE_STOP:
374 self._player.set_piece_by_node(self._node)
377 _moduleLogger.info("Unhandled player state %s" % self._player.state)
378 elif navState == "down":
380 self._window.destroy()
381 elif navState == "up":
383 elif navState == "left":
387 assert self._nextSearch is None
388 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
389 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
390 elif navState == "right":
394 assert self._nextSearch is None
395 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
396 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
398 @misc_utils.log_exception(_moduleLogger)
399 def _on_next_node(self, node):
400 self._nextSearch = None
401 self.emit("jump-to", node)
402 self._window.destroy()
404 @misc_utils.log_exception(_moduleLogger)
405 def _on_node_search_error(self, e):
406 self._nextSearch = None
407 self._errorBanner.push_message(str(e))
410 gobject.type_register(ScriptureChapterWindow)