2016-10-17 10 views
5

Stworzyłem odtwarzacz wideo w Gtk3 używając Gstreamer w Pythonie3. Działa, z wyjątkiem sytuacji, gdy dodaję GtkMenuBar (miejsce 2). Zostanie wtedy wyświetlony czarny ekran lub niepowodzenie z wyjątkiem. Wyjątek odwołuje się do XInitThreads, którego wzywam (miejsce 1) (wziąłem to z projektu pitivi), ale nie wydaje się, żeby to było inne.Odtwarzanie wideo w Gtk w oknie z menubarem

Pytanie: Jak mogę to wykonać?

Inne rzeczy, chciałbym wiedzieć:

  1. Dlaczego pasek menu przełamać?
  2. To będzie wyraźnie przerwać wszystko, co nie X, czy jest jakiś wstępnie skompilowany komponent, który streszcza tę logikę i ma poprzeczkę, której mi brakuje?

systemu:

  • python3
  • Gtk3
  • Ubuntu 16,04

Wyjątek:

[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. 

kod (w tak małej postaci jako pos dzialna wykazać pojęcie):

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() 
+1

nie mogę odpowiedzieć na to pytanie, ale jest to wspaniała sprawa. Wątek, konkretny problem, a nie coś prostego w dokumentacji, zapewnia doskonały MCVE, pokazuje komunikat o błędzie, informacje o systemie, cel kodu itp. Powinien to być przykład, jak zadać pytanie. – oldtechaa

Odpowiedz

2

Przy przeszukiwaniu dokumentacji na osobnym numerze natknęłam odniesienie do widgetu gtksink. Wydaje się, że jest to właściwy sposób umieszczania wideo w oknie gtk, ale niestety żaden z tutoriali na ten temat go nie używa.

Korzystanie z widgetu gtksink rozwiązuje wszystkie problemy i znacznie zmniejsza złożoność kodu.

Zmieniony kod:

from pprint import pprint 

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, Gst 
Gst.init(None) 
Gst.init_check(None) 


class GstWidget(Gtk.Box): 
    def __init__(self, pipeline): 
     super().__init__() 
     self.connect('realize', self._on_realize) 
     self._bin = Gst.parse_bin_from_description('videotestsrc', True) 

    def _on_realize(self, widget): 
     pipeline = Gst.Pipeline() 
     factory = pipeline.get_factory() 
     gtksink = factory.make('gtksink') 
     pipeline.add(gtksink) 
     pipeline.add(self._bin) 
     self._bin.link(gtksink) 
     self.pack_start(gtksink.props.widget, True, True, 0) 
     gtksink.props.widget.show() 
     pipeline.set_state(Gst.State.PLAYING) 


window = Gtk.ApplicationWindow() 

header_bar = Gtk.HeaderBar() 
header_bar.set_show_close_button(True) 
window.set_titlebar(header_bar) # Place 2 

widget = GstWidget('videotestsrc') 
widget.set_size_request(200, 200) 

window.add(widget) 

window.show_all() 

def on_destroy(win): 
    try: 
     Gtk.main_quit() 
    except KeyboardInterrupt: 
     pass 

window.connect('destroy', on_destroy) 

Gtk.main() 
Powiązane problemy