Python с pygobject, SIGSEGV при автозапуске в GNOME - PullRequest
0 голосов
/ 08 мая 2020

Я работаю над сценарием для установки видео в качестве видеообоев для GNOME. Сценарий работает, как ожидалось, за исключением того, что он выдает SIGSEGV при автозапуске с файлом .desktop. У меня есть некоторый опыт работы с python, но не с pygobject, пожалуйста, посоветуйте.

Файл .desktop:

[Desktop Entry]
Type=Application
Name=Video Wallpaper
Exec=video-wallpaper -p 5
StartupNotify=false
Terminal=false
Icon=
Categories=System;Monitor;

Скрипт python:

#!/bin/python
import argparse
import subprocess
import os
import pathlib
import signal
import json
import time

import gi
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from PIL import Image, ImageFilter

gi.require_version('Gtk', '3.0')
gi.require_version('GtkClutter', '1.0')
gi.require_version('ClutterGst', '3.0')
from gi.repository import Gtk, Gdk, GtkClutter, Clutter, ClutterGst, Gio

HOME = os.environ['HOME']
RC_FILENAME = '.wallpaperrc'
RC_PATH = HOME + '/' + RC_FILENAME

gso = Gio.Settings.new('org.gnome.desktop.background')
ORI_WALLPAPER_URI = gso.get_string('picture-uri')
BLUR_WALLPAPER_PATH = '/tmp/video-wallpaper.png'

config = {
    'video_path': '',
    'audio_volume': 0.5,
    'is_mute': False,
    'blur_wallpaper': True,
    'blur_radius': 5
}
video_wallpaper = None


def monitor_detect():
    display = Gdk.Display.get_default()
    monitor = display.get_primary_monitor()
    geometry = monitor.get_geometry()
    scale_factor = monitor.get_scale_factor()
    width = scale_factor * geometry.width
    height = scale_factor * geometry.height
    return width, height


def set_blur_wallpaper(video_path):
    # Extract first frame (use ffmpeg)
    subprocess.call('ffmpeg -y -i {} -vframes 1 {}'.format(video_path, BLUR_WALLPAPER_PATH), shell=True)
    blur_wallpaper = Image.open(BLUR_WALLPAPER_PATH)
    blur_wallpaper = blur_wallpaper.filter(ImageFilter.GaussianBlur(config['blur_radius']))
    blur_wallpaper.save(BLUR_WALLPAPER_PATH)
    gso.set_string('picture-uri', pathlib.Path(BLUR_WALLPAPER_PATH).resolve().as_uri())


def generate_rc():
    with open(RC_PATH, 'w') as f:
        json.dump(config, f)


def rc_modified_callback():
    with open(RC_PATH, 'r') as new_f:
        new_config = json.load(new_f)
        if new_config['video_path'] != config['video_path']:
            video_wallpaper.set_filename(new_config['video_path'])
            if config['blur_wallpaper']:
                set_blur_wallpaper(new_config['video_path'])
        if new_config['audio_volume'] != config['audio_volume']:
            video_wallpaper.set_audio_volume(new_config['audio_volume'])
        config.update(new_config)


def start_application():
    Gtk.main()


def quit_application(*args):
    Gtk.main_quit()
    gso.set_string('picture-uri', ORI_WALLPAPER_URI)


signal.signal(signal.SIGTERM, quit_application)
signal.signal(signal.SIGINT, quit_application)


class VideoWallpaper:
    def __init__(self, rc=None):
        # Settings
        self.video_path = rc['video_path']
        self.audio_volume = rc['audio_volume']
        self.is_mute = rc['is_mute']
        bg_color = Clutter.Color.get_static(Clutter.StaticColor.BLACK)

        # Monitor Detect
        self.width, self.height = monitor_detect()

        # Actors initialize
        GtkClutter.init()
        self.embed = GtkClutter.Embed()
        self.main_actor = self.embed.get_stage()
        self.wallpaper_actor = Clutter.Actor()
        self.wallpaper_actor.set_size(self.width, self.height)
        self.main_actor.add_child(self.wallpaper_actor)
        self.main_actor.set_background_color(bg_color)

        # Video initialize
        ClutterGst.init()
        self.video_playback = ClutterGst.Playback()
        self.video_content = ClutterGst.Content()
        self.video_content.set_player(self.video_playback)

        # Playback settings
        self.video_playback.set_filename(self.video_path)
        self.video_playback.set_playing(True)
        self.video_playback.connect('eos', self.loop_playback)
        self.wallpaper_actor.set_content(self.video_content)

        # Window settings
        self.window = Gtk.Window(title='Desktop')
        self.window.add(self.embed)
        self.window.set_type_hint(Gdk.WindowTypeHint.DESKTOP)
        self.window.set_size_request(self.width, self.height)
        self.window.show_all()

        self.set_audio_volume(0.0 if self.is_mute else self.audio_volume)

    def loop_playback(self, playback):
        playback.set_progress(0.0)
        playback.set_audio_volume(self.audio_volume)
        playback.set_playing(True)

    def set_filename(self, filename):
        self.video_playback.set_playing(False)
        self.video_path = filename
        self.video_playback.set_filename(filename)
        self.video_playback.set_progress(0.0)
        self.video_playback.set_playing(True)

    def set_audio_volume(self, volume):
        self.audio_volume = volume
        self.video_playback.set_audio_volume(volume)


class FileModifiedHandler(FileSystemEventHandler):
    def __init__(self, path, file_name, callback):
        self.file_name = file_name
        self.callback = callback

        # set observer to watch for changes in the directory
        self.observer = Observer()
        self.observer.schedule(self, path, recursive=False)
        self.observer.start()

    def on_moved(self, event):
        print(event)
        if not event.is_directory and event.dest_path.endswith(self.file_name):
            self.callback()  # call callback

    def on_modified(self, event):
        if not event.is_directory and event.src_path.endswith(self.file_name):
            self.callback()  # call callback


def main():
    global config
    global video_wallpaper

    if not os.path.isfile(RC_PATH):
        generate_rc()
        print('Generated .wallpaperrc in home directory, you have to configure it first')
        exit(0)
    else:
        with open(RC_PATH, 'r') as f:
            config = json.load(f)
        FileModifiedHandler(path=HOME, file_name=RC_FILENAME, callback=rc_modified_callback)
        video_wallpaper = VideoWallpaper(rc=config)
        if config['blur_wallpaper']:
            set_blur_wallpaper(config['video_path'])
        start_application()


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--deamonize', action='store_true')
    parser.add_argument('-p', '--pause', type=int, default=0)
    args = parser.parse_args()
    time.sleep(args.pause)
    if args.deamonize:
        # TODO
        pass
    else:
        main()

Ошибка:

video-wallpaper[232142]: segfault at 10 ip 00007fbd99275d74 sp 00007ffeecea77c8 error 4 in libpthread-2.31.so[7fbd99271000+10000]

Спасибо.

...