screenstreamer/screenstreamer/gui.py

158 lines
4.9 KiB
Python

from operator import indexOf
from PySide6 import QtCore, QtWidgets
from generated.mainwindow import Ui_ScreenStreamer
from streamer import Streamer
from reciever import Reciever
from pulse import Pulse
from Xlib import display
from Xlib.ext import randr
class ScreenStreamerGUI(QtWidgets.QMainWindow):
def __init__(self, parent = None) -> None:
QtWidgets.QMainWindow.__init__(self, parent)
self.ui = Ui_ScreenStreamer()
self.ui.setupUi(self)
displays = self.get_displays()
print(displays)
for disp in displays:
self.ui.displaySelect.addItem("{} ({}x{})".format(disp['name'], disp['width'], disp['height']), userData=disp)
audiodevices = Pulse.get_audio_inputs()
print(audiodevices)
self.ui.audioSource.addItem('No Audio', userData=-1) # always add this option
for audio in audiodevices:
text = audio['description'] if audio['description'] else audio['name']
if audio.get('monitor', False):
text += ' (Monitor)'
self.ui.audioSource.addItem(text, userData=audio['id'])
if audio.get('isdefault', False):
self.ui.audioSource.setCurrentIndex(indexOf(audiodevices, audio))
self.streamer = None
self.receiver = None
def get_displays(self):
disp = display.Display()
screen = disp.screen()
window = screen.root
res = randr.get_screen_resources(window)
result = list()
allwidth = 0
allheight = 0
for output in res.outputs:
params = disp.xrandr_get_output_info(output, res.config_timestamp)
if not params.crtc:
continue # non connected display ports
crtc = disp.xrandr_get_crtc_info(params.crtc, res.config_timestamp)
result.append({'name': params.name , 'width': crtc.width, 'height': crtc.height, 'x': crtc.x, 'y': crtc.y})
if crtc.width + crtc.x > allwidth:
allwidth = crtc.width + crtc.x
if crtc.height + crtc.y > allheight:
allheight = crtc.height + crtc.y
result.append({'name': 'All', 'width': allwidth, 'height': allheight, 'x': 0, 'y': 0})
return result
def format_display(self, displayinfo):
return ":0.0+{},{}".format(displayinfo['x'], displayinfo['y'])
def format_screensize(self, displayinfo):
return "{}:{}".format(displayinfo['width'], displayinfo['height'])
@QtCore.Slot()
def stream_pressed(self):
if self.streamer:
# stream already running -> stopping
self.streamer.stop()
self.ui.streamBtn.setEnabled(False)
return
displaydata = self.ui.displaySelect.currentData()
self.streamer = Streamer(
self.format_display(displaydata),
self.format_screensize(displaydata),
self.ui.videoCodec.currentText(),
self.ui.audioSource.currentData(),
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.set_stream_status(True)
self.ui.statusbar.showMessage('stream started')
@QtCore.Slot()
def recieve_pressed(self):
if self.receiver:
# recieve already running -> stopping
self.receiver.stop()
self.ui.recieveBtn.setEnabled(False)
return
self.receiver = Reciever(
self.ui.protocolSelect.currentText().lower(),
"{}:{}".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.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)
self.ui.listenAddr.setEnabled(not status)
self.ui.listenPort.setEnabled(not status)
self.ui.disableAudio.setEnabled(not status)
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)
self.ui.displaySelect.setEnabled(not status)
self.ui.videoCodec.setEnabled(not status)
self.ui.audioSource.setEnabled(not status)
self.ui.sendto.setEnabled(not status)
self.ui.streamPort.setEnabled(not status)
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)