首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在Gtk对话框中显示视频?

如何在Gtk对话框中显示视频?
EN

Stack Overflow用户
提问于 2016-11-12 21:15:22
回答 2查看 2.2K关注 0票数 1

我想在对话框中显示视频。

因此,我创建了一个Gst.DrawingArea和一个带有Gst.Element "playbin“的Gst.Pipeline

我创建了一个小示例,它会打开一个带有按钮的窗口。如果单击该按钮,则会打开对话框,并应播放视频。但我只听到了视频的声音。

在另一个只有一个窗口和一个DrawingArea的例子中,它工作得很好。

有没有可能在Gtk.Dialog中播放视频?

我使用的是Python 3.5.2。

编辑:

代码语言:javascript
复制
#!/usr/bin/python3

from os import path

import gi
gi.require_version('Gst', '1.0')
gi.require_version('Gtk', '3.0')
gi.require_version('GdkX11', '3.0')
gi.require_version('GstVideo', '1.0')
from gi.repository import Gst, Gtk, GLib, GdkX11, GstVideo

from gi.repository import GObject


GObject.threads_init()
Gst.init(None)
filename = "/path/to/movie.avi"
uri = 'file://' + filename


class DialogExample(Gtk.Dialog):

def __init__(self, parent):
    Gtk.Dialog.__init__(self, "My Dialog", parent, 0,
        (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
         Gtk.STOCK_OK, Gtk.ResponseType.OK))

    self.drawingarea = Gtk.DrawingArea.new()

    self.drawingarea.connect('draw', self.on_draw)
    #self.drawingarea.connect('realize', self.on_realize)
    self.drawingarea.connect('unrealize', self.on_unrealize)
    self.drawingarea.set_size_request(800, 600)
    self.set_default_size(1000, 800)

    self.btn_Play = Gtk.Button.new_with_label("Play")
    self.btn_Play.connect('clicked', self.on_click)

    box = self.get_content_area()
    box.add(self.drawingarea)
    box.add(self.btn_Play)

    # Create GStreamer pipeline
    self.pipeline = Gst.Pipeline()

    # Create bus to get events from GStreamer pipeline
    self.bus = self.pipeline.get_bus()
    self.bus.add_signal_watch()
    self.bus.connect('message::eos', self.on_eos)
    self.bus.connect('message::error', self.on_error)

    # This is needed to make the video output in our DrawingArea:
    self.bus.enable_sync_message_emission()
    self.bus.connect('sync-message::element', self.on_sync_message)

    # Create GStreamer elements
    self.playbin = Gst.ElementFactory.make('playbin', None)

    # Add playbin to the pipeline
    self.pipeline.add(self.playbin)

    # Set properties
    self.playbin.set_property('uri', uri)

    self.show_all()


def on_click(self, button):
    if self.playbin.get_state(0).state == Gst.State.PAUSED:
        self.pipeline.set_state(Gst.State.PLAYING)
        button.set_label("Stop")
    else:
        self.pipeline.set_state(Gst.State.PAUSED)
        button.set_label("Play")

def on_realize(self, widget, data=None):
    print("on_relaize")

    window = widget.get_window()
    self.xid = window.get_xid()
    self.playbin.set_window_handle(self.xid)


def on_draw(self, widget, cr):
    print("ondraw", self.playbin.get_state(0).state)
    if self.playbin.get_state(0).state < Gst.State.PAUSED:
        allocation = widget.get_allocation()

        cr.set_source_rgb(0, 0, 0)
        cr.rectangle(0, 0, allocation.width, allocation.height)
        cr.fill()

    self.on_realize(widget)


def on_unrealize(self, widget, data=None):
    # to prevent racing conditions when closing the window while playing
    self.playbin.set_state(Gst.State.NULL)
    self.pipeline.set_state(Gst.State.NULL)

def on_sync_message(self, bus, msg):
    if msg.get_structure().get_name() == 'prepare-window-handle':
        print('prepare-window-handle')

        print('on_sync', self.xid)

        print(msg)
        print(msg.src)


def on_eos(self, bus, msg):
    print('on_eos(): seeking to start of video')
    self.pipeline.seek_simple(
        Gst.Format.TIME,
        Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
        0
    )

def on_error(self, bus, msg):
    print('on_error():', msg.parse_error())



class DialogWindow(Gtk.Window):

