amikha1lov / RecApp

User friendly Open Source screencaster for Linux written in GTK. Using free GStreamer modules and not depend on FFmpeg.
GNU General Public License v3.0
116 stars 20 forks source link

Use GDBus instead of pydbus #76

Closed mathiascode closed 3 years ago

mathiascode commented 3 years ago

Removes the external pydbus dependency in favor of GDBus from GIO.

SeaDve commented 3 years ago

Hi, I just tried this commit, so far so good, there is no problem about it.

Edit: I found out that this commit is also bugged with below. Not sure what is the root cause of it. It is not very easy to reproduce but It happens.

Not relevant to this actual pull request, but relevant to implementing GDBus in the application. I do have a problem with using GDBus on ScreencastArea method. For some reason there are times where it argues gi.repository.GLib.Error: g-dbus-error-quark: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name is not activatable It is not always reproducible that's why it is very weird.

Here's the code (I put a comment where it triggers the error):

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

class Window(Gtk.ApplicationWindow):

    def __init__(self):
        Gtk.ApplicationWindow.__init__(self, title='test gdbus')

        self.box = Gtk.Box()
        self.add(self.box)
        self.start = Gtk.Button()
        self.start.set_label("Start")
        self.stop = Gtk.Button()
        self.stop.set_label("Stop")
        self.box.pack_start(self.start, True, True, 0)
        self.box.pack_start(self.stop, True, True, 0)
        self.start.connect("clicked", self.start_record)
        self.stop.connect("clicked", self.stop_record)

        self.bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
        self.GNOMEScreencast = Gio.DBusProxy.new_sync(
                    self.bus,
                    Gio.DBusProxyFlags.NONE,
                    None,
                    "org.gnome.Shell.Screencast",
                    "/org/gnome/Shell/Screencast",
                    "org.gnome.Shell.Screencast",
                    None)
        self.GNOMESelectArea = Gio.DBusProxy.new_sync(
                    self.bus,
                    Gio.DBusProxyFlags.NONE,
                    None,
                    "org.gnome.Shell.Screenshot",
                    "/org/gnome/Shell/Screenshot",
                    "org.gnome.Shell.Screenshot",
                    None)

    def start_record(self, widget):
        self.waylandcoordinates = self.GNOMESelectArea.call_sync("SelectArea", None, Gio.DBusProxyFlags.NONE, -1, None)
        self.GNOMEScreencast.call_sync(                             #This is the line that triggers the error
                    "ScreencastArea",
                    GLib.Variant.new_tuple(
                        GLib.Variant("i", self.waylandcoordinates[0]),
                        GLib.Variant("i", self.waylandcoordinates[1]),
                        GLib.Variant("i", self.waylandcoordinates[2]),
                        GLib.Variant("i", self.waylandcoordinates[3]),
                        GLib.Variant.new_string("dave.mkv"),
                        GLib.Variant("a{sv}",
                            {"framerate": GLib.Variant("i", 30),
                             "draw-cursor": GLib.Variant("b", True)}
                        ),
                    ),
                    Gio.DBusProxyFlags.NONE,
                    -1,
                    None)

    def stop_record(self, widget):
        self.GNOMEScreencast.StopScreencast()

window = Window()
window.connect("delete-event", Gtk.main_quit)
window.show_all()
Gtk.main()

Thanks!

mathiascode commented 3 years ago

It's strange. In the current dev branch, I sometimes run into this error:

Traceback (most recent call last):
  File "/usr/local/share/recapp/recapp/window.py", line 296, in on__stop_record_button_clicked
    stop_recording(self)
  File "/usr/local/share/recapp/recapp/rec.py", line 262, in stop_recording
    self.GNOMEScreencast.StopScreencast()
  File "/usr/lib/python3.9/site-packages/pydbus/proxy_method.py", line 72, in __call__
    ret = instance._bus.con.call_sync(
gi.repository.GLib.Error: g-dbus-error-quark: GDBus.Error:org.freedesktop.DBus.Error.NoReply: Message recipient disconnected from message bus without replying (4)
SeaDve commented 3 years ago

It's strange. In the current dev branch, I sometimes run into this error:

I never ran to those issue, probably the discrepancies on versions upstream. What about on master?

SeaDve commented 3 years ago

Not relevant to this actual pull request, but relevant to implementing GDBus in the application. I do have a problem with using GDBus on ScreencastArea method. For some reason there are times where it argues gi.repository.GLib.Error: g-dbus-error-quark: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name is not activatable It is not always reproducible that's why it is very weird.

I think I found the root of this problem. It turns out that when you switch between fullscreen and selection mode, and you are recording with fullscreen mode then immediately switch to the other mode, it is blocked until a reply is received, making the name not activatable. The solution is to use call instead of call_sync (not sure if this is the ideal solution).

The calling thread is blocked until a reply is received. See Gio.DBusProxy.call() for the asynchronous version of this method.

reference: https://lazka.github.io/pgi-docs/Gio-2.0/classes/DBusProxy.html#Gio.DBusProxy.call_sync