How to enable hardware acceleration with python-vlc in Gtk3 application - python

Hello I am writing python application with gtk and vlc. Playback works, but without hardware acceleration.
import vlc
class Player:
def __init__(self):
self.instance = vlc.Instance("--no-xlib")
self.player = self.instance.media_player_new()
def visualize(self,widget):
self.player.set_xwindow(widget.get_window().get_xid())
def playurl(self,url):
media = self.instance.media_new(url)
self.player.set_media(media)
self.player.play()
When I run it I see:
[00007f4dfc014830] main filter error: Failed to create video converter
[00007f4df80af2a0] vdpau_avcodec generic error: Xlib is required for VDPAU
So I decided to remove "--no-xlib" parameter, but now I see this:
[00007f16b40078f0] egl_x11 gl error: Xlib not initialized for threads
Someone said this can help:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
I've added this on start of my main function. But it causes segmentation fault when calling Gtk.main()
def main():
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
builder = Gtk.Builder()
builder.add_from_file(BUILDER_PATH)
mw = MainWin(builder) # class containing widgets loaded from GtkBuilder
mw.Show()
myvlc = Player()
myvlc.visualize(mw.player) # mw.player is GtkDrawingArea
myvlc.playurl("http://livesim.dashif.org/livesim/ato_10/testpic_2s/Manifest.mpd")
Gtk.main() # Crash
if __name__ == "__main__":
main()
PS: When I start vlc player /usr/bin/vlc HW acceleration works normally.

Related

Restarting Kernel whenever i exit the gui without error message

Currently trying to build a GUI.
Whenever I try to exit the GUI using either the button I created or the exit button on the OS it takes some time and at the end the console shows Restarting kernel... without any other msg.
I am using Spyder with Python 3.9.
BTW I am not using sys.exit() as I saw in some other questions that it was the problem kind of.. I really don't get it..
The code :
class Class_Thread(filex.Classx,QThread):
def run(self):
self.setTerminationEnabled(True)
"""
the code the gui runs
"""
class UI(QMainWindow):
def __init__(self):
super(UI,self).__init__()
#load the UI file
uic.loadUi("test.ui", self)
self.Class_instance = Class_Thread()
#define the widgets
self.start_button = self.findChild(QPushButton,"start_button")
self.reset_button = self.findChild(QPushButton,"reset")
self.exit_button = self.findChild(QPushButton,"exit")
self.start_button.clicked.connect(self.start_check)
self.reset_button.clicked.connect(self.reset_code)
self.exit_button.clicked.connect(QtCore.QCoreApplication.instance().quit)
#show the app
self.show()
def reset_code(self):
self.Class_instance.quit()
self.reset_button.setEnabled(False)
self.start_button.setEnabled(True)
def start_check(self):
self.reset_button.setEnabled(True)
self.start_button.setEnabled(False)
self.CC_Instance.start()
app = QApplication(sys.argv)
UIWindow = UI()
UIWindow.show()
UIWindow.activateWindow()
app.exec_()

How to play custom GUI sounds in GTK3 Python app?

Tinkering with a small GTK3 app in Python3, I can trigger XDG theme sounds like so:
#!/usr/bin/python3
import gi
gi.require_version("Gtk", "3.0")
gi.require_version('GSound', '1.0')
from gi.repository import Gtk, GSound
class PyApp:
def __init__(self):
super(PyApp, self).__init__()
self.builder = Gtk.Builder()
self.builder.add_from_file("test.glade")
handlers = {
"onButtonClick": self.onButtonClick
}
self.builder.connect_signals(handlers)
self.sound = GSound.Context()
self.sound.init()
self.window = self.builder.get_object("window1")
self.window.show_all()
def onButtonClick(self, button):
self.sound.play_simple({ GSound.ATTR_EVENT_ID : "phone-incoming-call" })
if __name__ == "__main__":
app = PyApp()
Gtk.main()
But how do I make GSound play my own sounds? Do I have to construct a custom XDG theme, and if so do I have to install this in the correct system folder (e.g. /usr/share/sounds/), or can I bundle it stand-alone with my app? Also, how do I tell the Gsound.context() which theme to use? Very little information available about this.
Edit: This looked promising:
self.sound = GSound.Context()
self.sound.set_attributes({GSound.ATTR_CANBERRA_XDG_THEME_NAME: "freedesktop"})
Alas:
gi.repository.GLib.Error: gsound - error - quark: Invalid argument (-2)

How to play a mp4 file in wx.media

