Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  headless-monitor-tests.py

  Sprache: Python
 

import sys
import os
import subprocess
import gi

gi.require_version('Gdk''4.0')

from gi.repository import GLib, Gdk
from pydbus import SessionBus

verbose = True

screen_cast = None
monitors = {}
waiting = False
done = False
monitor_model = None
display = None

def terminate():
    for key in monitors:
        monitor = monitors[key];
        pipeline = monitor['pipeline'];
        pipeline.terminate()
    sys.exit(1)

def stream_added_closure(name):
    def stream_added(node_id):
        if verbose:
            print('pipewire stream added')

        monitor = monitors[name];

        freq = monitor['freq'];
        width = monitor['width'];
        height = monitor['height'];
        # FIXME scale = monitor['scale'];

        # Use gstreamer out-of-process, since the gst gl support gets
        # itself into a twist with its wayland connection when monitors
        # disappear
        pipeline_desc = f'gst-launch-1.0 pipewiresrc path={node_id} ! video/x-raw,max-framerate={freq}/1,width={width},height={height} ! videoconvert ! glimagesink' # >& gstreamer-monitor.log'
        if verbose:
            print(f'launching {pipeline_desc}')
        monitor['pipeline'] = subprocess.Popen([pipeline_desc], shell=True)

    return stream_added

def add_monitor(name, width, height, scale, freq):
    if verbose:
        print(f'add monitor {name}: {width}x{height}, scale {scale}, frequency {freq}')
    session_path = screen_cast.CreateSession({})
    session = bus.get('org.gnome.Mutter.ScreenCast', session_path)
    monitors[name] = {
        'session': session,
        'width': width,
        'height': height,
        'scale': scale,
        'freq': freq
    }
    stream_path = session.RecordVirtual({})
    stream = bus.get('org.gnome.Mutter.ScreenCast', stream_path)
    stream.onPipeWireStreamAdded = stream_added_closure(name)
    session.Start()

def remove_monitor(name):
    if verbose:
        print(f'remove monitor {name}')
    try:
        monitor = monitors[name];
        pipeline = monitor['pipeline']
        pipeline.kill()
        session = monitor['session']
        session.Stop()
    except KeyError:
        print('failed to remove monitor')
    monitors[name] = None

expected_change = None
loop = None

def quit_cb(loop):
    loop.quit()
    print('timed out while waiting')

def wait(millis):
    global loop
    before = GLib.get_monotonic_time()
    loop = GLib.MainLoop()
    GLib.timeout_add(millis, quit_cb, loop)
    loop.run()
    if verbose:
        time = (GLib.get_monotonic_time() - before) / 1000
        print(f'waited for {time} milliseconds')

def monitors_changed(monitors, position, removed, added):
    global expected_change

    assert expected_change != None'No change expected'
    assert position == expected_change['position'], 'Unexpected position in monitors-changed'
    assert removed == expected_change['removed'], 'Unexpected removed in monitors-changed'
    assert added == expected_change['added'], 'Unexpected added in monitors-changed'

    if verbose:
        print('got expected monitors-changed signal')

    expected_change = None
    loop.quit()

def launch_observer():
    global monitor_model
    global display

    if display == None:
        display = Gdk.Display.open(os.getenv('WAYLAND_DISPLAY'))

    if verbose:
        print('launch observer')

    monitor_model = display.get_monitors()
    assert monitor_model.get_n_items() == 0'Unexpected initial monitors'
    monitor_model.connect('items-changed', monitors_changed)

def expect_monitors_changed(position, removed, added, timeout):
    global expected_change
    expected_change = {
        'position' : position,
        'removed' : removed,
        'added' : added
    }
    wait(timeout)
    assert expected_change == None'Expected change did not happen'

def got_connector(monitor, pspec):
    loop.quit()

def expect_monitor(position, width, height, scale, freq):
    assert monitor_model.get_n_items() > position, f'Monitor {position} not present'
    monitor = monitor_model.get_item(position)
    if monitor.get_connector() == None:
        if verbose:
            print('waiting for connector')
        handler = monitor.connect('notify::connector', got_connector)
        wait(500)
        monitor.disconnect(handler)
    assert monitor.get_connector() != None'Monitor has no connector'
    assert monitor.is_valid(), 'Monitor is not valid'
    geometry = monitor.get_geometry()
    assert geometry.width == width, 'Unexpected monitor width'
    assert geometry.height == height, 'Unexpected monitor height'
    assert monitor.get_scale_factor() == scale, 'Unexpected scale factor'
    assert monitor.get_refresh_rate() == freq, 'Unexpected monitor frequency'
    if verbose:
        print(f'monitor {position}: {geometry.width}x{geometry.height} frequency {monitor.get_refresh_rate()} scale {monitor.get_scale_factor()} model \'{monitor.get_model()}\' connector \'{monitor.get_connector()}\'')

def run_commands():
    try:
        launch_observer()

        add_monitor('0', width=100, height=100, scale=1, freq=60)
        expect_monitors_changed(00110000)
        expect_monitor (position=0, width=100, height=100, scale=1, freq=60000)

        add_monitor('1', width=1024, height=768, scale=1, freq=144)
        expect_monitors_changed(10110000)
        expect_monitor (position=1, width=1024, height=768, scale=1, freq=144000)

        remove_monitor('0')
        expect_monitors_changed(01011000# mutter takes 10 seconds to remove it

        remove_monitor('1')
        expect_monitors_changed(01011000)
    except AssertionError as e:
        print(f'Error: {e}')
        terminate()

def mutter_appeared(name):
    global screen_cast
    global done
    if verbose:
        print('mutter appeared on the bus')
    screen_cast = bus.get('org.gnome.Mutter.ScreenCast',
                          '/org/gnome/Mutter/ScreenCast')
    run_commands()

    if verbose:
        print ('Done running commands, exiting...')
    done = True

def mutter_vanished():
    global done
    if screen_cast != None:
        if verbose:
            print('mutter left the bus')
        done = True

bus = SessionBus()
bus.watch_name('org.gnome.Mutter.ScreenCast'0, mutter_appeared, mutter_vanished)

try:
    while not done:
      GLib.MainContext.default().iteration(True)
except KeyboardInterrupt:
    print('Interrupted')

Messung V0.5 in Prozent
C=97 H=96 G=96

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-07-02) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik