J'ai créé un lecteur vidéo dans Gtk3 en utilisant Gstreamer dans Python3. Cela fonctionne sauf quand j'ajoute un GtkMenuBar (place 2). Il affichera alors un écran noir, ou échouera avec une exception. L'exception fait référence au XInitThreads
, que j'appelle (Place 1) (j'ai pris cela du projet pitivi) mais cela ne semble pas faire de différence.Lecture d'une vidéo dans Gtk dans une fenêtre avec une barre de menus
Question: Comment est-ce que je fais ce travail?
Autres choses que je voudrais savoir:
- Pourquoi la barre de menus romprait ce?
- Cela va clairement se briser sur tout ce qui n'est pas X, y a-t-il un composant prédéfini à l'abstraction de cette logique et est-ce qu'il y a une plateforme croisée qui me manque?
System:
- python3
- gtk3
- Ubuntu 16,04
L'exception:
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python3: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Le code (en tant que petite une forme aussi pos sible de démontrer le concept):
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gst', '1.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gtk, xlib
from gi.repository import Gst, Gdk, GdkX11, GstVideo
Gst.init(None)
Gst.init_check(None)
# Place 1
from ctypes import cdll
x11 = cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
# [xcb] Unknown request in queue while dequeuing
# [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
# [xcb] Aborting, sorry about that.
# python3: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
# (foo.py:31933): Gdk-WARNING **: foo.py: Fatal IO error 11 (Resource temporarily unavailable) on X server :1.
class PipelineManager(object):
def __init__(self, window, pipeline):
self.window = window
if isinstance(pipeline, str):
pipeline = Gst.parse_launch(pipeline)
self.pipeline = pipeline
bus = pipeline.get_bus()
bus.set_sync_handler(self.bus_callback)
pipeline.set_state(Gst.State.PLAYING)
def bus_callback(self, bus, message):
if message.type is Gst.MessageType.ELEMENT:
if GstVideo.is_video_overlay_prepare_window_handle_message(message):
Gdk.threads_enter()
Gdk.Display.get_default().sync()
win = self.window.get_property('window')
if isinstance(win, GdkX11.X11Window):
message.src.set_window_handle(win.get_xid())
else:
print('Nope')
Gdk.threads_leave()
return Gst.BusSyncReply.PASS
pipeline = Gst.parse_launch('videotestsrc ! xvimagesink sync=false')
window = Gtk.ApplicationWindow()
header_bar = Gtk.HeaderBar()
header_bar.set_show_close_button(True)
# window.set_titlebar(header_bar) # Place 2
drawing_area = Gtk.DrawingArea()
drawing_area.connect('realize', lambda widget: PipelineManager(widget, pipeline))
window.add(drawing_area)
window.show_all()
def on_destroy(win):
try:
Gtk.main_quit()
except KeyboardInterrupt:
pass
window.connect('destroy', on_destroy)
Gtk.main()
Je ne peux pas répondre à la question, mais cela est une question superbe. Sur le sujet, un problème spécifique, pas quelque chose de simple dans la documentation, fournit un MCVE parfait, affiche un message d'erreur, des informations système, le but du code, etc. Cela devrait être un exemple de la façon de poser une question. – oldtechaa