5 import util.misc as misc_utils
20 _moduleLogger = logging.getLogger(__name__)
23 class Player(gobject.GObject):
27 gobject.SIGNAL_RUN_LAST,
29 (gobject.TYPE_PYOBJECT, ),
32 gobject.SIGNAL_RUN_LAST,
34 (gobject.TYPE_PYOBJECT, ),
37 gobject.SIGNAL_RUN_LAST,
39 (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT),
43 STATE_PLAY = stream.Stream.STATE_PLAY
44 STATE_PAUSE = stream.Stream.STATE_PAUSE
45 STATE_STOP = stream.Stream.STATE_STOP
47 def __init__(self, index):
48 gobject.GObject.__init__(self)
51 self._nextSearch = None
53 self._calls = call_monitor.CallMonitor()
54 self._calls.connect("call_start", self._on_call_start)
56 self._stream = stream.Stream()
57 self._stream.connect("state-change", self._on_stream_state)
58 self._stream.connect("eof", self._on_stream_eof)
59 self._stream.connect("error", self._on_stream_error)
61 def set_piece_by_node(self, node):
62 self._set_piece_by_node(node)
70 if self._node is None:
72 return self._node.title
76 if self._node is None:
78 return self._node.subtitle
81 def can_navigate(self):
82 if self._node is None:
84 return self.node.can_navigate
88 return self._stream.state
91 _moduleLogger.info("play")
97 _moduleLogger.info("pause")
101 _moduleLogger.info("stop")
103 self.set_piece_by_node(None)
107 def back(self, forcePlay = False):
108 _moduleLogger.info("back")
109 assert self._nextSearch is None
110 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
111 self._nextSearch.start(
113 lambda node: self._on_next_node(node, forcePlay),
114 self._on_node_search_error
117 def next(self, forcePlay = False):
118 _moduleLogger.info("next")
119 assert self._nextSearch is None
120 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
121 self._nextSearch.start(
123 lambda node: self._on_next_node(node, forcePlay),
124 self._on_node_search_error
127 def seek(self, percent):
128 target = percent * self._stream.duration
129 self._stream.seek_time(target)
132 def percent_elapsed(self):
133 percent = float(self._stream.elapsed) / float(self._stream.duration)
136 def _set_piece_by_node(self, node):
137 assert node is None or node.is_leaf(), node
138 if self._node is node:
139 _moduleLogger.info("Already set to %r" % node)
142 if self._node is not None:
143 self._stream.set_file(self._node.uri)
144 _moduleLogger.info("New node %r" % self._node)
145 self.emit("title_change", self._node)
147 @misc_utils.log_exception(_moduleLogger)
148 def _on_next_node(self, node, forcePlay):
149 self._nextSearch = None
151 restart = self.state == self.STATE_PLAY
152 self._set_piece_by_node(node)
153 if restart or forcePlay:
156 @misc_utils.log_exception(_moduleLogger)
157 def _on_node_search_error(self, e):
158 self._nextSearch = None
159 self.emit("error", e, "")
161 @misc_utils.log_exception(_moduleLogger)
162 def _on_stream_state(self, s, state):
163 _moduleLogger.info("State change %r" % state)
164 self.emit("state_change", state)
166 @misc_utils.log_exception(_moduleLogger)
167 def _on_stream_eof(self, s, uri):
168 _moduleLogger.info("EOF %s" % uri)
169 self.next(forcePlay = True)
171 @misc_utils.log_exception(_moduleLogger)
172 def _on_stream_error(self, s, error, debug):
173 _moduleLogger.info("Error %s %s" % (error, debug))
174 self.emit("error", error, debug)
176 @misc_utils.log_exception(_moduleLogger)
177 def _on_call_start(self, monitor):
178 _moduleLogger.info("Call in progress, pausing")
182 gobject.type_register(Player)