This commit is contained in:
wheaney 2024-09-18 13:58:26 -07:00
parent b1d3815bec
commit 8c4a3b46cb
4 changed files with 97 additions and 0 deletions

View File

@ -4,10 +4,13 @@ from .license import BREEZY_GNOME_FEATURES
from .settingsmanager import SettingsManager
from .shortcutdialog import bind_shortcut_settings
from .statemanager import StateManager
from .virtualdisplay import VirtualMonitor
from .xrdriveripc import XRDriverIPC
import gettext
import logging
_ = gettext.gettext
logger = logging.getLogger('breezy_ui')
@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/connected-device.ui')
class ConnectedDevice(Gtk.Box):
@ -28,6 +31,7 @@ class ConnectedDevice(Gtk.Box):
widescreen_mode_switch = Gtk.Template.Child()
widescreen_mode_row = Gtk.Template.Child()
curved_display_switch = Gtk.Template.Child()
add_virtual_display_button = Gtk.Template.Child()
set_toggle_display_distance_start_button = Gtk.Template.Child()
set_toggle_display_distance_end_button = Gtk.Template.Child()
reassign_recenter_display_shortcut_button = Gtk.Template.Child()
@ -55,6 +59,7 @@ class ConnectedDevice(Gtk.Box):
self.follow_mode_switch,
self.follow_threshold_scale,
self.curved_display_switch,
# self.add_virtual_display_button,
self.set_toggle_display_distance_start_button,
self.set_toggle_display_distance_end_button,
self.movement_look_ahead_scale
@ -87,6 +92,7 @@ class ConnectedDevice(Gtk.Box):
self.set_toggle_display_distance_start_button,
self.set_toggle_display_distance_end_button
])
self.add_virtual_display_button.connect('clicked', self.on_add_virtual_display)
self.state_manager = StateManager.get_instance()
self.state_manager.bind_property('follow-mode', self.follow_mode_switch, 'active', GObject.BindingFlags.DEFAULT)
@ -166,6 +172,12 @@ class ConnectedDevice(Gtk.Box):
for widget in widgets:
widget.connect('clicked', lambda *args, widget=widget: on_set_display_distance_toggle(widget))
reload_display_distance_toggle_button(widget)
def on_add_virtual_display(self, widget):
VirtualMonitor(1920, 1080, self.on_virtual_display_ready).create()
def on_virtual_display_ready(self):
logger.info("Virtual display ready")
def _on_widget_destroy(self, widget):
self.state_manager.unbind_property('follow-mode', self.follow_mode_switch, 'active')

View File

@ -84,6 +84,19 @@
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes"><!-- adjustment slider -->Virtual monitors</property>
<property name="valign">2</property>
<child>
<object class="GtkButton" id="add_virtual_display_button">
<property name="name">add-virtual-display</property>
<property name="valign">3</property>
<property name="label" translatable="yes">Add</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>

View File

@ -46,6 +46,7 @@ breezydesktop_sources = [
'shortcutdialog.py',
'statemanager.py',
'time.py',
'virtualdisplay.py',
'verify.py',
'window.py'
]

71
ui/src/virtualdisplay.py Normal file
View File

@ -0,0 +1,71 @@
#!/usr/bin/python3
import logging
import sys
import signal
import pydbus
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GLib, GObject, Gst
logger = logging.getLogger('breezy_ui')
screen_cast_iface = 'org.gnome.Mutter.ScreenCast'
screen_cast_session_iface = 'org.gnome.Mutter.ScreenCast.Session'
screen_cast_stream_iface = 'org.gnome.Mutter.ScreenCast.Session'
gst_pipeline_format = "pipewiresrc path=%u ! video/x-raw,max-framerate=120/1,width=%d,height=%d ! videoconvert ! fakesink sync=false"
def _screen_cast_session():
bus = pydbus.SessionBus()
screen_cast = bus.get(screen_cast_iface, '/org/gnome/Mutter/ScreenCast')
session_path = screen_cast.CreateSession([])
logger.info("session path: %s" % session_path)
screen_cast_session = bus.get(screen_cast_iface, session_path)
return screen_cast_session
class VirtualMonitor:
def __init__(self, width, height, on_ready_cb):
self.width = width
self.height = height
self.on_ready_cb = on_ready_cb
Gst.init(None)
def create(self):
session = _screen_cast_session()
stream_path = session.RecordVirtual({
'is-platform': GLib.Variant.new_boolean(True),
})
logger.info("stream path: %s" % stream_path)
bus = pydbus.SessionBus()
self.stream = bus.get(screen_cast_iface, stream_path)
self.stream.onPipeWireStreamAdded = self._on_pipewire_stream_added
session.Start()
def terminate(self):
if self.stream is not None:
self.stream.Stop()
if self.pipeline is not None:
self.pipeline.send_event(Gst.Event.new_eos())
self.pipeline.set_state(Gst.State.NULL)
def _on_message(self, bus, message):
type = message.type
logger.info("message type: %s" % type)
if type == Gst.MessageType.EOS or type == Gst.MessageType.ERROR:
self.terminate()
def _on_pipewire_stream_added(self, node_id):
logger.info("pipe wire stream added: %u" % node_id)
self.pipeline = Gst.parse_launch(gst_pipeline_format % (node_id, self.width, self.height))
self.pipeline.set_state(Gst.State.PLAYING)
self.pipeline.get_bus().connect('message', self._on_message)
self.pipeline.set_state(Gst.State.PAUSED)
self.on_ready_cb()