5 import util.misc as misc_utils
7 import stream as _stream
8 stream = _stream # Silence PyFlakes
10 import stream_gst as stream
15 _moduleLogger = logging.getLogger(__name__)
18 class Player(gobject.GObject):
22 gobject.SIGNAL_RUN_LAST,
24 (gobject.TYPE_PYOBJECT, ),
27 gobject.SIGNAL_RUN_LAST,
29 (gobject.TYPE_PYOBJECT, ),
32 gobject.SIGNAL_RUN_LAST,
34 (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT),
38 STATE_PLAY = stream.Stream.STATE_PLAY
39 STATE_PAUSE = stream.Stream.STATE_PAUSE
40 STATE_STOP = stream.Stream.STATE_STOP
42 def __init__(self, index):
43 gobject.GObject.__init__(self)
46 self._nextSearch = None
48 self._calls = call_monitor.CallMonitor()
49 self._calls.connect("call_start", self._on_call_start)
51 self._stream = stream.Stream()
52 self._stream.connect("state-change", self._on_stream_state)
53 self._stream.connect("eof", self._on_stream_eof)
54 self._stream.connect("error", self._on_stream_error)
56 def set_piece_by_node(self, node):
57 self._set_piece_by_node(node)
65 if self._node is None:
67 return self._node.title
71 if self._node is None:
73 return self._node.subtitle
76 def can_navigate(self):
77 if self._node is None:
79 return self.node.can_navigate
83 return self._stream.state
86 _moduleLogger.info("play")
92 _moduleLogger.info("pause")
96 _moduleLogger.info("stop")
98 self.set_piece_by_node(None)
102 def back(self, forcePlay = False):
103 _moduleLogger.info("back")
104 assert self._nextSearch is None
105 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
106 self._nextSearch.start(
108 lambda node: self._on_next_node(node, forcePlay),
109 self._on_node_search_error
112 def next(self, forcePlay = False):
113 _moduleLogger.info("next")
114 assert self._nextSearch is None
115 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
116 self._nextSearch.start(
118 lambda node: self._on_next_node(node, forcePlay),
119 self._on_node_search_error
122 def seek(self, percent):
123 target = percent * self._stream.duration
124 self._stream.seek_time(target)
127 def percent_elapsed(self):
128 percent = float(self._stream.elapsed) / float(self._stream.duration)
131 def _set_piece_by_node(self, node):
132 assert node is None or node.is_leaf(), node
133 if self._node is node:
134 _moduleLogger.info("Already set to %r" % node)
137 if self._node is not None:
138 self._stream.set_file(self._node.uri)
139 _moduleLogger.info("New node %r" % self._node)
140 self.emit("title_change", self._node)
142 @misc_utils.log_exception(_moduleLogger)
143 def _on_next_node(self, node, forcePlay):
144 self._nextSearch = None
146 restart = self.state == self.STATE_PLAY
147 self._set_piece_by_node(node)
148 if restart or forcePlay:
151 @misc_utils.log_exception(_moduleLogger)
152 def _on_node_search_error(self, e):
153 self._nextSearch = None
154 self.emit("error", e, "")
156 @misc_utils.log_exception(_moduleLogger)
157 def _on_stream_state(self, s, state):
158 _moduleLogger.info("State change %r" % state)
159 self.emit("state_change", state)
161 @misc_utils.log_exception(_moduleLogger)
162 def _on_stream_eof(self, s, uri):
163 _moduleLogger.info("EOF %s" % uri)
164 self.next(forcePlay = True)
166 @misc_utils.log_exception(_moduleLogger)
167 def _on_stream_error(self, s, error, debug):
168 _moduleLogger.info("Error %s %s" % (error, debug))
169 self.emit("error", error, debug)
171 @misc_utils.log_exception(_moduleLogger)
172 def _on_call_start(self, monitor):
173 _moduleLogger.info("Call in progress, pausing")
177 gobject.type_register(Player)