2 Minimal VLC VLM client for AceProxy. Client class.
10 from vlcmessages import *
12 from pprint import pprint
14 class VlcException(Exception):
17 Exception from VlcClient
22 class VlcClient(object):
29 self, host='127.0.0.1', port=4212, password='admin', connect_timeout=10,
30 result_timeout=10, out_port=8081):
32 self._recvbuffer = None
34 self._out_port = out_port
38 self._resulttimeout = result_timeout
40 self._shuttingDown = gevent.event.Event()
41 # Authentication done event
42 self._auth = gevent.event.AsyncResult()
44 self._resultlock = gevent.coros.RLock()
46 self._result = gevent.event.AsyncResult()
50 self._password = password
53 logger = logging.getLogger('VlcClient_init')
60 self._socket = telnetlib.Telnet(host, port, connect_timeout)
61 logger.info("Successfully connected with VLC socket!")
62 except Exception as e:
64 "Socket creation error! VLC is not running? ERROR: " + repr(e))
66 # Spawning recvData greenlet
67 gevent.spawn(self._recvData)
70 # Waiting for authentication event
72 if self._auth.get(timeout=self._resulttimeout) == False:
73 errmsg = "Authentication error"
75 raise VlcException(errmsg)
76 except gevent.Timeout:
77 errmsg = "Authentication timeout"
79 raise VlcException(errmsg)
82 # Destructor just calls destroy() method
87 logger = logging.getLogger("VlcClient_destroy")
89 if self._shuttingDown.isSet():
90 # Already in the middle of destroying
93 # If socket is still alive (connected)
96 logger.info("Destroying VlcClient...")
97 self._write(VlcMessage.request.SHUTDOWN)
98 # Set shuttingDown flag for recvData
99 self._shuttingDown.set()
101 # Ignore exceptions on destroy
104 def _write(self, message):
106 logger = logging.getLogger("VlcClient_write")
108 # Return if in the middle of destroying
109 if self._shuttingDown.isSet():
114 logger.info('VLC command: ' + message)
115 self._socket.write(message + "\r\n")
116 except EOFError as e:
117 raise VlcException("Vlc Write error! ERROR: " + repr(e))
119 def _broadcast(self, brtype, stream_name, input=None, muxer='ts', pre_access='', qtype='default'):
120 if self._shuttingDown.isSet():
123 # Start/stop broadcast with VLC
126 broadcast = 'startBroadcast'
128 broadcast = 'stopBroadcast'
130 logger = logging.getLogger("VlcClient_" + broadcast)
132 self._result = gevent.event.AsyncResult()
134 self._resultlock.acquire()
135 # Write message to VLC socket
137 msg = VlcMessage.request.startBroadcast(stream_name, input, self._out_port, muxer, pre_access, qtype)
140 if stream_name not in self.streams:
141 self._resultlock.release()
142 logger.error("Attempting to delete not existing stream %s" % stream_name)
144 self._write(VlcMessage.request.stopBroadcast(stream_name))
148 result = self._result.get(timeout=self._resulttimeout)
150 logger.error(broadcast + " error")
151 raise VlcException(broadcast + " error")
152 except gevent.Timeout:
153 logger.error(broadcast + " result timeout")
154 raise VlcException(broadcast + " result timeout")
156 logger.info("working with %s stream: %s" % (stream_name,broadcast))
158 self.streams[stream_name]=time.time()
160 del self.streams[stream_name]
161 self._resultlock.release()
162 logger.info("worked with %s stream: %s" % (stream_name,broadcast))
165 logger.info("Broadcast started")
167 logger.info("Broadcast stopped")
169 def startBroadcast(self, stream_name, input, muxer='ts', pre_access='', qtype='default'):
170 logger = logging.getLogger("VlcClient_startBroadcast")
171 logger.debug("Starting broadcast......")
172 return self._broadcast(True, stream_name, input, muxer, pre_access, qtype)
174 def stopBroadcast(self, stream_name):
175 return self._broadcast(False, stream_name)
177 def mark(self,stream_name):
178 self.streams[stream_name]=time.time()
180 def clean_streams(self,timeout=15):
181 self._resultlock.acquire()
183 for stream,lasttime in self.streams.iteritems():
184 print stream,lasttime
185 if time.time()-lasttime>timeout:
187 for stream in to_stop:
188 self.stopBroadcast(stream)
189 self._resultlock.release()
191 def pauseBroadcast(self, stream_name):
192 return self._write(VlcMessage.request.pauseBroadcast(stream_name))
194 def playBroadcast(self, stream_name):
195 return self._write(VlcMessage.request.playBroadcast(stream_name))
199 logger = logging.getLogger("VlcClient_recvData")
204 self._recvbuffer = self._socket.read_until("\n")
205 # Stripping "> " from VLC
206 self._recvbuffer = self._recvbuffer.lstrip("> ")
208 # If something happened during read, abandon reader
209 if not self._shuttingDown.isSet():
210 logger.error("Exception at socket read")
211 self._shuttingDown.set()
214 # Parsing everything only if the string is not empty
217 # First line (VLC version)
218 self._vlcver = self._recvbuffer.strip()
219 # Send password here since PASSWORD doesn't have \n
220 self._write(self._password)
222 elif self._recvbuffer.startswith(VlcMessage.response.SHUTDOWN):
223 # Exit from this loop
224 logger.debug("Got SHUTDOWN from VLC")
227 elif self._recvbuffer.startswith(VlcMessage.response.WRONGPASS):
229 logger.error("Wrong VLC password!")
230 self._auth.set(False)
233 elif self._recvbuffer.startswith(VlcMessage.response.AUTHOK):
235 logger.info("Authentication successful")
238 elif VlcMessage.response.BROADCASTEXISTS in self._recvbuffer:
239 # Broadcast already exists
240 logger.error("Broadcast already exists!")
241 self._result.set(False)
243 elif VlcMessage.response.STOPERR in self._recvbuffer:
244 # Media unknown (stopping non-existent stream)
245 logger.error("Broadcast does not exist!")
246 self._result.set(False)
248 # Do not move this before error handlers!
249 elif self._recvbuffer.startswith(VlcMessage.response.STARTOK):
251 logger.info("Broadcast started")
252 self._result.set(True)
254 elif self._recvbuffer.startswith(VlcMessage.response.STOPOK):
256 logger.info("Broadcast stopped")
257 self._result.set(True)