Use Twisted for VLC communication (#353)

* Port VLCPlayer from asyncore/asynchat to Twisted

Rationale: asyncore/asynchat are deprecated since Python 3.6 and
are going to be removed from the standard library from Python 3.10.
It is unclear if these libraries will be picked up by maintainers
and independently published on PyPI. At the moment, we are working
on replacing them, in this commit with Twisted LineReceiver.

Known issues: does not work with GUI. There is a conflict with
qt5reactor -> "QSocketNotifier: Can only be used with threads
started with QThread".

* Fix QSocketNotifier issue with qt5reactor

Sending the call to transport.write wrapped in a
self.reactor.callFromThread instead of directly does the trick.
Include also fixes to allow correct quit of VLC and Syncplay when
either one is closed.

Known issues: there is a noticeable lag (~ 1 second) between the
start of Syncplay MainWindow and the start of VLC.

* Re-add try/except to VLC

* Bring back missing try

Co-authored-by: Alberto Sottile <alby128@gmail.com>
This commit is contained in:
Etoh 2020-09-20 13:45:23 +01:00 committed by GitHub
parent a02ddccf6b
commit dd8c864d98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 20 additions and 18 deletions

View File

@ -32,13 +32,13 @@ class VLCProtocol(LineReceiver):
if not self.factory.requestedVLCVersion: if not self.factory.requestedVLCVersion:
self.factory.requestedVLCVersion = True self.factory.requestedVLCVersion = True
self.sendLine("get-vlc-version") self.sendLine("get-vlc-version")
# try: try:
lineToSend = line.encode('utf-8') + self.delimiter lineToSend = line.encode('utf-8') + self.delimiter
self.transport.write(lineToSend) self.transport.write(lineToSend)
if self.factory._playerController._client and self.factory._playerController._client.ui: if self.factory._playerController._client and self.factory._playerController._client.ui:
self.factory._playerController._client.ui.showDebugMessage("player >> {}".format(line)) self.factory._playerController._client.ui.showDebugMessage("player >> {}".format(line))
# except: except:
# pass pass
def connectionMade(self): def connectionMade(self):
self.factory.connected = True self.factory.connected = True
@ -82,10 +82,10 @@ class VLCClientFactory(ClientFactory):
self._playerController._vlcclosed.set() self._playerController._vlcclosed.set()
if not self.connected and not self.timeVLCLaunched: if not self.connected and not self.timeVLCLaunched:
# For circumstances where Syncplay is not connected to VLC and is not reconnecting # For circumstances where Syncplay is not connected to VLC and is not reconnecting
#try: try:
self._process.terminate() self._process.terminate()
#except: # When VLC is already closed except: # When VLC is already closed
# pass pass
class VlcPlayer(BasePlayer): class VlcPlayer(BasePlayer):
@ -139,12 +139,14 @@ class VlcPlayer(BasePlayer):
return return
def initWhenConnected(self): def initWhenConnected(self):
self._client.ui.showErrorMessage(getMessage("vlc-initial-warning")) try:
if not self._vlcready.wait(constants.VLC_OPEN_MAX_WAIT_TIME): if not self._vlcready.wait(constants.VLC_OPEN_MAX_WAIT_TIME):
self._vlcready.set() self._vlcready.set()
self._client.ui.showErrorMessage(getMessage("vlc-failed-connection"), True) self._client.ui.showErrorMessage(getMessage("vlc-failed-connection"), True)
self.reactor.callFromThread(self._client.stop, True,) self.reactor.callFromThread(self._client.stop, True,)
self.reactor.callFromThread(self._client.initPlayer, self,) self.reactor.callFromThread(self._client.initPlayer, self,)
except:
pass
def _fileUpdateClearEvents(self): def _fileUpdateClearEvents(self):
self._durationAsk.clear() self._durationAsk.clear()
@ -514,4 +516,4 @@ class VlcPlayer(BasePlayer):
out.close() out.close()
def sendLine(self, line): def sendLine(self, line):
self.reactor.callFromThread(self._factory.protocol.sendLine, line) self.reactor.callFromThread(self._factory.protocol.sendLine, line)