We want to replace gjs' custom (and now legacy) imports system
with standard EcmaScript modules: JS developers are already
familiar with them, they have better tooling support and using
standard features over non-standard ones is generally the right
thing to do.
Our D-Bus services are separate from the main process, and thus
can be ported separately (except for the few imports that are
shared with the main process' code base).
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2786>
Calling _teardownPipeline() before _tryNextPipeline() was actually not a
good idea, it sets the pipelineState to STOPPED, which means we can't try
any of the following pipelines anymore.
Instead what we want to do is set the pipeline state of the old pipeline to
NULL when trying a new one, without calling _teardownPipeline() for that.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2754>
This pipeline imports dmabufs and does format conversion using GL.
The `video/x-raw(memory:DMABuf)` filter ensures format negotiation
between `pipewiresrc` and Mutter will only succeed if Mutter advertises
dmabuf support as well, falling back to the next pipeline otherwise.
Using this pipeline frees Mutter from downloading buffer content on the
main thread which can have a big impact on compositor performance.
Doing format conversion on the GPU should further improve the overall
performance on most hardware.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2597>
Make sure gnome-shell gets notified of errors that happen during screen
recording using the screencastService, so that it can properly notify the
user about the error and tear down its state, too.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2752>
Pipewire versions < 0.3.67 may not fail immediatly on negotiation
errors, thus use the last/fallback pipeline directly.
Technically, a similar recent version of Wireplumber is required
as well, but we can't check that easily and the combination of old
Wireplumber and new Pipewire is quite unlikely.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2609>
Introduce a fallback mechanism for gstreamer pipelines that allows to
define multiple pipelines and prefer them over each other.
The way this works is that we introduce a new STARTING PipelineState.
While the Recorder is in that state, it is allowed to tear down the
current pipeline and start another one whenever an error happens, this is
used to try multiple pipelines in a fixed order until a working one is
found.
Right now there's just a single pipeline using the existing vp8 encoder, the
actual new encoders and pipelines will be added in a separate commit.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2609>
The check for the Pipewire version was originally introduced in
d32c0348 which states:
> Since it is not clear yet when a proper solution will arrive,
> this makes use of `always-copy` as a workaround for now and
> should be reverted once it is no longer needed.
The check for a stable Gstreamer version with the mention proper fix was
introduced in d7b44319 and carried for the 43 cycle.
By the time Gnome 44 will be released all distros should have had enough
time to update their Gstreamer version - or backport the patches, in
case of not ustream-supported versions.
Thus lets drop it now.
Note: `always-copy` is not suitable for dmabuf buffers as it copies via
mmap.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2609>
Right now when we tell gstreamer to move the pipeline to the state
PLAYING, we pretend that happens immediately and set our PipelineState
to PLAYING right afterwards.
In reality though it's more complicated than that: Gstreamer changes
states asynchronously and set_state() returns a Gst.StateChangeReturn.ASYNC.
In that case we should wait until the according STATE_CHANGED event happens
on the bus, and only then set our PipelineState to PLAYING.
Since the STATE_CHANGED event will also happen when set_state() returns
SUCCESS, we can use the same async logic for that.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
Gstreamer can produce various errors, we shouldn't pretend those don't
exist and go on as usual when one happens. Instead, when an error
happens, tear down the pipeline, set our PipelineState to the new ERROR
state and bail out with a proper error message.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
We're tracking three different state-machines in the Recorder object:
The state of the gstreamer pipeline, the state of the screencast
session, and the sender of our dbus invocation that might vanish.
Properly handling errors that might appear in any of those three "black
boxes" is not easy, especially tearing down the other two when one of
them breaks.
So refactor the error handling here: Add a single error path for each of
those three states we're tracking, and make them all subsequently call
the _bailOutOnError() method. From there we tear down the other states and
call the error callbacks.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2197>
The videos directory doesn't necessarily have to exist, users are free to
delete it. Right now we don't handle this case and screencasting fails.
Let's handle it and fall back to the users home directory instead when
xdg-videos doesn't exist.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2594>
Some gstreamer plugins require a connection to the display server,
so they block until the server is up and running. That's why we
moved the check into the D-Bus service, so that the blocking would
not lock up the compositor itself.
However the block can still delay the service initialization so
much that auto-shutdown hits immediately when returning from the
constructor. If that happens, the proxy on the shell side is no
longer backed by a remote object when the init callback runs, and
all properties therefore resolve as `null`.
As a result, gnome-shell thinks that screencasts aren't supported
and hides the screencast button.
Fix this by holding the service during the gstreamer checks, so
that the auto-shutdown timeout only starts after the service is
ready.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/6051
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2533>
Pipewire 0.3.52 via commit a1f33a99 introduced a change that affects how
long pipewiresrc holds onto the pw_buffers it dequeued. Before that
change the pw_buffer was held until the end of the videoconvert element
at the beginning of the pipeline. After that change the pw_buffer was
held onto until the filesink at the end of the pipeline. This was
starving MetaScreenCastStreamSrc of pw_buffers to record new frames
into, resulting in the majority of frames being missed, especially in
situations in which the encoder was taking longer.
Pipewire 0.3.57 via commit 1ea1d525 will allow queuing the pw_buffer
early again via the `always-copy` option. This however is only a
workaround until a proper solution is found in either pipewire or
gstreamer that does not depend on copying the buffer contents and
instead queues the pw_buffer again after videoconvert as prior to
a1f33a99.
Since it is not clear yet when a proper solution will arrive, this makes
use of `always-copy` as a workaround for now and should be reverted once
it is no longer needed.
Related: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5585
Related: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/2461
Related: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/283
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2436>
After porting the more complex cases - in particular those that
affect a module's API - we are left with straight-forward D-Bus
method calls that can be moved to promise-based wrappers in one
go.
For consistency, this also switches from Remote to Async where
the call result is ignored.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2344>
Screenshots use `%Y-%m-%d %H-%M-%S` for the timestamp, which has the
advantage of allowing proper lexicographical sorting.
The screencast file name pattern, on the other hand, uses
locale-dependent expansions, which break sorting based on file name, and
introduces the chance of potentially invalid characters on different
file systems.
Fixes: #5115
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2300>
ES modules do not allow exports to be overriden, in anticipation
of the ESM port add a `setCurrentExtension` utility which will
throw if used in the shell. This is tested using a conditional
import of Main.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2363>
We currently decide at build time whether to include screencast
support, based on whether the required gst/pipewire library headers
are installed.
That check is imprecise, because having the library headers available
at build time doesn't necessarily mean that the libraries are there
at runtime, or that the corresponding typelibs are installed.
It makes more sense to check the requirements at runtime, so prepare
for that by installing the screencast service unconditionally, but
bail out early if the dependencies aren't met.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2297>
If one of these libraries breaks its GIR API in future, then upgrading
packages unrelated to gnome-shell might pull in the newer version,
causing gnome-shell to crash when it gets a newer GIR API that is
incompatible with its expectations. For example, this seems to be
happening in Debian testing at the moment, when GNOME Shell 41.4
imports GWeather and can get version 4.0 instead of the version 3.0 that
it expected.
Adding explicit API versions at the time the newer version is released
is too late, because that will still let the newer version of the GIR API
break pre-existing GNOME Shell packages. Prevent similar crashes in
future by making the desired versions explicit.
This is done for all third-party libraries except GLib, similar to the
common practice in Python code; if GLib breaks API, then that will be
a disruptive change to the whole GLib/GObject ecosystem, regardless.
Gvc, Meta, Shell, Shew, St are not included because they're private
(only exist in a non-default search path entry).
Clutter and Cogl *are* included, because we need to import the fork of
them that comes with Meta, as opposed to their deprecated standalone
versions.
Signed-off-by: Simon McVittie <smcv@debian.org>
Bug-Debian: https://bugs.debian.org/1008926
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2261>
If the finish function isn't specified, promisify will now try
to use the async name without '_async'/'_begin' suffix (if any)
and '_finish' appended.
Everything except IBus uses a variation of that pattern, so there's
quite a bit of boilerplate we get to remove…
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2174>
The current preference API - buildPrefsWidget() - predates client-side
decorations. While extension authors have been finding ways around
the limitation of not having access to the window/titlebar, the change
to the new Adwaita API seems like a good time for an updated API that
officially provides that access (as far as allowed by libadwaita).
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2012>
Adapt the new GNOME platform API for the upcoming 42. This makes
sure that we get the latest version of the stylesheet, as well as
support for the new dark mode.
Using the dedicated preference API also gives extensions with more
complex preferences an easier and standardized way for implementing
multi-page preferences.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2012>
The error UI comprises the bits that are actually custom. Splitting them
out from the off-the-shelf window makes it easier to replace the dialog
with libadwaita's dedicated preference window.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2012>
The REPLACE flag we currently pass is useless, as replacing the service
is disallowed when not started with the ALLOW_REPLACEMENT flag.
Fix this by adopting a more standard pattern where replacement is always
allowed, but only actually requested when `--replace` is passed on the
command line.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2152>
All fd.o Notifications signals are emitted for a particular notification,
so debugging aside, only the owner of said notification has a legitimate
reason to act on it.
So far we (and other implementations like the old notification-daemon)
have relied on the client-side to properly filter the signals (like
libnotify), but at least the QT implementation is known to not do
that.
Enforce correct client behavior by only emitting the signal to the
original sender.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/5008
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2153>
Instead of testing if the videos directory exists and using the home
directory otherwise, just try to create the target directory. This
aligns with how the screenshot UI handles the screenshots folder, and
it's convenient for putting screencasts into a subdirectory.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2102>
Like the main gnome-shell process, the extensions service loads code from
extensions. It therefore makes sense to prevent GType name clashes there
as well, just like we already to in the gnome-shell process.
This may break some extensions that use the old type name in .ui files,
but they can be fixed easily by specifying an explicit GTypeName.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2024>
Replace deprecated functions with their direct replacements:
- dep.get_pkgconfig_variable() → dep.get_variable()
- prg.path() → prg.full_path()
- source/build_root() → project_source/build_root()
In one case we need meson.global_source_root() that was only
added in meson 0.58, so bump the requirement to that.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2077>
Showing multiple preference dialogs at the same time (for instance
by repeated `gnome-extensions prefs` calls) may or may not work as
expected, depending on whether any of the dialogs is modal or not
(read: opened via the Extensions app).
The easiest way to address this is to disallow more than a single
dialog at the time. It's arguably also the more predictable behavior,
and means extensions don't have to deal with inconsistent state
caused by multiple dialogs.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4564
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2013>
GTK4 relies entirely on refcounting for cleanup (that is,
there is no longer a destroy() method that forces a dispose
run regardless of the refcount).
Unfortunately that makes cleanup harder in (some) language
bindings, where an object may be kept alive implicitly by
closures etc.
Address this by releasing the hold count when the window
is closed rather than when it is destroyed.
This isn't the most elegant, but it ensure that the service
doesn't get stuck if an extension doesn't carefully clean
up everything in its prefs widget.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4564
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2013>
If parsing the pipeline fails for some reason, we currently end up
with a zombie session that leads to a stuck recording indicator in
gnome-shell.
Instead, properly tear down the session to allow mutter and gnome-shell
to correctly update their state.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1878>
The current gstreamer pipeline performs quite bad on slower machines and
is dropping lots of frames, improve the pipeline by changing a few
things:
- Use threads for videoconvert and improve speed of videoconvert by
disabling some unneeded things
- Add a queue before the encoding step, this allows the encoder to work
at its own pace and will lead to a lot more stability
- Remove the fixed quantizer and only set a max quantizer, this helps
quite a bit with performance
- Change the deadline parameter of vp8enc to 1: This makes the encoder
go into real time mode, which will make it a lot faster
- Set cpu-used to 16, the maximum possible value.
- Set static-threshold to 1000, static-threshold is the motion detection
threshold, and while a value of 100 is recommended for screencasting in
the gstreamer documentation (see [1]), using 1000 appears to perform a
lot better and still outputs fairly good quality
- Set a larger buffer size than the default size, this seems to get a
bit more stability during high load scenarios
All in all, those changes make the pipeline drop no more frames when
recording at 30 FPS and 2K screen resolution. That was tested on a
fairly recent mobile core-i5 processor.
Also, because we now have two %T replacement strings for the number of
threads, we need to switch to replaceAll(). For that to work, we have to
put the %T matching expression into quotes.
[1] https://gstreamer.freedesktop.org/documentation/vpx/GstVPXEnc.html?gi-language=c#GstVPXEnc:static-threshold
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1633>
For the screensaver service, it is quite normal that a consumer only
subscribes to the "ActiveChanged" signal without calling any methods.
The result is that we don't know about the consumer, and shut down
the service anyway after we hit the timeout.
If this happens, we break functionality like gnome-settings-daemon's
screen blanking on idle.
Fix this by simply disabling auto-shutdown for the service, which
also reflects the expectation that the screen saver service is
always running in a GNOME session.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4114
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1824>