def __init__(self):
    Gtk.Window.__init__(self, title="Dialog Example")

    self.set_border_width(6)

    button = Gtk.Button("Open dialog")
    button.connect("clicked", self.on_button_clicked)

    self.add(button)



def on_button_clicked(self, widget):
    dialog = DialogExample(self)


    response = dialog.run()

    if response == Gtk.ResponseType.OK:
        print("The OK button was clicked")
    elif response == Gtk.ResponseType.CANCEL:
        print("The Cancel button was clicked")

    dialog.destroy()


win = DialogWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

编辑2:UI after I pressed the play button

EN

回答 2

Stack Overflow用户

发布于 2018-07-27 02:07:19

这是另一种方式,使用gstreamer的gtksink。即使一个“讨厌的”合成器正在运行,这也应该是可行的(正如发问者提到的使用Cinnamon的Linux Mint中的问题):

代码语言:javascript
复制
#!/usr/bin/env python3

import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Gst", "1.0")
from gi.repository import Gtk, Gst

import os, sys

Gst.init(None)
Gst.init_check(None)


class PlayerWidget(Gtk.Box):
    """ This is the gtksink widget """
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        self.player = Gst.ElementFactory.make("playbin")

        self.connect('realize', self.on_realize)

    def on_realize(self, widget):
        playerFactory = self.player.get_factory()
        gtksink = playerFactory.make('gtksink')
        self.player.set_property("video-sink", gtksink)

        self.pack_start(gtksink.props.widget, True, True, 0)
        gtksink.props.widget.show()


class VideoDialog(Gtk.Dialog):
    def __init__(self, parent, filename):
        Gtk.Dialog.__init__(self, "VideoDialog", parent, 0,
                            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                             Gtk.STOCK_OK, Gtk.ResponseType.OK))
        self.filename = filename
        self.__setupUi()

    def __setupUi(self):
        self.set_default_size(800, 400)

        self.playerWidget = PlayerWidget(parent=self)
        self.playerWidget.set_size_request(800, 450)

        self.player = self.playerWidget.player
        self.player.set_property("uri", self.filename)

        self.btnPlay = Gtk.Button(label="Play")
        self.btnPlay.connect("clicked", self.on_btnPlay_clicked)

        self.hboxBtn01 = Gtk.Box()
        self.hboxBtn01.add(self.btnPlay)

        self.vbox_intern = self.get_content_area()
        self.vbox_intern.add(self.playerWidget)
        self.vbox_intern.add(self.hboxBtn01)

        self.show_all()

    def on_btnPlay_clicked(self, widget):
        playerState = self.player.get_state(Gst.SECOND).state
        if playerState <= Gst.State.PAUSED:
            self.player.set_state(Gst.State.PLAYING)
            self.btnPlay.set_label("Pause")
        elif playerState is Gst.State.PLAYING:
            self.player.set_state(Gst.State.PAUSED)
            self.btnPlay.set_label("Play")


class MainWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="Open VideoDialog")

        self.filename = "https://www.freedesktop.org/software/gstreamer-sdk" + \
                                        "/data/media/sintel_trailer-480p.webm"
        self.set_border_width(40)
        self.set_default_size(200, 110)
        button = Gtk.Button("Don't push the button!")
        button.connect("clicked", self.on_button_clicked)
        self.add(button)

    def on_button_clicked(self, widget):
        videoDialog = VideoDialog(self, self.filename)
        videoDialog.set_transient_for(self)
        videoDialog.set_modal(True)

        if Gtk.ResponseType.OK == videoDialog.run():
            print("Response: OK")
        else:
            print("Response: Cancel")

        videoDialog.player.set_state(Gst.State.NULL)
        videoDialog.destroy()

win = MainWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

编辑:在基于debian的发行版中,gstreamer的gtksink似乎不在它所属的包中(即gst-plugins-good)。在Debian9上,它是gst-plugins-bad(?)的一部分。在Ubuntu18.04上,gst-inspect1.0 gtksink声称它是gst-plugins-good的一部分,但它不是。它在gstreamer1.0-gtk3中。所以你必须安装...?

票数 0
EN

Stack Overflow用户

发布于 2020-11-05 20:45:20

vishal-mote,我刚刚添加了文件选择器对话框,并将uri/url编码添加到file://,以便gtk应用程序播放选定的视频。

