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)
75 gobject.type_register(ScripturesWindow)
78 class ScriptureBooksWindow(windows._base.ListWindow):
80 def __init__(self, app, player, store, node):
81 windows._base.ListWindow.__init__(self, app, player, store, node)
82 self._window.set_title(self._node.title)
85 def _get_columns(cls):
86 yield gobject.TYPE_PYOBJECT, None
88 textrenderer = gtk.CellRendererText()
89 hildonize.set_cell_thumb_selectable(textrenderer)
90 column = gtk.TreeViewColumn("Book")
91 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
92 column.pack_start(textrenderer, expand=True)
93 column.add_attribute(textrenderer, "text", 1)
94 yield gobject.TYPE_STRING, column
97 windows._base.ListWindow._refresh(self)
98 self._node.get_children(
99 self._on_scripture_books,
103 @misc_utils.log_exception(_moduleLogger)
104 def _on_scripture_books(self, programs):
105 if self._isDestroyed:
106 _moduleLogger.info("Download complete but window destroyed")
110 for programNode in programs:
111 program = programNode.get_properties()
112 row = programNode, program["title"]
113 self._model.append(row)
117 @misc_utils.log_exception(_moduleLogger)
118 def _on_error(self, exception):
120 self._errorBanner.push_message(str(exception))
122 def _window_from_node(self, node):
123 booksWindow = ScriptureChaptersWindow(self._app, self._player, self._store, node)
124 booksWindow.window.set_modal(True)
125 booksWindow.window.set_transient_for(self._window)
126 booksWindow.window.set_default_size(*self._window.get_size())
127 booksWindow.connect("quit", self._on_quit)
128 booksWindow.connect("home", self._on_home)
129 booksWindow.connect("jump-to", self._on_jump)
134 gobject.type_register(ScriptureBooksWindow)
137 class ScriptureChaptersWindow(windows._base.ListWindow):
139 def __init__(self, app, player, store, node):
140 windows._base.ListWindow.__init__(self, app, player, store, node)
141 self._window.set_title(self._node.title)
144 def _get_columns(cls):
145 yield gobject.TYPE_PYOBJECT, None
147 textrenderer = gtk.CellRendererText()
148 hildonize.set_cell_thumb_selectable(textrenderer)
149 column = gtk.TreeViewColumn("Chapter")
150 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
151 column.pack_start(textrenderer, expand=True)
152 column.add_attribute(textrenderer, "text", 1)
153 yield gobject.TYPE_STRING, column
156 windows._base.ListWindow._refresh(self)
157 self._node.get_children(
158 self._on_scripture_chapters,
162 @misc_utils.log_exception(_moduleLogger)
163 def _on_scripture_chapters(self, programs):
164 if self._isDestroyed:
165 _moduleLogger.info("Download complete but window destroyed")
169 for programNode in programs:
170 program = programNode.get_properties()
171 row = programNode, program["title"]
172 self._model.append(row)
176 @misc_utils.log_exception(_moduleLogger)
177 def _on_error(self, exception):
179 self._errorBanner.push_message(str(exception))
181 def _window_from_node(self, node):
182 booksWindow = ScriptureChapterWindow(self._app, self._player, self._store, node)
183 booksWindow.window.set_modal(True)
184 booksWindow.window.set_transient_for(self._window)
185 booksWindow.window.set_default_size(*self._window.get_size())
186 booksWindow.connect("quit", self._on_quit)
187 booksWindow.connect("home", self._on_home)
188 booksWindow.connect("jump-to", self._on_jump)
193 gobject.type_register(ScriptureChaptersWindow)
196 class ScriptureChapterWindow(windows._base.BasicWindow):
198 def __init__(self, app, player, store, node):
199 windows._base.BasicWindow.__init__(self, app, player, store)
201 self._playerNode = self._player.node
202 self._nextSearch = None
203 self._updateSeek = None
205 self.connect_auto(self._player, "state-change", self._on_player_state_change)
206 self.connect_auto(self._player, "title-change", self._on_player_title_change)
207 self.connect_auto(self._player, "error", self._on_player_error)
209 self._loadingBanner = banners.GenericBanner()
211 self._presenter = presenter.StreamPresenter(self._store)
212 self._presenter.set_context(
213 self._store.STORE_LOOKUP["scripture_background"],
217 self._presenterNavigation = presenter.NavigationBox()
218 self._presenterNavigation.toplevel.add(self._presenter.toplevel)
219 self._presenterNavigation.connect("action", self._on_nav_action)
220 self._presenterNavigation.connect("navigating", self._on_navigating)
222 self._seekbar = hildonize.create_seekbar()
223 self._seekbar.connect("change-value", self._on_user_seek)
225 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
226 self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
227 self._layout.pack_start(self._seekbar, False, False)
229 self._window.set_title(self._node.title)
232 windows._base.BasicWindow.show(self)
233 self._window.show_all()
234 self._errorBanner.toplevel.hide()
235 self._loadingBanner.toplevel.hide()
236 self._set_context(self._player.state)
239 def jump_to(self, node):
240 assert self._node is node
244 return self._playerNode is self._node
246 def _show_loading(self):
247 animationPath = self._store.STORE_LOOKUP["loading"]
248 animation = self._store.get_pixbuf_animation_from_store(animationPath)
249 self._loadingBanner.show(animation, "Loading...")
251 def _hide_loading(self):
252 self._loadingBanner.hide()
254 def _set_context(self, state):
255 if state == self._player.STATE_PLAY:
257 self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
259 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
260 elif state == self._player.STATE_PAUSE:
261 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
262 elif state == self._player.STATE_STOP:
263 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
265 _moduleLogger.info("Unhandled player state %s" % state)
267 @misc_utils.log_exception(_moduleLogger)
268 def _on_user_seek(self, widget, scroll, value):
269 self._player.seek(value / 100.0)
271 @misc_utils.log_exception(_moduleLogger)
272 def _on_player_update_seek(self):
273 if self._isDestroyed:
275 self._seekbar.set_value(self._player.percent_elapsed * 100)
278 @misc_utils.log_exception(_moduleLogger)
279 def _on_player_state_change(self, player, newState):
280 if self._active and self._player.state == self._player.STATE_PLAY:
282 assert self._updateSeek is None
283 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
284 self._updateSeek.start(seconds=1)
287 if self._updateSeek is not None:
288 self._updateSeek.cancel()
289 self._updateSeek = None
291 if not self._presenterNavigation.is_active():
292 self._set_context(newState)
294 @misc_utils.log_exception(_moduleLogger)
295 def _on_player_title_change(self, player, node):
296 if not self._active or node in [None, self._node]:
297 self._playerNode = player.node
299 self._playerNode = player.node
300 self.emit("jump-to", node)
301 self._window.destroy()
303 @misc_utils.log_exception(_moduleLogger)
304 def _on_player_error(self, player, err, debug):
305 _moduleLogger.error("%r - %r" % (err, debug))
307 @misc_utils.log_exception(_moduleLogger)
308 def _on_navigating(self, widget, navState):
309 if navState == "clicking":
310 if self._player.state == self._player.STATE_PLAY:
312 imageName = "pause_pressed"
314 imageName = "play_pressed"
315 elif self._player.state == self._player.STATE_PAUSE:
316 imageName = "play_pressed"
317 elif self._player.state == self._player.STATE_STOP:
318 imageName = "play_pressed"
320 _moduleLogger.info("Unhandled player state %s" % self._player.state)
321 elif navState == "down":
323 elif navState == "up":
324 if self._player.state == self._player.STATE_PLAY:
329 elif self._player.state == self._player.STATE_PAUSE:
331 elif self._player.state == self._player.STATE_STOP:
334 _moduleLogger.info("Unhandled player state %s" % self._player.state)
335 elif navState == "left":
337 elif navState == "right":
340 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
342 @misc_utils.log_exception(_moduleLogger)
343 def _on_nav_action(self, widget, navState):
344 self._set_context(self._player.state)
346 if navState == "clicking":
347 if self._player.state == self._player.STATE_PLAY:
351 self._player.set_piece_by_node(self._node)
353 elif self._player.state == self._player.STATE_PAUSE:
355 elif self._player.state == self._player.STATE_STOP:
356 self._player.set_piece_by_node(self._node)
359 _moduleLogger.info("Unhandled player state %s" % self._player.state)
360 elif navState == "down":
362 self._window.destroy()
363 elif navState == "up":
365 elif navState == "left":
369 assert self._nextSearch is None
370 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
371 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
372 elif navState == "right":
376 assert self._nextSearch is None
377 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
378 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
380 @misc_utils.log_exception(_moduleLogger)
381 def _on_next_node(self, node):
382 self._nextSearch = None
383 self.emit("jump-to", node)
384 self._window.destroy()
386 @misc_utils.log_exception(_moduleLogger)
387 def _on_node_search_error(self, e):
388 self._nextSearch = None
389 self._errorBanner.push_message(str(e))
392 gobject.type_register(ScriptureChapterWindow)