error handling
This commit is contained in:
parent
7339f52bcf
commit
2399277971
|
@ -75,9 +75,8 @@ class ScreenStreamerGUI(QtWidgets.QMainWindow):
|
|||
def stream_pressed(self):
|
||||
if self.streamer:
|
||||
# stream already running -> stopping
|
||||
self.streamer = None
|
||||
self.ui.statusbar.showMessage('stream stopped')
|
||||
self.ui.streamBtn.setText('Stream')
|
||||
self.streamer.stop()
|
||||
self.ui.streamBtn.setEnabled(False)
|
||||
return
|
||||
|
||||
displaydata = self.ui.displaySelect.currentData()
|
||||
|
@ -88,18 +87,17 @@ class ScreenStreamerGUI(QtWidgets.QMainWindow):
|
|||
self.ui.protocolSelect.currentText().lower(),
|
||||
"{}:{}".format(self.ui.sendto.text(), self.ui.streamPort.value())
|
||||
)
|
||||
self.streamer.process_manager.process_terminated.connect(self.stream_terminated)
|
||||
self.streamer.start()
|
||||
self.ui.streamBtn.setText('Stop Stream')
|
||||
# TODO: add feedback on error
|
||||
self.set_stream_status(True)
|
||||
self.ui.statusbar.showMessage('stream started')
|
||||
|
||||
@QtCore.Slot()
|
||||
def recieve_pressed(self):
|
||||
if self.receiver:
|
||||
# stream already running -> stopping
|
||||
self.receiver = None
|
||||
self.ui.statusbar.showMessage('recieve stopped')
|
||||
self.ui.recieveBtn.setText('Recieve')
|
||||
# recieve already running -> stopping
|
||||
self.receiver.stop()
|
||||
self.ui.recieveBtn.setEnabled(False)
|
||||
return
|
||||
|
||||
self.receiver = Reciever(
|
||||
|
@ -107,7 +105,44 @@ class ScreenStreamerGUI(QtWidgets.QMainWindow):
|
|||
"{}:{}".format(self.ui.listenAddr.text(), self.ui.listenPort.value()),
|
||||
self.ui.disableAudio.checkState() == 'Checked'
|
||||
)
|
||||
self.receiver.process_manager.process_terminated.connect(self.recieve_terminated)
|
||||
self.receiver.start()
|
||||
self.ui.recieveBtn.setText('Stop Recieve')
|
||||
# TODO: add feedback on error
|
||||
self.set_recieve_status(True)
|
||||
self.ui.statusbar.showMessage('recieve started')
|
||||
|
||||
def set_recieve_status(self, status: bool):
|
||||
"""status = True - stream is running"""
|
||||
self.ui.recieveBtn.setEnabled(True)
|
||||
if status:
|
||||
self.ui.recieveBtn.setText('Stop Recieve')
|
||||
else:
|
||||
self.ui.recieveBtn.setText('Recieve')
|
||||
|
||||
def set_stream_status(self, status: bool):
|
||||
"""status = True - stream is running"""
|
||||
self.ui.streamBtn.setEnabled(True)
|
||||
if status:
|
||||
self.ui.streamBtn.setText('Stop Stream')
|
||||
else:
|
||||
self.ui.streamBtn.setText('Stream')
|
||||
|
||||
def show_error(self, tag: str, returncode: int, errormsg: str):
|
||||
if errormsg:
|
||||
error = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, tag + ' Error', tag + ' Error: ' + errormsg, QtWidgets.QMessageBox.Ok, self)
|
||||
error.show()
|
||||
error.exec()
|
||||
|
||||
@QtCore.Slot(int, str)
|
||||
def recieve_terminated(self, returncode, errormsg):
|
||||
self.receiver = None
|
||||
self.ui.statusbar.showMessage('recieve stopped')
|
||||
self.show_error('Recieve', returncode, errormsg)
|
||||
self.set_recieve_status(False)
|
||||
|
||||
@QtCore.Slot(int, str)
|
||||
def stream_terminated(self, returncode, errormsg):
|
||||
self.streamer = None
|
||||
self.ui.statusbar.showMessage('stream stopped')
|
||||
self.show_error('Stream', returncode, errormsg)
|
||||
self.set_stream_status(False)
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
from PySide6.QtCore import QObject, Signal
|
||||
from threading import Thread
|
||||
import subprocess
|
||||
|
||||
class ProcManager(QObject):
|
||||
|
||||
process_terminated = Signal(int, str)
|
||||
|
||||
def __init__(self) -> None:
|
||||
super(ProcManager, self).__init__()
|
||||
|
||||
self.thre = None
|
||||
self.proc = None
|
||||
|
||||
def start(self, proc):
|
||||
# this method might override the old process and thread
|
||||
self.proc = proc
|
||||
|
||||
self.thre = Thread(target=self.detect_end)
|
||||
self.thre.start()
|
||||
|
||||
def stop(self):
|
||||
if self.proc:
|
||||
self.proc.terminate()
|
||||
|
||||
try:
|
||||
self.proc.wait(1)
|
||||
except subprocess.TimeoutExpired as e:
|
||||
self.proc.kill()
|
||||
|
||||
if self.thre:
|
||||
self.thre.join()
|
||||
self.thre = None
|
||||
|
||||
def detect_end(self):
|
||||
# wait for the process to terminate
|
||||
while True:
|
||||
try:
|
||||
self.proc.wait(1)
|
||||
break
|
||||
except subprocess.TimeoutExpired as e:
|
||||
continue
|
||||
|
||||
returncode = self.proc.returncode
|
||||
errorstream = self.proc.stderr.read()
|
||||
if isinstance(errorstream, bytes):
|
||||
errorstream = errorstream.decode('utf-8')
|
||||
|
||||
self.proc = None
|
||||
|
||||
print('Process Terminated:', returncode, errorstream)
|
||||
|
||||
self.process_terminated.emit(returncode, errorstream)
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import subprocess
|
||||
from procmanager import ProcManager
|
||||
|
||||
class Reciever:
|
||||
|
||||
|
@ -6,7 +7,7 @@ class Reciever:
|
|||
self.protocol = protocol # should be 'tcp' or 'udp'
|
||||
self.target = target
|
||||
self.disable_audio = disable_audio
|
||||
self.proc = None
|
||||
self.process_manager = ProcManager()
|
||||
|
||||
def __del__(self) -> None:
|
||||
self.stop()
|
||||
|
@ -14,7 +15,7 @@ class Reciever:
|
|||
def start(self):
|
||||
# currently there is no direct ffplay support in the ffmpeg package
|
||||
|
||||
args = ['ffplay', '-fflags', 'nobuffer', '-flags', 'low_delay', '-f', 'mpegts']
|
||||
args = ['ffplay', '-hide_banner', '-loglevel', 'error', '-fflags', 'nobuffer', '-flags', 'low_delay', '-f', 'mpegts']
|
||||
|
||||
if self.disable_audio:
|
||||
args.append('-an')
|
||||
|
@ -22,12 +23,9 @@ class Reciever:
|
|||
# the address
|
||||
args.append(self.protocol+ '://' + self.target + '?listen')
|
||||
|
||||
self.proc = subprocess.Popen(args)
|
||||
proc = subprocess.Popen(args, encoding='utf-8', shell=False, text=True, stderr=subprocess.PIPE)
|
||||
self.process_manager.start(proc)
|
||||
|
||||
def stop(self):
|
||||
if self.proc:
|
||||
self.proc.terminate()
|
||||
self.proc.wait(1)
|
||||
self.proc.kill()
|
||||
self.proc = None
|
||||
self.process_manager.stop()
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import ffmpeg
|
||||
from procmanager import ProcManager
|
||||
|
||||
class Streamer:
|
||||
|
||||
|
@ -8,14 +9,14 @@ class Streamer:
|
|||
self.audioindex = audioindex
|
||||
self.protocol = protocol # should be 'tcp' or 'udp'
|
||||
self.target = target
|
||||
self.proc = None
|
||||
self.process_manager = ProcManager()
|
||||
|
||||
def __del__(self) -> None:
|
||||
self.stop()
|
||||
|
||||
def start(self):
|
||||
streams = []
|
||||
self.input = ffmpeg.input(self.screendef, f='x11grab', r=60, s=self.screensize)
|
||||
self.input = ffmpeg.input(self.screendef, f='x11grab', r=60, s=self.screensize, hide_banner='-y', loglevel='error')
|
||||
streams.append(self.input)
|
||||
|
||||
if self.audioindex != -1:
|
||||
|
@ -23,13 +24,10 @@ class Streamer:
|
|||
streams.append(self.audio)
|
||||
|
||||
self.output = ffmpeg.output(*streams, self.protocol + '://' + self.target, f='mpegts', vcodec='nvenc_hevc', tune='zerolatency')
|
||||
self.proc = ffmpeg.run_async(self.output)
|
||||
proc = ffmpeg.run_async(self.output, pipe_stderr=True)
|
||||
self.process_manager.start(proc)
|
||||
|
||||
def stop(self):
|
||||
if self.proc:
|
||||
self.proc.terminate()
|
||||
self.proc.wait(1)
|
||||
self.proc.kill()
|
||||
self.proc = None
|
||||
self.process_manager.stop()
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue