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)