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 column = gtk.TreeViewColumn("Conference")
39 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
40 column.pack_start(textrenderer, expand=True)
41 column.add_attribute(textrenderer, "text", 2)
42 yield gobject.TYPE_STRING, column
45 windows._base.ListWindow._refresh(self)
46 self._node.get_children(
51 @misc_utils.log_exception(_moduleLogger)
52 def _on_conferences(self, programs):
54 _moduleLogger.info("Download complete but window destroyed")
58 for programNode in programs:
59 program = programNode.get_properties()
60 row = programNode, program["title"], program["full_title"]
61 self._model.append(row)
65 @misc_utils.log_exception(_moduleLogger)
66 def _on_error(self, exception):
68 self._errorBanner.push_message(str(exception))
70 def _window_from_node(self, node):
71 sessionsWindow = ConferenceSessionsWindow(self._app, self._player, self._store, node)
72 sessionsWindow.window.set_modal(True)
73 sessionsWindow.window.set_transient_for(self._window)
74 sessionsWindow.window.set_default_size(*self._window.get_size())
75 sessionsWindow.connect("quit", self._on_quit)
76 sessionsWindow.connect("home", self._on_home)
77 sessionsWindow.connect("jump-to", self._on_jump)
81 @misc_utils.log_exception(_moduleLogger)
82 def _on_row_activated(self, view, path, column):
83 itr = self._model.get_iter(path)
84 node = self._model.get_value(itr, 0)
85 self._window_from_node(node)
88 gobject.type_register(ConferencesWindow)
91 class ConferenceSessionsWindow(windows._base.ListWindow):
93 def __init__(self, app, player, store, node):
94 windows._base.ListWindow.__init__(self, app, player, store, node)
95 self._window.set_title(self._node.title)
98 def _get_columns(cls):
99 yield gobject.TYPE_PYOBJECT, None
101 textrenderer = gtk.CellRendererText()
102 column = gtk.TreeViewColumn("Session")
103 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
104 column.pack_start(textrenderer, expand=True)
105 column.add_attribute(textrenderer, "text", 1)
106 yield gobject.TYPE_STRING, column
109 windows._base.ListWindow._refresh(self)
110 self._node.get_children(
111 self._on_conference_sessions,
115 @misc_utils.log_exception(_moduleLogger)
116 def _on_conference_sessions(self, programs):
117 if self._isDestroyed:
118 _moduleLogger.info("Download complete but window destroyed")
122 for programNode in programs:
123 program = programNode.get_properties()
124 row = programNode, program["title"]
125 self._model.append(row)
129 @misc_utils.log_exception(_moduleLogger)
130 def _on_error(self, exception):
132 self._errorBanner.push_message(str(exception))
134 def _window_from_node(self, node):
135 sessionsWindow = ConferenceTalksWindow(self._app, self._player, self._store, node)
136 sessionsWindow.window.set_modal(True)
137 sessionsWindow.window.set_transient_for(self._window)
138 sessionsWindow.window.set_default_size(*self._window.get_size())
139 sessionsWindow.connect("quit", self._on_quit)
140 sessionsWindow.connect("home", self._on_home)
141 sessionsWindow.connect("jump-to", self._on_jump)
142 sessionsWindow.show()
143 return sessionsWindow
145 @misc_utils.log_exception(_moduleLogger)
146 def _on_row_activated(self, view, path, column):
147 itr = self._model.get_iter(path)
148 node = self._model.get_value(itr, 0)
149 self._window_from_node(node)
152 gobject.type_register(ConferenceSessionsWindow)
155 class ConferenceTalksWindow(windows._base.ListWindow):
157 def __init__(self, app, player, store, node):
158 windows._base.ListWindow.__init__(self, app, player, store, node)
159 self._window.set_title(self._node.title)
162 def _get_columns(cls):
163 yield gobject.TYPE_PYOBJECT, None
165 textrenderer = gtk.CellRendererText()
166 column = gtk.TreeViewColumn("Talk")
167 column.set_property("sizing", gtk.TREE_VIEW_COLUMN_FIXED)
168 column.pack_start(textrenderer, expand=True)
169 column.add_attribute(textrenderer, "text", 1)
170 yield gobject.TYPE_STRING, column
173 windows._base.ListWindow._refresh(self)
174 self._node.get_children(
175 self._on_conference_talks,
179 @misc_utils.log_exception(_moduleLogger)
180 def _on_conference_talks(self, programs):
181 if self._isDestroyed:
182 _moduleLogger.info("Download complete but window destroyed")
186 for programNode in programs:
187 program = programNode.get_properties()
188 row = programNode, "%s\n%s" % (program["title"], program["speaker"])
189 self._model.append(row)
193 @misc_utils.log_exception(_moduleLogger)
194 def _on_error(self, exception):
196 self._errorBanner.push_message(str(exception))
198 def _window_from_node(self, node):
199 sessionsWindow = ConferenceTalkWindow(self._app, self._player, self._store, node)
200 sessionsWindow.window.set_modal(True)
201 sessionsWindow.window.set_transient_for(self._window)
202 sessionsWindow.window.set_default_size(*self._window.get_size())
203 sessionsWindow.connect("quit", self._on_quit)
204 sessionsWindow.connect("home", self._on_home)
205 sessionsWindow.connect("jump-to", self._on_jump)
206 sessionsWindow.show()
207 return sessionsWindow
209 @misc_utils.log_exception(_moduleLogger)
210 def _on_row_activated(self, view, path, column):
211 itr = self._model.get_iter(path)
212 node = self._model.get_value(itr, 0)
213 self._window_from_node(node)
216 gobject.type_register(ConferenceTalksWindow)
219 class ConferenceTalkWindow(windows._base.BasicWindow):
221 def __init__(self, app, player, store, node):
222 windows._base.BasicWindow.__init__(self, app, player, store)
224 self._playerNode = self._player.node
225 self._nextSearch = None
226 self._updateSeek = None
228 self.connect_auto(self._player, "state-change", self._on_player_state_change)
229 self.connect_auto(self._player, "title-change", self._on_player_title_change)
230 self.connect_auto(self._player, "error", self._on_player_error)
232 self._loadingBanner = banners.GenericBanner()
234 self._presenter = presenter.StreamPresenter(self._store)
235 self._presenter.set_context(
236 self._store.STORE_LOOKUP["conference_background"],
240 self._presenterNavigation = presenter.NavigationBox()
241 self._presenterNavigation.toplevel.add(self._presenter.toplevel)
242 self._presenterNavigation.connect("action", self._on_nav_action)
243 self._presenterNavigation.connect("navigating", self._on_navigating)
245 self._seekbar = hildonize.create_seekbar()
246 self._seekbar.connect("change-value", self._on_user_seek)
248 self._layout.pack_start(self._loadingBanner.toplevel, False, False)
249 self._layout.pack_start(self._presenterNavigation.toplevel, True, True)
250 self._layout.pack_start(self._seekbar, False, False)
252 self._window.set_title(self._node.title)
255 windows._base.BasicWindow.show(self)
256 self._window.show_all()
257 self._errorBanner.toplevel.hide()
258 self._loadingBanner.toplevel.hide()
259 self._set_context(self._player.state)
262 def jump_to(self, node):
263 assert self._node is node
267 return self._playerNode is self._node
269 def _show_loading(self):
270 animationPath = self._store.STORE_LOOKUP["loading"]
271 animation = self._store.get_pixbuf_animation_from_store(animationPath)
272 self._loadingBanner.show(animation, "Loading...")
274 def _hide_loading(self):
275 self._loadingBanner.hide()
277 def _set_context(self, state):
278 if state == self._player.STATE_PLAY:
280 self._presenter.set_state(self._store.STORE_LOOKUP["pause"])
282 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
283 elif state == self._player.STATE_PAUSE:
284 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
285 elif state == self._player.STATE_STOP:
286 self._presenter.set_state(self._store.STORE_LOOKUP["play"])
288 _moduleLogger.info("Unhandled player state %s" % state)
290 @misc_utils.log_exception(_moduleLogger)
291 def _on_user_seek(self, widget, scroll, value):
292 self._player.seek(value / 100.0)
294 @misc_utils.log_exception(_moduleLogger)
295 def _on_player_update_seek(self):
296 if self._isDestroyed:
298 self._seekbar.set_value(self._player.percent_elapsed * 100)
301 @misc_utils.log_exception(_moduleLogger)
302 def _on_player_state_change(self, player, newState):
303 if self._active and self._player.state == self._player.STATE_PLAY:
305 assert self._updateSeek is None
306 self._updateSeek = go_utils.Timeout(self._on_player_update_seek, once=False)
307 self._updateSeek.start(seconds=1)
310 if self._updateSeek is not None:
311 self._updateSeek.cancel()
312 self._updateSeek = None
314 if not self._presenterNavigation.is_active():
315 self._set_context(newState)
317 @misc_utils.log_exception(_moduleLogger)
318 def _on_player_title_change(self, player, node):
319 if not self._active or node in [None, self._node]:
320 self._playerNode = player.node
322 self._playerNode = player.node
323 self.emit("jump-to", node)
324 self._window.destroy()
326 @misc_utils.log_exception(_moduleLogger)
327 def _on_player_error(self, player, err, debug):
328 _moduleLogger.error("%r - %r" % (err, debug))
330 @misc_utils.log_exception(_moduleLogger)
331 def _on_navigating(self, widget, navState):
332 if navState == "clicking":
333 if self._player.state == self._player.STATE_PLAY:
335 imageName = "pause_pressed"
337 imageName = "play_pressed"
338 elif self._player.state == self._player.STATE_PAUSE:
339 imageName = "play_pressed"
340 elif self._player.state == self._player.STATE_STOP:
341 imageName = "play_pressed"
343 _moduleLogger.info("Unhandled player state %s" % self._player.state)
344 elif navState == "down":
346 elif navState == "up":
347 if self._player.state == self._player.STATE_PLAY:
352 elif self._player.state == self._player.STATE_PAUSE:
354 elif self._player.state == self._player.STATE_STOP:
357 _moduleLogger.info("Unhandled player state %s" % self._player.state)
358 elif navState == "left":
360 elif navState == "right":
363 self._presenter.set_state(self._store.STORE_LOOKUP[imageName])
365 @misc_utils.log_exception(_moduleLogger)
366 def _on_nav_action(self, widget, navState):
367 self._set_context(self._player.state)
369 if navState == "clicking":
370 if self._player.state == self._player.STATE_PLAY:
374 self._player.set_piece_by_node(self._node)
376 elif self._player.state == self._player.STATE_PAUSE:
378 elif self._player.state == self._player.STATE_STOP:
379 self._player.set_piece_by_node(self._node)
382 _moduleLogger.info("Unhandled player state %s" % self._player.state)
383 elif navState == "down":
385 self._window.destroy()
386 elif navState == "up":
388 elif navState == "left":
392 assert self._nextSearch is None
393 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
394 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
395 elif navState == "right":
399 assert self._nextSearch is None
400 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
401 self._nextSearch.start(self._node, self._on_next_node, self._on_node_search_error)
403 @misc_utils.log_exception(_moduleLogger)
404 def _on_next_node(self, node):
405 self._nextSearch = None
406 self.emit("jump-to", node)
407 self._window.destroy()
409 @misc_utils.log_exception(_moduleLogger)
410 def _on_node_search_error(self, e):
411 self._nextSearch = None
412 self._errorBanner.push_message(str(e))
415 gobject.type_register(ConferenceTalkWindow)