-
-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add screen cast portal #122
Conversation
The handling of the sessions is not threadsafe. You can have parallel callers of screencast methods, closing of request handles or disappearance of dbus names trigger code, but nothing protects the sessions hash table. The data in that hashtable is never returned from check_session though, so I think all you need is to wrap a mutex around that and where things are added/removed from the hash. Also, I think the API is a bit weird wrt session lifetimes, or at least not cleanly specified. The common scenario will be the client:
But this leaves a couple of questions for other scenarios:
I think you should make session close an explicit operation (and make owner disappearing from bus the same operation as this). You also need to track the state of the screencase (is it active or not, etc) and return errors to the client if its in the wrong state (double start, stop before start, etc). This will validate stuff in the common code so that the portal implementations don't have to care about weird cases. Additionally, it will make it possible for the session close/client exit to automatically do the right thing (stop only if active). Also, you need to decide if multiple start/stop pairs can be done on a single session (and if not return errors if this happens). |
e59227d
to
9f768ed
Compare
The new branch contains the new reworked API, which means "sessions" are outsourced to a generic org.freedesktop.portal.Session API. Another change is that I made it a requirement to call "SelectSources()" before "Start()". The rest is more about clarifications on what may be called when etc. |
<term>streams a(ua{sv})</term> | ||
<listitem><para> | ||
An array of PipeWire streams. Each stream consists of a PipeWire | ||
node ID (the first element in the tuble, and a Vardict of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/tuble/tuple/
<term>streams a(ua{sv})</term> | ||
<listitem><para> | ||
An array of PipeWire streams. Each stream consists of a PipeWire | ||
node ID (the first element in the tuble, and a Vardict of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/tuble/tuple/
<listitem><para> | ||
An array of PipeWire streams. Each stream consists of a PipeWire | ||
node ID (the first element in the tuble, and a Vardict of | ||
properties. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it the case that the array only has one member unless 'multiple' is true ? might be worth pointing out in the docs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, does the node id give you some kind of usable for-display identifier for the multiple streams if you were to show the multiple streams in the UI, or should that be in the dbus API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'd make sense to add things to the vardict that comes with each stream. The idea is that we can add things as we need them. I guess a 'human readable name' ala Built in display or Dell 24" might be useful.
Any update on when the final pipewire api will be available ? |
src/session.c
Outdated
|
||
g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (session), | ||
G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should add a g-authorize-method callback here that only allows callers where the sender matches the sender part of the object path
Wim added some kind of permission system in PipeWire/pipewire@d5643e8 a few days ago but I have yet to see whether the portal can make use of it. |
I had a look over this, and it seems ok to me. One thing I don't quite understand though is how the permissions are going to work under wayland? I mean, the protocol that the portal implementation uses to get the data needs some kind of authentication to not just break all the privacy between wayland clients (sandboxed or not). |
The idea is that the flow should be something like this:
|
Or what do you mean with data needed? The portal implementation is outside of the sandbox; the apps should only see the communication between the sandox and the non-impl side of just the channel between the portal and the app, right? I mean, two separate apps will not see the portal communication done between the other app and the portal, right? Where do you see any privacy being breached? |
Ah, the thing I was missing was the "sealing". I.e. what makes the returned fd different from just a connection to the entire pipewire graph. |
We are still waiting for pipewire permission api to be integrated here before this can be merged, correct ? |
Right. I talked to Wim earlier and can move forward with the API currently on the PipeWire master branch. |
9f768ed
to
b4a1026
Compare
This new branch needs PipeWire checked out from master from yesterday (22nd Jan), preferably at least commit f2aafffb2c68a023fd20b08451de20d1e2808fb3 to make the test python app able to work. It also needs an updated mutter; I'll provide a link to the corresponding branch after I cleaned it up a bit. |
The portal can abort the interaction by calling | ||
org.freedesktop.impl.portal.Session.Close() on the Session object. | ||
--> | ||
<interface name="org.freedesktop.impl.portal.Session"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a version property here:
<property name="version" type="u" access="read"/>
That way we can extend this api later and do runtime checks on it.
closing all active sessions made by said client. | ||
--> | ||
<interface name="org.freedesktop.portal.Session"> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
version here too
@short_description: Screen cast portal | ||
--> | ||
<interface name="org.freedesktop.portal.ScreenCast"> | ||
<!-- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Want a version property here too, and on the impl.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, i see you have one at the end.
This function can only be called once, if there was one or more stream | ||
shared in the response to starting the session. | ||
--> | ||
<method name="TakePipeWireRemote"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need:
<annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
here, so that you get the right codegen for the fds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, i see you did that in the makefile. We're changing those to inline annotations instead.
src/screen-cast.c
Outdated
|
||
fd_list = g_unix_fd_list_new (); | ||
fd_id = g_unix_fd_list_append (fd_list, | ||
pw_remote_steal_fd (remote->remote), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this leaks the fd. fd_list_append() dups the passed in fd and keeps that.
Overall this looks good to me, commented on some things. |
Add two new D-Bus interfaces: org.freedesktop.portal.Session and org.freedesktop.impl.portal.Session. These two interfaces may be used by portal APIs that want long lived sessions. Each contain a Close method and a Closed signal, but ultimately its the interface that makes use of the Session concept that specifies exactly how the method and signal may be used. In general, a session may always be closed by the portal, for example if the session owner vanished, so an API must always take this into consideration.
A 'Call' object is like a Request but without a reply, thus without any D-Bus object that sends signals or have methods. It is meant for simple method calls without any Request object carrying a reply.
8da45c5
to
da8ba44
Compare
This function can only be called once, if there was one or more stream | ||
shared in the response to starting the session. | ||
--> | ||
<method name="TakePipeWireRemote"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will change this to "OpenPipeWireRemote", and allow it to be called multiple times, having the portal open the PipeWire remote on demand. The reason is that this simplifies app-side by allowing to pass one pw_remote file descriptor per gstreamer object. The alternative would be to add ref-counting to pw_remote and teach the gstreamer things to share.
Introduce a portal enabling applications to create PipeWire based screen cast streams. The application facing API is defined by org.freedesktop.portal.ScreenCast and uses org.freedesktop.portal.Session for keeping track of screen cast sessions. The portal depends on having PipeWire present on the host system, as xdg-desktop-portal will link against it, open a PipeWire remote on behalf of the client, set up permission, then hand over the remote as a file descriptor to the application interacting with the portal.
da8ba44
to
a69be55
Compare
Add print preview
This adds a screen cast portal, provided via org.freedesktop.portal.ScreenCast. A sample user illustrating how its used can be found here: https://gitlab.gnome.org/snippets/19 . A xdg-desktop-portal-gtk implementation (needing mutter 3.26 + https://bugzilla.gnome.org/show_bug.cgi?id=787715 ): https://github.com/jadahl/xdg-desktop-portal-gtk/commits/wip/screen-cast .
There are some things to note about it, and as is, it is not ready to be merged. More on that below.
This is, as far as I can tell, the first portal API that introduces long lived sessions. I need this so that I can later couple a screen cast session with a remote desktop session. To summarize, doing remote desktop might (most likely) involve screen casting, but we should not pop up two portal dialogs; thus we need a combined "Start" switch.
Sessions here are currently associated by passing a session ID that the application retrieves from the Result vardict from a "CreateSession" method. This is then passed to every method that depend on a given session (SelectSources, Start, Stop).
The "combined" sessions will be done by having the application first create a org.freedesktop.portal.RemoteDesktop session (in the same way as is done in the commit introducing the ScreenCast in this PR). The session ID is then passed as an option when creating the org.freedesktop.portal.ScreenCast session. This will mean that the screen cast session is controlled by the remote desktop session, which in practice means that the application Starts/Stops both sessions atomically using the remote desktop session. Vardict entries from the screen cast Start method will instead be passed via the Result object of the remote desktop Start method.
This requires PipeWire, which is not yet possible to be used from inside a flatpak sandbox. As the idea is to have the portal pass the PipeWire remote file descriptor to the client, this portal API naturally must be changed to also do this. The intention here is to first get feedback on the portal API itself, then make the needed adaptations for passing a file descriptor.