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 textrenderer.set_property("scale", 0.75)
31 column = gtk.TreeViewColumn("Date")
32 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
33 column.set_property("fixed-width", 96)
34 column.pack_start(textrenderer, expand=True)
35 column.add_attribute(textrenderer, "text", 1)
36 yield gobject.TYPE_STRING, column
38 textrenderer = gtk.CellRendererText()
39 hildonize.set_cell_thumb_selectable(textrenderer)
40 column = gtk.TreeViewColumn("Conference")
41 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
42 column.pack_start(textrenderer, expand=True)
43 column.add_attribute(textrenderer, "text", 2)
44 yield gobject.TYPE_STRING, column
47 windows._base.ListWindow._refresh(self)
48 self._node.get_children(
53 @misc_utils.log_exception(_moduleLogger)
54 def _on_conferences(self, programs):
56 _moduleLogger.info("Download complete but window destroyed")
60 for programNode in programs:
61 program = programNode.get_properties()
62 row = programNode, program["title"], program["full_title"]
63 self._model.append(row)
67 @misc_utils.log_exception(_moduleLogger)
68 def _on_error(self, exception):
70 self._errorBanner.push_message(str(exception))
72 def _window_from_node(self, node):
73 sessionsWindow = ConferenceSessionsWindow(self._app, self._player, self._store, node)
74 sessionsWindow.window.set_modal(True)
75 sessionsWindow.window.set_transient_for(self._window)
76 sessionsWindow.window.set_default_size(*self._window.get_size())
77 sessionsWindow.connect("quit", self._on_quit)
78 sessionsWindow.connect("home", self._on_home)
79 sessionsWindow.connect("jump-to", self._on_jump)
84 gobject.type_register(ConferencesWindow)
87 class ConferenceSessionsWindow(windows._base.ListWindow):
89 def __init__(self, app, player, store, node):
90 windows._base.ListWindow.__init__(self, app, player, store, node)
91 self._window.set_title(self._node.title)
94 def _get_columns(cls):
95 yield gobject.TYPE_PYOBJECT, None
97 textrenderer = gtk.CellRendererText()
98 hildonize.set_cell_thumb_selectable(textrenderer)
99 column = gtk.TreeViewColumn("Session")
100 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
101 column.pack_start(textrenderer, expand=True)
102 column.add_attribute(textrenderer, "text", 1)
103 yield gobject.TYPE_STRING, column
106 windows._base.ListWindow._refresh(self)
107 self._node.get_children(
108 self._on_conference_sessions,
112 @misc_utils.log_exception(_moduleLogger)
113 def _on_conference_sessions(self, programs):
114 if self._isDestroyed:
115 _moduleLogger.info("Download complete but window destroyed")
119 for programNode in programs:
120 program = programNode.get_properties()
121 row = programNode, program["title"]
122 self._model.append(row)
126 @misc_utils.log_exception(_moduleLogger)
127 def _on_error(self, exception):
129 self._errorBanner.push_message(str(exception))
131 def _window_from_node(self, node):
132 sessionsWindow = ConferenceTalksWindow(self._app, self._player, self._store, node)
133 sessionsWindow.window.set_modal(True)
134 sessionsWindow.window.set_transient_for(self._window)
135 sessionsWindow.window.set_default_size(*self._window.get_size())
136 sessionsWindow.connect("quit", self._on_quit)
137 sessionsWindow.connect("home", self._on_home)
138 sessionsWindow.connect("jump-to", self._on_jump)
139 sessionsWindow.show()
140 return sessionsWindow
143 gobject.type_register(ConferenceSessionsWindow)
146 class ConferenceTalksWindow(windows._base.ListWindow):
148 def __init__(self, app, player, store, node):
149 windows._base.ListWindow.__init__(self, app, player, store, node)
150 self._window.set_title(self._node.title)
153 def _get_columns(cls):
154 yield gobject.TYPE_PYOBJECT, None
156 textrenderer = gtk.CellRendererText()
157 column = gtk.TreeViewColumn("Talk")
158 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
159 column.pack_start(textrenderer, expand=True)
160 column.add_attribute(textrenderer, "markup", 1)
161 yield gobject.TYPE_STRING, column
164 windows._base.ListWindow._refresh(self)
165 self._node.get_children(
166 self._on_conference_talks,
170 @misc_utils.log_exception(_moduleLogger)
171 def _on_conference_talks(self, programs):
172 if self._isDestroyed:
173 _moduleLogger.info("Download complete but window destroyed")
177 for programNode in programs:
178 program = programNode.get_properties()
179 row = programNode, "%s\n<small>%s</small>" % (programNode.title, programNode.subtitle)
180 self._model.append(row)
184 @misc_utils.log_exception(_moduleLogger)
185 def _on_error(self, exception):
187 self._errorBanner.push_message(str(exception))
189 def _window_from_node(self, node):
190 sessionsWindow = ConferenceTalkWindow(self._app, self._player, self._store, node)
191 sessionsWindow.window.set_modal(True)
192 sessionsWindow.window.set_transient_for(self._window)
193 sessionsWindow.window.set_default_size(*self._window.get_size())
194 sessionsWindow.connect("quit", self._on_quit)
195 sessionsWindow.connect("home", self._on_home)
196 sessionsWindow.connect("jump-to", self._on_jump)
197 sessionsWindow.show()
198 return sessionsWindow
201 gobject.type_register(ConferenceTalksWindow)
204 class ConferenceTalkWindow(windows._base.BasicWindow):
206 def __init__(self, app, player, store, node):
207 windows._base.BasicWindow.__init__(self, app, player, store)
209 self._playerNode = self._player.node
210 self._nextSearch = None
211 self._updateSeek = None
213 self.connect_auto(self._player, "state-change", self._on_player_state_change)
214 self.connect_auto(self._player, "title-change", self._on_player_title_change)
215 self.connect_auto(self._player, "error", self._on_player_error)
217 self._loadingBanner = banners.GenericBanner()
219 self._presenter = presenter.StreamPresenter(self._store)
220 self._presenter.set_context(
221 self._store.STORE_LOOKUP["conference_background"],
225 self._presenterNavigation = presenter.NavigationBox()
226 self._presenterNavigation.toplevel.add(self._presenter.toplevel)
227 self._presenterNavigation.connect("action", self._on_nav_action)
228 self._presenterNavigation.connect("navigating", self._on_navigating)
230 self._seekbar = hildonize.create_seekbar()
231 self._seekbar.connect("change-value", self._on_user_seek)
233 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
234 self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
235 self._layout.pack_start(self._seekbar, False, False)
237 self._window.set_title(self._node.title)
240 windows._base.BasicWindow.show(self)
241 self._window.show_all()
242 self._errorBanner.toplevel.hide()
243 self._loadingBanner.toplevel.hide()
244 self._set_context(self._player.state)
247 def jump_to(self, node):
248 assert self._node is node
252 return self._playerNode is self._node
254 def _show_loading(self):
255 animationPath = self._store.STORE_LOOKUP["loading"]
256 animation = self._store.get_pixbuf_animation_from_store(animationPath)
257 self._loadingBanner.show(animation, "Loading...")
259 def _hide_loading(self):
260 self._loadingBanner.hide()
262 def _set_context(self, state):
263 if state == self._player.STATE_PLAY:
265 self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
267 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
268 elif state == self._player.STATE_PAUSE:
269 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
270 elif state == self._player.STATE_STOP:
271 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
273 _moduleLogger.info("Unhandled player state %s" % state)
275 @misc_utils.log_exception(_moduleLogger)
276 def _on_user_seek(self, widget, scroll, value):
277 self._player.seek(value / 100.0)
279 @misc_utils.log_exception(_moduleLogger)
280 def _on_player_update_seek(self):
281 if self._isDestroyed:
283 self._seekbar.set_value(self._player.percent_elapsed * 100)
286 @misc_utils.log_exception(_moduleLogger)
287 def _on_player_state_change(self, player, newState):
288 if self._active and self._player.state == self._player.STATE_PLAY:
290 assert self._updateSeek is None
291 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
292 self._updateSeek.start(seconds=1)
295 if self._updateSeek is not None:
296 self._updateSeek.cancel()
297 self._updateSeek = None
299 if not self._presenterNavigation.is_active():
300 self._set_context(newState)
302 @misc_utils.log_exception(_moduleLogger)
303 def _on_player_title_change(self, player, node):
304 if not self._active or node in [None, self._node]:
305 self._playerNode = player.node
307 self._playerNode = player.node
308 self.emit("jump-to", node)
309 self._window.destroy()
311 @misc_utils.log_exception(_moduleLogger)
312 def _on_player_error(self, player, err, debug):
313 _moduleLogger.error("%r - %r" % (err, debug))
315 @misc_utils.log_exception(_moduleLogger)
316 def _on_navigating(self, widget, navState):
317 if navState == "clicking":
318 if self._player.state == self._player.STATE_PLAY:
320 imageName = "pause_pressed"
322 imageName = "play_pressed"
323 elif self._player.state == self._player.STATE_PAUSE:
324 imageName = "play_pressed"
325 elif self._player.state == self._player.STATE_STOP:
326 imageName = "play_pressed"
328 _moduleLogger.info("Unhandled player state %s" % self._player.state)
329 elif navState == "down":
331 elif navState == "up":
332 if self._player.state == self._player.STATE_PLAY:
337 elif self._player.state == self._player.STATE_PAUSE:
339 elif self._player.state == self._player.STATE_STOP:
342 _moduleLogger.info("Unhandled player state %s" % self._player.state)
343 elif navState == "left":
345 elif navState == "right":
348 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
350 @misc_utils.log_exception(_moduleLogger)
351 def _on_nav_action(self, widget, navState):
352 self._set_context(self._player.state)
354 if navState == "clicking":
355 if self._player.state == self._player.STATE_PLAY:
359 self._player.set_piece_by_node(self._node)
361 elif self._player.state == self._player.STATE_PAUSE:
363 elif self._player.state == self._player.STATE_STOP:
364 self._player.set_piece_by_node(self._node)
367 _moduleLogger.info("Unhandled player state %s" % self._player.state)
368 elif navState == "down":
370 self._window.destroy()
371 elif navState == "up":
373 elif navState == "left":
377 assert self._nextSearch is None
378 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
379 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
380 elif navState == "right":
384 assert self._nextSearch is None
385 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
386 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
388 @misc_utils.log_exception(_moduleLogger)
389 def _on_next_node(self, node):
390 self._nextSearch = None
391 self.emit("jump-to", node)
392 self._window.destroy()
394 @misc_utils.log_exception(_moduleLogger)
395 def _on_node_search_error(self, e):
396 self._nextSearch = None
397 self._errorBanner.push_message(str(e))
400 gobject.type_register(ConferenceTalkWindow)