7 import util.go_utils as go_utils
8 import util.misc as misc_utils
16 _moduleLogger = logging.getLogger(__name__)
19 class ConferencesWindow(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("Date")
31 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
32 column.set_property("fixed-width", 96)
33 column.pack_start(textrenderer, expand=True)
34 column.add_attribute(textrenderer, "text", 1)
35 yield gobject.TYPE_STRING, column
37 textrenderer = gtk.CellRendererText()
38 hildonize.set_cell_thumb_selectable(textrenderer)
39 column = gtk.TreeViewColumn("Conference")
40 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
41 column.pack_start(textrenderer, expand=True)
42 column.add_attribute(textrenderer, "text", 2)
43 yield gobject.TYPE_STRING, column
46 windows._base.ListWindow._refresh(self)
47 self._node.get_children(
52 @misc_utils.log_exception(_moduleLogger)
53 def _on_conferences(self, programs):
55 _moduleLogger.info("Download complete but window destroyed")
59 for programNode in programs:
60 program = programNode.get_properties()
61 row = programNode, program["title"], program["full_title"]
62 self._model.append(row)
66 @misc_utils.log_exception(_moduleLogger)
67 def _on_error(self, exception):
69 self._errorBanner.push_message(str(exception))
71 def _window_from_node(self, node):
72 sessionsWindow = ConferenceSessionsWindow(self._app, self._player, self._store, node)
73 sessionsWindow.window.set_modal(True)
74 sessionsWindow.window.set_transient_for(self._window)
75 sessionsWindow.window.set_default_size(*self._window.get_size())
76 sessionsWindow.connect("quit", self._on_quit)
77 sessionsWindow.connect("home", self._on_home)
78 sessionsWindow.connect("jump-to", self._on_jump)
82 @misc_utils.log_exception(_moduleLogger)
83 def _on_row_activated(self, view, path, column):
84 itr = self._model.get_iter(path)
85 node = self._model.get_value(itr, 0)
86 self._window_from_node(node)
89 gobject.type_register(ConferencesWindow)
92 class ConferenceSessionsWindow(windows._base.ListWindow):
94 def __init__(self, app, player, store, node):
95 windows._base.ListWindow.__init__(self, app, player, store, node)
96 self._window.set_title(self._node.title)
99 def _get_columns(cls):
100 yield gobject.TYPE_PYOBJECT, None
102 textrenderer = gtk.CellRendererText()
103 hildonize.set_cell_thumb_selectable(textrenderer)
104 column = gtk.TreeViewColumn("Session")
105 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
106 column.pack_start(textrenderer, expand=True)
107 column.add_attribute(textrenderer, "text", 1)
108 yield gobject.TYPE_STRING, column
111 windows._base.ListWindow._refresh(self)
112 self._node.get_children(
113 self._on_conference_sessions,
117 @misc_utils.log_exception(_moduleLogger)
118 def _on_conference_sessions(self, programs):
119 if self._isDestroyed:
120 _moduleLogger.info("Download complete but window destroyed")
124 for programNode in programs:
125 program = programNode.get_properties()
126 row = programNode, program["title"]
127 self._model.append(row)
131 @misc_utils.log_exception(_moduleLogger)
132 def _on_error(self, exception):
134 self._errorBanner.push_message(str(exception))
136 def _window_from_node(self, node):
137 sessionsWindow = ConferenceTalksWindow(self._app, self._player, self._store, node)
138 sessionsWindow.window.set_modal(True)
139 sessionsWindow.window.set_transient_for(self._window)
140 sessionsWindow.window.set_default_size(*self._window.get_size())
141 sessionsWindow.connect("quit", self._on_quit)
142 sessionsWindow.connect("home", self._on_home)
143 sessionsWindow.connect("jump-to", self._on_jump)
144 sessionsWindow.show()
145 return sessionsWindow
147 @misc_utils.log_exception(_moduleLogger)
148 def _on_row_activated(self, view, path, column):
149 itr = self._model.get_iter(path)
150 node = self._model.get_value(itr, 0)
151 self._window_from_node(node)
154 gobject.type_register(ConferenceSessionsWindow)
157 class ConferenceTalksWindow(windows._base.ListWindow):
159 def __init__(self, app, player, store, node):
160 windows._base.ListWindow.__init__(self, app, player, store, node)
161 self._window.set_title(self._node.title)
164 def _get_columns(cls):
165 yield gobject.TYPE_PYOBJECT, None
167 textrenderer = gtk.CellRendererText()
168 hildonize.set_cell_thumb_selectable(textrenderer)
169 column = gtk.TreeViewColumn("Talk")
170 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
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_conference_talks,
182 @misc_utils.log_exception(_moduleLogger)
183 def _on_conference_talks(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["speaker"])
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 sessionsWindow = ConferenceTalkWindow(self._app, self._player, self._store, node)
203 sessionsWindow.window.set_modal(True)
204 sessionsWindow.window.set_transient_for(self._window)
205 sessionsWindow.window.set_default_size(*self._window.get_size())
206 sessionsWindow.connect("quit", self._on_quit)
207 sessionsWindow.connect("home", self._on_home)
208 sessionsWindow.connect("jump-to", self._on_jump)
209 sessionsWindow.show()
210 return sessionsWindow
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(ConferenceTalksWindow)
222 class ConferenceTalkWindow(windows._base.BasicWindow):
224 def __init__(self, app, player, store, node):
225 windows._base.BasicWindow.__init__(self, app, 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["conference_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 if self._isDestroyed:
301 self._seekbar.set_value(self._player.percent_elapsed * 100)
304 @misc_utils.log_exception(_moduleLogger)
305 def _on_player_state_change(self, player, newState):
306 if self._active and self._player.state == self._player.STATE_PLAY:
308 assert self._updateSeek is None
309 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
310 self._updateSeek.start(seconds=1)
313 if self._updateSeek is not None:
314 self._updateSeek.cancel()
315 self._updateSeek = None
317 if not self._presenterNavigation.is_active():
318 self._set_context(newState)
320 @misc_utils.log_exception(_moduleLogger)
321 def _on_player_title_change(self, player, node):
322 if not self._active or node in [None, self._node]:
323 self._playerNode = player.node
325 self._playerNode = player.node
326 self.emit("jump-to", node)
327 self._window.destroy()
329 @misc_utils.log_exception(_moduleLogger)
330 def _on_player_error(self, player, err, debug):
331 _moduleLogger.error("%r - %r" % (err, debug))
333 @misc_utils.log_exception(_moduleLogger)
334 def _on_navigating(self, widget, navState):
335 if navState == "clicking":
336 if self._player.state == self._player.STATE_PLAY:
338 imageName = "pause_pressed"
340 imageName = "play_pressed"
341 elif self._player.state == self._player.STATE_PAUSE:
342 imageName = "play_pressed"
343 elif self._player.state == self._player.STATE_STOP:
344 imageName = "play_pressed"
346 _moduleLogger.info("Unhandled player state %s" % self._player.state)
347 elif navState == "down":
349 elif navState == "up":
350 if self._player.state == self._player.STATE_PLAY:
355 elif self._player.state == self._player.STATE_PAUSE:
357 elif self._player.state == self._player.STATE_STOP:
360 _moduleLogger.info("Unhandled player state %s" % self._player.state)
361 elif navState == "left":
363 elif navState == "right":
366 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
368 @misc_utils.log_exception(_moduleLogger)
369 def _on_nav_action(self, widget, navState):
370 self._set_context(self._player.state)
372 if navState == "clicking":
373 if self._player.state == self._player.STATE_PLAY:
377 self._player.set_piece_by_node(self._node)
379 elif self._player.state == self._player.STATE_PAUSE:
381 elif self._player.state == self._player.STATE_STOP:
382 self._player.set_piece_by_node(self._node)
385 _moduleLogger.info("Unhandled player state %s" % self._player.state)
386 elif navState == "down":
388 self._window.destroy()
389 elif navState == "up":
391 elif navState == "left":
395 assert self._nextSearch is None
396 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
397 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
398 elif navState == "right":
402 assert self._nextSearch is None
403 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
404 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
406 @misc_utils.log_exception(_moduleLogger)
407 def _on_next_node(self, node):
408 self._nextSearch = None
409 self.emit("jump-to", node)
410 self._window.destroy()
412 @misc_utils.log_exception(_moduleLogger)
413 def _on_node_search_error(self, e):
414 self._nextSearch = None
415 self._errorBanner.push_message(str(e))
418 gobject.type_register(ConferenceTalkWindow)