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.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
32 column.pack_start(textrenderer, expand=True)
33 column.add_attribute(textrenderer, "text", 1)
34 yield gobject.TYPE_STRING, column
37 windows._base.ListWindow._refresh(self)
38 self._node.get_children(
43 @misc_utils.log_exception(_moduleLogger)
44 def _on_scriptures(self, programs):
46 _moduleLogger.info("Download complete but window destroyed")
50 for programNode in programs:
51 program = programNode.get_properties()
52 row = programNode, program["title"]
53 self._model.append(row)
57 @misc_utils.log_exception(_moduleLogger)
58 def _on_error(self, exception):
60 self._errorBanner.push_message(str(exception))
62 def _window_from_node(self, node):
63 booksWindow = ScriptureBooksWindow(self._app, self._player, self._store, node)
64 booksWindow.window.set_modal(True)
65 booksWindow.window.set_transient_for(self._window)
66 booksWindow.window.set_default_size(*self._window.get_size())
67 booksWindow.connect("quit", self._on_quit)
68 booksWindow.connect("home", self._on_home)
69 booksWindow.connect("jump-to", self._on_jump)
73 @misc_utils.log_exception(_moduleLogger)
74 def _on_row_activated(self, view, path, column):
75 itr = self._model.get_iter(path)
76 node = self._model.get_value(itr, 0)
77 self._window_from_node(node)
80 gobject.type_register(ScripturesWindow)
83 class ScriptureBooksWindow(windows._base.ListWindow):
85 def __init__(self, app, player, store, node):
86 windows._base.ListWindow.__init__(self, app, player, store, node)
87 self._window.set_title(self._node.title)
90 def _get_columns(cls):
91 yield gobject.TYPE_PYOBJECT, None
93 textrenderer = gtk.CellRendererText()
94 column = gtk.TreeViewColumn("Book")
95 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
96 column.pack_start(textrenderer, expand=True)
97 column.add_attribute(textrenderer, "text", 1)
98 yield gobject.TYPE_STRING, column
101 windows._base.ListWindow._refresh(self)
102 self._node.get_children(
103 self._on_scripture_books,
107 @misc_utils.log_exception(_moduleLogger)
108 def _on_scripture_books(self, programs):
109 if self._isDestroyed:
110 _moduleLogger.info("Download complete but window destroyed")
114 for programNode in programs:
115 program = programNode.get_properties()
116 row = programNode, program["title"]
117 self._model.append(row)
121 @misc_utils.log_exception(_moduleLogger)
122 def _on_error(self, exception):
124 self._errorBanner.push_message(str(exception))
126 def _window_from_node(self, node):
127 booksWindow = ScriptureChaptersWindow(self._app, self._player, self._store, node)
128 booksWindow.window.set_modal(True)
129 booksWindow.window.set_transient_for(self._window)
130 booksWindow.window.set_default_size(*self._window.get_size())
131 booksWindow.connect("quit", self._on_quit)
132 booksWindow.connect("home", self._on_home)
133 booksWindow.connect("jump-to", self._on_jump)
137 @misc_utils.log_exception(_moduleLogger)
138 def _on_row_activated(self, view, path, column):
139 itr = self._model.get_iter(path)
140 node = self._model.get_value(itr, 0)
141 self._window_from_node(node)
144 gobject.type_register(ScriptureBooksWindow)
147 class ScriptureChaptersWindow(windows._base.ListWindow):
149 def __init__(self, app, player, store, node):
150 windows._base.ListWindow.__init__(self, app, player, store, node)
151 self._window.set_title(self._node.title)
154 def _get_columns(cls):
155 yield gobject.TYPE_PYOBJECT, None
157 textrenderer = gtk.CellRendererText()
158 column = gtk.TreeViewColumn("Chapter")
159 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
160 column.pack_start(textrenderer, expand=True)
161 column.add_attribute(textrenderer, "text", 1)
162 yield gobject.TYPE_STRING, column
165 windows._base.ListWindow._refresh(self)
166 self._node.get_children(
167 self._on_scripture_chapters,
171 @misc_utils.log_exception(_moduleLogger)
172 def _on_scripture_chapters(self, programs):
173 if self._isDestroyed:
174 _moduleLogger.info("Download complete but window destroyed")
178 for programNode in programs:
179 program = programNode.get_properties()
180 row = programNode, program["title"]
181 self._model.append(row)
185 @misc_utils.log_exception(_moduleLogger)
186 def _on_error(self, exception):
188 self._errorBanner.push_message(str(exception))
190 def _window_from_node(self, node):
191 booksWindow = ScriptureChapterWindow(self._app, self._player, self._store, node)
192 booksWindow.window.set_modal(True)
193 booksWindow.window.set_transient_for(self._window)
194 booksWindow.window.set_default_size(*self._window.get_size())
195 booksWindow.connect("quit", self._on_quit)
196 booksWindow.connect("home", self._on_home)
197 booksWindow.connect("jump-to", self._on_jump)
201 @misc_utils.log_exception(_moduleLogger)
202 def _on_row_activated(self, view, path, column):
203 itr = self._model.get_iter(path)
204 node = self._model.get_value(itr, 0)
205 self._window_from_node(node)
208 gobject.type_register(ScriptureChaptersWindow)
211 class ScriptureChapterWindow(windows._base.BasicWindow):
213 def __init__(self, app, player, store, node):
214 windows._base.BasicWindow.__init__(self, app, player, store)
216 self._playerNode = self._player.node
217 self._nextSearch = None
218 self._updateSeek = None
220 self.connect_auto(self._player, "state-change", self._on_player_state_change)
221 self.connect_auto(self._player, "title-change", self._on_player_title_change)
222 self.connect_auto(self._player, "error", self._on_player_error)
224 self._loadingBanner = banners.GenericBanner()
226 self._presenter = presenter.StreamPresenter(self._store)
227 self._presenter.set_context(
228 self._store.STORE_LOOKUP["scripture_background"],
232 self._presenterNavigation = presenter.NavigationBox()
233 self._presenterNavigation.toplevel.add(self._presenter.toplevel)
234 self._presenterNavigation.connect("action", self._on_nav_action)
235 self._presenterNavigation.connect("navigating", self._on_navigating)
237 self._seekbar = hildonize.create_seekbar()
238 self._seekbar.connect("change-value", self._on_user_seek)
240 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
241 self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
242 self._layout.pack_start(self._seekbar, False, False)
244 self._window.set_title(self._node.title)
247 windows._base.BasicWindow.show(self)
248 self._window.show_all()
249 self._errorBanner.toplevel.hide()
250 self._loadingBanner.toplevel.hide()
251 self._set_context(self._player.state)
254 def jump_to(self, node):
255 assert self._node is node
259 return self._playerNode is self._node
261 def _show_loading(self):
262 animationPath = self._store.STORE_LOOKUP["loading"]
263 animation = self._store.get_pixbuf_animation_from_store(animationPath)
264 self._loadingBanner.show(animation, "Loading...")
266 def _hide_loading(self):
267 self._loadingBanner.hide()
269 def _set_context(self, state):
270 if state == self._player.STATE_PLAY:
272 self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
274 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
275 elif state == self._player.STATE_PAUSE:
276 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
277 elif state == self._player.STATE_STOP:
278 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
280 _moduleLogger.info("Unhandled player state %s" % state)
282 @misc_utils.log_exception(_moduleLogger)
283 def _on_user_seek(self, widget, scroll, value):
284 self._player.seek(value / 100.0)
286 @misc_utils.log_exception(_moduleLogger)
287 def _on_player_update_seek(self):
288 if self._isDestroyed:
290 self._seekbar.set_value(self._player.percent_elapsed * 100)
293 @misc_utils.log_exception(_moduleLogger)
294 def _on_player_state_change(self, player, newState):
295 if self._active and self._player.state == self._player.STATE_PLAY:
297 assert self._updateSeek is None
298 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
299 self._updateSeek.start(seconds=1)
302 if self._updateSeek is not None:
303 self._updateSeek.cancel()
304 self._updateSeek = None
306 if not self._presenterNavigation.is_active():
307 self._set_context(newState)
309 @misc_utils.log_exception(_moduleLogger)
310 def _on_player_title_change(self, player, node):
311 if not self._active or node in [None, self._node]:
312 self._playerNode = player.node
314 self._playerNode = player.node
315 self.emit("jump-to", node)
316 self._window.destroy()
318 @misc_utils.log_exception(_moduleLogger)
319 def _on_player_error(self, player, err, debug):
320 _moduleLogger.error("%r - %r" % (err, debug))
322 @misc_utils.log_exception(_moduleLogger)
323 def _on_navigating(self, widget, navState):
324 if navState == "clicking":
325 if self._player.state == self._player.STATE_PLAY:
327 imageName = "pause_pressed"
329 imageName = "play_pressed"
330 elif self._player.state == self._player.STATE_PAUSE:
331 imageName = "play_pressed"
332 elif self._player.state == self._player.STATE_STOP:
333 imageName = "play_pressed"
335 _moduleLogger.info("Unhandled player state %s" % self._player.state)
336 elif navState == "down":
338 elif navState == "up":
339 if self._player.state == self._player.STATE_PLAY:
344 elif self._player.state == self._player.STATE_PAUSE:
346 elif self._player.state == self._player.STATE_STOP:
349 _moduleLogger.info("Unhandled player state %s" % self._player.state)
350 elif navState == "left":
352 elif navState == "right":
355 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
357 @misc_utils.log_exception(_moduleLogger)
358 def _on_nav_action(self, widget, navState):
359 self._set_context(self._player.state)
361 if navState == "clicking":
362 if self._player.state == self._player.STATE_PLAY:
366 self._player.set_piece_by_node(self._node)
368 elif self._player.state == self._player.STATE_PAUSE:
370 elif self._player.state == self._player.STATE_STOP:
371 self._player.set_piece_by_node(self._node)
374 _moduleLogger.info("Unhandled player state %s" % self._player.state)
375 elif navState == "down":
377 self._window.destroy()
378 elif navState == "up":
380 elif navState == "left":
384 assert self._nextSearch is None
385 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
386 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
387 elif navState == "right":
391 assert self._nextSearch is None
392 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
393 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
395 @misc_utils.log_exception(_moduleLogger)
396 def _on_next_node(self, node):
397 self._nextSearch = None
398 self.emit("jump-to", node)
399 self._window.destroy()
401 @misc_utils.log_exception(_moduleLogger)
402 def _on_node_search_error(self, e):
403 self._nextSearch = None
404 self._errorBanner.push_message(str(e))
407 gobject.type_register(ScriptureChapterWindow)