代码语言:javascript
复制
#!/usr/bin/env python3

gi.require_version("Gtk", "3.0")
gi.require_version("Gst", "1.0")
from gi.repository import Gtk, Gst
from urllib.parse import urlparse 
from urllib.parse import quote
import os, sys

Gst.init(None)
Gst.init_check(None)


class PlayerWidget(Gtk.Box):
    """ This is the gtksink widget """
    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        self.player = Gst.ElementFactory.make("playbin")

        self.connect('realize', self.on_realize)

    def on_realize(self, widget):
        playerFactory = self.player.get_factory()
        gtksink = playerFactory.make('gtksink')
        self.player.set_property("video-sink", gtksink)

        self.pack_start(gtksink.props.widget, True, True, 0)
        gtksink.props.widget.show()


class VideoDialog(Gtk.Dialog):
    def __init__(self, parent, filename):
        Gtk.Dialog.__init__(self, "VideoDialog", parent, 0,
                            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
                             Gtk.STOCK_OK, Gtk.ResponseType.OK))
        self.filename = filename
        self.__setupUi()

    def __setupUi(self):
        self.set_default_size(800, 400)

        self.playerWidget = PlayerWidget(parent=self)
        self.playerWidget.set_size_request(800, 450)

        self.player = self.playerWidget.player
        self.player.set_property("uri", self.filename)

        self.btnPlay = Gtk.Button(label="Play")
        self.btnPlay.connect("clicked", self.on_btnPlay_clicked)

        self.hboxBtn01 = Gtk.Box()
        self.hboxBtn01.add(self.btnPlay)

        self.vbox_intern = self.get_content_area()
        self.vbox_intern.add(self.playerWidget)
        self.vbox_intern.add(self.hboxBtn01)

        self.show_all()



    def on_btnPlay_clicked(self, widget):
        playerState = self.player.get_state(Gst.SECOND).state
        if playerState <= Gst.State.PAUSED:
            self.player.set_state(Gst.State.PLAYING)
            self.btnPlay.set_label("Pause")
        elif playerState is Gst.State.PLAYING:
            self.player.set_state(Gst.State.PAUSED)
            self.btnPlay.set_label("Play")


class MainWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="Open VideoDialog")

        self.filename = "https://www.freedesktop.org/software/gstreamer-sdk" + \
                                        "/data/media/sintel_trailer-480p.webm"
        self.set_border_width(40)
        self.set_default_size(200, 110)
        button = Gtk.Button("Choose File!")
        button.connect("clicked", self.on_file_clicked)
        self.add(button)
        #uncomment below to start the player as if button is pressed
        #self.on_button_clicked(Gtk.Button)
        
        
        
    def on_file_clicked(self, widget):
        dialog = Gtk.FileChooserDialog(
            title="Please choose a file", parent=self, action=Gtk.FileChooserAction.OPEN
        )
        dialog.add_buttons(
            Gtk.STOCK_CANCEL,
            Gtk.ResponseType.CANCEL,
            Gtk.STOCK_OPEN,
            Gtk.ResponseType.OK,
        )

        self.add_filters(dialog)

        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            print("Open clicked")
            print("File selected: " + dialog.get_filename())
            self.filename = quote(dialog.get_filename())
            #encode URI to file://<path+filename>
            self.filename = "file://"+self.filename
            print(self.filename)
            # when the file is selected cose the file dialog
            dialog.destroy()
            self.on_button_clicked(Gtk.Button)
            
        elif response == Gtk.ResponseType.CANCEL:
            print("Cancel clicked")

        dialog.destroy()

    def add_filters(self, dialog):
        filter_video = Gtk.FileFilter()
        filter_video.set_name("Video File")
        filter_video.add_mime_type("video/*")
        dialog.add_filter(filter_video)

        filter_any = Gtk.FileFilter()
        filter_any.set_name("Any files")
        filter_any.add_pattern("*")
        dialog.add_filter(filter_any)
        
        

    def on_button_clicked(self, widget):
        videoDialog = VideoDialog(self, self.filename)
        videoDialog.set_transient_for(self)
        videoDialog.set_modal(True)

        if Gtk.ResponseType.OK == videoDialog.run():
            print("Response: OK")
        else:
            print("Response: Cancel")

        videoDialog.player.set_state(Gst.State.NULL)
        videoDialog.destroy()

win = MainWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40563216

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档