5 import util.misc as misc_utils
11 _moduleLogger = logging.getLogger(__name__)
14 class Player(gobject.GObject):
18 gobject.SIGNAL_RUN_LAST,
20 (gobject.TYPE_PYOBJECT, ),
23 gobject.SIGNAL_RUN_LAST,
25 (gobject.TYPE_PYOBJECT, ),
28 gobject.SIGNAL_RUN_LAST,
30 (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT),
34 STATE_PLAY = stream.GSTStream.STATE_PLAY
35 STATE_PAUSE = stream.GSTStream.STATE_PAUSE
36 STATE_STOP = stream.GSTStream.STATE_STOP
38 def __init__(self, index):
39 gobject.GObject.__init__(self)
42 self._nextSearch = None
44 self._calls = call_monitor.CallMonitor()
45 self._calls.connect("call_start", self._on_call_start)
47 self._stream = stream.GSTStream()
48 self._stream.connect("state-change", self._on_stream_state)
49 self._stream.connect("eof", self._on_stream_eof)
50 self._stream.connect("error", self._on_stream_error)
52 def set_piece_by_node(self, node):
53 self._set_piece_by_node(node)
61 if self._node is None:
63 return self._node.title
67 if self._node is None:
69 return self._node.subtitle
72 def can_navigate(self):
73 if self._node is None:
75 return self.node.can_navigate
79 return self._stream.state
82 _moduleLogger.info("play")
88 _moduleLogger.info("pause")
92 _moduleLogger.info("stop")
94 self.set_piece_by_node(None)
98 def back(self, forcePlay = False):
99 _moduleLogger.info("back")
100 assert self._nextSearch is None
101 self._nextSearch = stream_index.AsyncWalker(stream_index.get_previous)
102 self._nextSearch.start(
104 lambda node: self._on_next_node(node, forcePlay),
105 self._on_node_search_error
108 def next(self, forcePlay = False):
109 _moduleLogger.info("next")
110 assert self._nextSearch is None
111 self._nextSearch = stream_index.AsyncWalker(stream_index.get_next)
112 self._nextSearch.start(
114 lambda node: self._on_next_node(node, forcePlay),
115 self._on_node_search_error
118 def seek(self, percent):
119 target = percent * self._stream.duration
120 self._stream.seek_time(target)
123 def percent_elapsed(self):
124 percent = float(self._stream.elapsed) / float(self._stream.duration)
127 def _set_piece_by_node(self, node):
128 assert node is None or node.is_leaf(), node
129 if self._node is node:
130 _moduleLogger.info("Already set to %r" % node)
133 if self._node is not None:
134 self._stream.set_file(self._node.uri)
135 _moduleLogger.info("New node %r" % self._node)
136 self.emit("title_change", self._node)
138 @misc_utils.log_exception(_moduleLogger)
139 def _on_next_node(self, node, forcePlay):
140 self._nextSearch = None
142 restart = self.state == self.STATE_PLAY
143 self._set_piece_by_node(node)
144 if restart or forcePlay:
147 @misc_utils.log_exception(_moduleLogger)
148 def _on_node_search_error(self, e):
149 self._nextSearch = None
150 self.emit("error", e, "")
152 @misc_utils.log_exception(_moduleLogger)
153 def _on_stream_state(self, s, state):
154 _moduleLogger.info("State change %r" % state)
155 self.emit("state_change", state)
157 @misc_utils.log_exception(_moduleLogger)
158 def _on_stream_eof(self, s, uri):
159 _moduleLogger.info("EOF %s" % uri)
160 self.next(forcePlay = True)
162 @misc_utils.log_exception(_moduleLogger)
163 def _on_stream_error(self, s, error, debug):
164 _moduleLogger.info("Error %s %s" % (error, debug))
165 self.emit("error", error, debug)
167 @misc_utils.log_exception(_moduleLogger)
168 def _on_call_start(self, monitor):
169 _moduleLogger.info("Call in progress, pausing")
173 gobject.type_register(Player)