I want to do an mp4 player and I am trying to get the module to play a video but at the moment of giving it no error occurs
def prueba(self,z):
self.open = wx.media.MediaCtrl(panel)
self.open.Load("video.mp4")
self.open.GetBestSize()
self.open.Play()
panel = wx.Panel(frame,id=-1,size=(500,500))
self.Bind(wx.media.EVT_MEDIA_LOADED,self.prueba)
Edit:
When I´m trying the following code:
import wx
import wx.media
class TestPanel(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.testMedia = wx.media.MediaCtrl(self, style=wx.SIMPLE_BORDER,)
self.media = '/home/rolf/BBB.ogv'
self.testMedia.Bind(wx.media.EVT_MEDIA_LOADED, self.play)
self.testMedia.Bind(wx.media.EVT_MEDIA_FINISHED, self.quit)
if self.testMedia.Load(self.media):
pass
else:
print("Media not found")
self.quit(None)
def play(self, event):
self.testMedia.Play()
def quit(self, event):
self.Destroy()
if __name__ == '__main__':
app = wx.App()
Frame = TestPanel()
Frame.Show()
app.MainLoop()
With an mp4 file...
ERROR
You need to load the media before the event EVT_MEDIA_LOADED will fire.
Try this as a skeleton program:
import wx
import wx.media
class TestPanel(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.testMedia = wx.media.MediaCtrl(self, style=wx.SIMPLE_BORDER,)
self.media = '/home/rolf/BBB.ogv'
self.testMedia.Bind(wx.media.EVT_MEDIA_LOADED, self.play)
self.testMedia.Bind(wx.media.EVT_MEDIA_FINISHED, self.quit)
if self.testMedia.Load(self.media):
pass
else:
print("Media not found")
self.quit(None)
def play(self, event):
self.testMedia.Play()
def quit(self, event):
self.Destroy()
if __name__ == '__main__':
app = wx.App()
Frame = TestPanel()
Frame.Show()
app.MainLoop()
Edit based on comment
The above code works on Linux.
If you are using a different OS or if you are on Linux but do not have Gstreamer installed, you may have an issue.
There is an option to choose your media backend:
Generally, you should almost certainly leave this part up to wx.media.MediaCtrl - but if you need a certain backend for a particular reason, such as QuickTime for playing .mov files, all you need to do to choose a specific backend is to pass the name of the backend class to wx.media.MediaCtrl.Create . The following are valid backend identifiers:
MEDIABACKEND_DIRECTSHOW: Use ActiveMovie/DirectShow. Uses the native ActiveMovie (I.E. DirectShow) control. Default backend on Windows and supported by nearly all Windows versions, even some Windows CE versions. May display a windows media player logo while inactive.
MEDIABACKEND_QUICKTIME: Use QuickTime. Mac Only. WARNING: May not working correctly embedded in a wx.Notebook.
MEDIABACKEND_GSTREAMER, Use GStreamer. Unix Only. Requires GStreamer 0.8 along with at the very least the xvimagesink, xoverlay, and gst-play modules of gstreamer to function. You need the correct modules to play the relevant files, for example the mad module to play mp3s, etc.
MEDIABACKEND_WMP10, Uses Windows Media Player 10 (Windows only) - works on mobile machines with Windows Media Player 10 and desktop machines with either Windows Media Player 9 or 10.
This would result in your media defintion looking like this:
self.testMedia = wx.media.MediaCtrl(self, style=wx.SIMPLE_BORDER,szBackend=wx.media.MEDIABACKEND_WMP10)
for example.

python-vlc will not embed gtk widget into window, but open a new window instead

I'm working on a gtk3 front end for libvlc written in python using python-vlc. I'm following the gtk3 example from the python-vlc github page, but am experiencing strange behavior. I have a widget that looks like that:
import gi
import sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class PlayerWidget(Gtk.DrawingArea):
__gtype_name__ = 'VLCWidget'
def __init__(self, instance):
Gtk.DrawingArea.__init__(self)
self.player = instance.media_player_new()
def handle_embed(*args):
if sys.platform == 'win32':
self.player.set_hwnd(self.get_window().get_handle())
else:
self.player.set_xwindow(self.get_window().get_xid())
return True
self.connect("realize", handle_embed)
self.set_size_request(320, 200)
I embed it here:
import vlc
import sys
from widgets.player import PlayerWidget
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class VideoPlayer(Gtk.Window):
CONST_APP_NAME = "video player"
def __init__(self):
Gtk.Window.__init__(self)
if 'linux' in sys.platform:
self.instance = vlc.Instance("--no-xlib")
else:
self.instance = vlc.Instance()
self.set_default_size(800, 600)
header = Gtk.HeaderBar(title=self.CONST_APP_NAME)
header.set_subtitle("Filename.mp4")
header.set_show_close_button(True) # this one is the troublemaker
self.set_titlebar(header)
self.connect("destroy", Gtk.main_quit)
self.player_widget = PlayerWidget(self.instance)
self.add(self.player_widget)
def show_window(self):
self.show_all()
Gtk.main()
def set_media(self, fname):
self.player_widget.player.set_media(self.instance.media_new(fname))
def play(self):
self.player_widget.play()
if not len(sys.argv) > 0:
print('Please provide a filename')
sys.exit(1)
p = VideoPlayer()
p.set_media(sys.argv[1])
p.play()
p.show_window()
p.instance.release()
It works fine if I embed it into an empty Gtk.window. If, however, I add a HeaderBar to that window as well and then add a close button to that HeaderBar using set_show_close_button(True) it stops working as expected. The PlayerWidget will not be shown embedded anymore, but instead a new (second) window will be opened where the video is played. If I do not add the close button to the HeaderBar the widget gets embedded just fine.
A warning is thrown to the console: xcb_window window error: X server failure
I first thought it could be because I use gnome under wayland, but it occurs on X as well as on wayland.
Any help is appreciated.
Update 1: Added full code example. When I ran it today, the first time it actually worked as expected, but after that the same bug as described above occured again. Very weird.
As #mtz and #stovfl correctly pointed out, the problem was that I started the video playback (p.play()) before creating the window (p.show_window()).
As suggested I used GLib.idle_add(p.play) to let the window start the playback once it's ready. The GLib module can be imported using from gi.repository import GLib.

Python Webkit-Browser: Problems on attaching the developer-toolbar

I want to dive in Python by building a simple browser-application. I've mad a minimalistic webkitbrowser with a tutorial and now want to extend the program, but I'm stuck at some tiny problems I cannot solve.
Python 3.3.3
using Glade for the UI
The first step is to simply add a second scrolledWindow in which the developer-tools should load, immediately.
Here is my .ui-file so far, and this is the python-code:
from gi.repository import Gtk, WebKit
UI_FILE = "browser.ui"
class Browser:
"""A simple Webkit-Browser in GTK+"""
def __init__(self):
self.builder = Gtk.Builder()
self.builder.add_from_file(UI_FILE)
self.builder.connect_signals(self)
self.back = self.builder.get_object("back")
self.forward = self.builder.get_object("forward")
self.adress = self.builder.get_object("adress")
self.webview = WebKit.WebView()
scrolled_window = self.builder.get_object("scrolledwindow")
scrolled_window.add(self.webview)
self.settings = WebKit.WebSettings()
self.settings.set_property('enable-developer-extras', True)
self.webview.set_settings(self.settings)
self.devtools = WebKit.WebInspector()
scrolled_window_dev = self.builder.get_object("scrolledwindowDev")
scrolled_window_dev.add(self.devtools)
^^^^^
self.webview.connect("title-changed", self.on_title_changed)
self.window = self.builder.get_object("window")
self.window.show_all()
def on_title_changed(self, webview, frame, title):
self.window.set_title(title)
def on_button_clicked(self, button):
if button.get_stock_id() == Gtk.STOCK_GO_FORWARD:
self.webview.go_forward()
elif button.get_stock_id() == Gtk.STOCK_GO_BACK:
self.webview.go_back()
def on_entry_activate(self, widget):
url = widget.get_text()
if not "http://" in url:
url = "http://"+url
self.webview.load_uri(url)
def destroy(self, window):
Gtk.main_quit()
def main():
app = Browser()
Gtk.main()
if __name__ == "__main__":
main()
I get the error
TypeError: argument widget: Expected Gtk.Widget, but got
gi.repository.WebKit.WebInspector
Okay, this is stated in the reference of Webkit, that WebInspector is a GObject and not a GtkWidget. But I don't know what to do now.
So, can I make a GtkWidget from a GObject (if yes - how) or should I attach the dev-tools in a complete different way?
The inspector, as you noted, isn't a widget. It's a web page, so you need to create another webview for it. You do this by getting self.window.props.web_inspector (don't create a new inspector) and connecting to its inspect-web-view signal. Inside that signal handler, you need to create a new webview, add that webview to a window or wherever you want to display it, and return it.
You'll probably also want to handle the show-window, attach-window, detach-window, and close-window signals.
More documentation here: inspect-web-view
Example of running Inspector in separate window. Webkit-gtk.
This gist without many signals connected.
https://gist.github.com/alex-eri/53518825b2a8a50dd1695c69ee5058cc

Categories

Resources