Browse Source

Upgrade glycin

Tests the beta for GNOME 49 with the loaders in the Flatpak runtime.
fractal-13
Kévin Commaille 7 months ago
parent
commit
0e9d34dd9d
No known key found for this signature in database
GPG Key ID: F26F4BE20A08255B
  1. 142
      Cargo.lock
  2. 2
      Cargo.toml
  3. 21
      build-aux/org.gnome.Fractal.Devel.json
  4. 20
      src/components/media/animated_image_paintable.rs
  5. 18
      src/utils/media/image/mod.rs
  6. 74
      src/utils/media/image/queue.rs

142
Cargo.lock generated

@ -216,6 +216,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "async-lock"
version = "3.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc"
dependencies = [
"event-listener",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-recursion"
version = "1.1.1"
@ -259,6 +270,12 @@ dependencies = [
"syn",
]
[[package]]
name = "async-task"
version = "4.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "async-trait"
version = "0.1.88"
@ -453,6 +470,19 @@ dependencies = [
"generic-array",
]
[[package]]
name = "blocking"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21"
dependencies = [
"async-channel",
"async-task",
"futures-io",
"futures-lite",
"piper",
]
[[package]]
name = "bloomfilter"
version = "1.0.16"
@ -695,12 +725,37 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -1684,14 +1739,16 @@ dependencies = [
[[package]]
name = "glycin"
version = "2.1.1"
version = "3.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37cb9e103cb6b8925bf5e8a1cf8a1166797d8aaefaabd03e68cf6ad7443a1baa"
checksum = "0ca9a2584f5315609d3284b8885ebd7f8475b991b2ae77b7fdfb22b723fe3321"
dependencies = [
"futures-channel",
"futures-util",
"gdk4",
"gio",
"glib",
"glycin-common",
"glycin-utils",
"gufo-common",
"gufo-exif",
@ -1711,25 +1768,51 @@ dependencies = [
"zbus",
]
[[package]]
name = "glycin-common"
version = "1.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3344437ebbb38f373d52a2636cefdae31689d32042bbed402438d29abe04d9e9"
dependencies = [
"bitflags 2.9.1",
"gufo-common",
"half",
"memmap2",
"nix 0.29.0",
"paste",
"rmp-serde",
"serde",
"thiserror 2.0.12",
"zerocopy",
"zvariant",
]
[[package]]
name = "glycin-utils"
version = "3.0.1"
version = "4.0.0-beta.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0816d1db00696479cda3cd6c914fb07115982b019dac96555d203c0d5b6d37a"
checksum = "5bb0e781372a461edbf6efddf5fb5ea4b700581773ca6a962cbf9666c8765a46"
dependencies = [
"async-lock",
"bitflags 2.9.1",
"blocking",
"env_logger",
"futures-util",
"glycin-common",
"gufo-common",
"half",
"libc",
"libseccomp",
"log",
"memmap2",
"nix 0.29.0",
"paste",
"rmp-serde",
"rayon",
"serde",
"thiserror 2.0.12",
"tokio",
"zbus",
"zerocopy",
]
[[package]]
@ -2073,9 +2156,9 @@ dependencies = [
[[package]]
name = "gufo-common"
version = "0.2.0"
version = "1.0.0-beta"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccb2b4c040e67e6d6ad954f04693a11864df82bce6c6c468524b6a78bb75581f"
checksum = "6b369fe87840c7f9769e475e65500420072bf040c09b12d00fda83567190ea0f"
dependencies = [
"paste",
"serde",
@ -2084,9 +2167,9 @@ dependencies = [
[[package]]
name = "gufo-exif"
version = "0.2.2"
version = "0.3.0-beta"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1448d72e2458b35dd10c0f148ea913b38c61b649552b22a97fa836ec376189ff"
checksum = "42ed15d1144c2ea214eaf8cb8a83168c9a4dccdbc3b18b889e5610f8cf33128d"
dependencies = [
"gufo-common",
"thiserror 2.0.12",
@ -2112,6 +2195,16 @@ dependencies = [
"tracing",
]
[[package]]
name = "half"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
dependencies = [
"cfg-if",
"crunchy",
]
[[package]]
name = "hashbrown"
version = "0.15.5"
@ -3866,6 +3959,17 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "piper"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
dependencies = [
"atomic-waker",
"fastrand",
"futures-io",
]
[[package]]
name = "pkcs8"
version = "0.10.2"
@ -4108,6 +4212,26 @@ dependencies = [
"rand_core 0.9.3",
]
[[package]]
name = "rayon"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "readlock"
version = "0.1.9"

2
Cargo.toml

@ -61,7 +61,7 @@ zeroize = "1"
# gtk-rs project and dependents. These usually need to be updated together.
adw = { package = "libadwaita", version = "0.7", features = ["v1_7"] }
glycin = { version = "2", default-features = false, features = ["tokio", "gdk4"] }
glycin = { version = "3.0.0-beta.1", default-features = false, features = ["tokio", "gdk4"] }
gst = { version = "0.23", package = "gstreamer" }
gst_app = { version = "0.23", package = "gstreamer-app" }
gst_pbutils = { version = "0.23", package = "gstreamer-pbutils" }

21
build-aux/org.gnome.Fractal.Devel.json

@ -95,27 +95,6 @@
}
]
},
{
"name": "glycin-loaders",
"buildsystem": "meson",
"config-opts": [
"-Dtests=false",
"-Dlibglycin=false",
"-Dintrospection=false",
"-Dvapi=false",
"-Dcapi_docs=false",
"-Dpython_tests=false"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.gnome.org/sophie-h/glycin.git",
"tag": "1.2.2",
"commit": "c7d362287303944721cf583d4d9e9f7721bfa407",
"disable-submodules": true
}
]
},
{
"name": "fractal",
"buildsystem": "meson",

20
src/components/media/animated_image_paintable.rs

@ -6,7 +6,7 @@ use tracing::error;
use crate::{
spawn, spawn_tokio,
utils::{CountedRef, File},
utils::{CountedRef, File, TokioDrop},
};
mod imp {
@ -20,7 +20,7 @@ mod imp {
#[derive(Default)]
pub struct AnimatedImagePaintable {
/// The image loader.
image_loader: OnceCell<Arc<Image<'static>>>,
image_loader: OnceCell<Arc<TokioDrop<Image>>>,
/// The file of the image.
file: OnceCell<File>,
/// The current frame that is displayed.
@ -49,7 +49,7 @@ mod imp {
self.current_frame
.borrow()
.as_ref()
.map_or_else(|| self.image_loader().info().height, |f| f.height())
.map_or_else(|| self.image_loader().details().height(), |f| f.height())
.try_into()
.unwrap_or(i32::MAX)
}
@ -58,7 +58,7 @@ mod imp {
self.current_frame
.borrow()
.as_ref()
.map_or_else(|| self.image_loader().info().width, |f| f.width())
.map_or_else(|| self.image_loader().details().width(), |f| f.width())
.try_into()
.unwrap_or(i32::MAX)
}
@ -95,23 +95,23 @@ mod imp {
impl AnimatedImagePaintable {
/// The image loader.
fn image_loader(&self) -> &Arc<Image<'static>> {
fn image_loader(&self) -> &Arc<TokioDrop<Image>> {
self.image_loader
.get()
.expect("image loader is initialized")
.expect("image loader should be initialized")
}
/// Initialize the image.
pub(super) fn init(
&self,
file: File,
image_loader: Arc<Image<'static>>,
image_loader: Arc<TokioDrop<Image>>,
first_frame: Arc<Frame>,
) {
self.file.set(file).expect("file is uninitialized");
self.file.set(file).expect("file should be uninitialized");
self.image_loader
.set(image_loader)
.expect("image loader is uninitialized");
.expect("image loader should be uninitialized");
self.current_frame.replace(Some(first_frame));
self.update_animation();
@ -233,7 +233,7 @@ impl AnimatedImagePaintable {
/// frame.
pub(crate) fn new(
file: File,
image_loader: Arc<Image<'static>>,
image_loader: Arc<TokioDrop<Image>>,
first_frame: Arc<Frame>,
) -> Self {
let obj = glib::Object::new::<Self>();

18
src/utils/media/image/mod.rs

@ -28,7 +28,10 @@ pub(crate) use queue::{IMAGE_QUEUE, ImageRequestPriority};
use super::{FrameDimensions, MediaFileError};
use crate::{
DISABLE_GLYCIN_SANDBOX, RUNTIME, components::AnimatedImagePaintable, spawn_tokio, utils::File,
DISABLE_GLYCIN_SANDBOX, RUNTIME,
components::AnimatedImagePaintable,
spawn_tokio,
utils::{File, TokioDrop},
};
/// The maximum dimensions of a thumbnail in the timeline.
@ -65,7 +68,7 @@ const THUMBNAIL_DIMENSIONS_THRESHOLD: u32 = 200;
const SUPPORTED_ANIMATED_IMAGE_MIME_TYPES: &[&str] = &["image/gif", "image/png", "image/webp"];
/// Get an image loader for the given file.
async fn image_loader(file: gio::File) -> Result<glycin::Image<'static>, glycin::ErrorCtx> {
async fn image_loader(file: gio::File) -> Result<glycin::Image, glycin::ErrorCtx> {
let mut loader = glycin::Loader::new(file);
if DISABLE_GLYCIN_SANDBOX {
@ -88,11 +91,11 @@ async fn load_image(
let image_loader = image_loader(file.as_gfile()).await?;
let frame_request = request_dimensions.map(|request| {
let image_info = image_loader.info();
let image_details = image_loader.details();
let original_dimensions = FrameDimensions {
width: image_info.width,
height: image_info.height,
width: image_details.width(),
height: image_details.height(),
};
original_dimensions.to_image_loader_request(request)
@ -104,9 +107,10 @@ async fn load_image(
} else {
image_loader.next_frame().await?
};
Ok(Image {
file,
loader: image_loader.into(),
loader: TokioDrop::new(image_loader).into(),
first_frame: first_frame.into(),
})
})
@ -120,7 +124,7 @@ pub(crate) struct Image {
/// The file of the image.
file: File,
/// The image loader.
loader: Arc<glycin::Image<'static>>,
loader: Arc<TokioDrop<glycin::Image>>,
/// The first frame of the image.
first_frame: Arc<glycin::Frame>,
}

74
src/utils/media/image/queue.rs

@ -491,14 +491,13 @@ impl IntoFuture for DownloadRequestData {
Box::pin(async move {
let media = client.media();
let data = match media.get_media_content(&settings, true).await {
Ok(data) => data,
Err(error) => {
return Err(MediaFileError::from(error));
}
};
let data = media
.get_media_content(&settings, true)
.await
.map_err(MediaFileError::from)?;
let file = save_data_to_tmp_file(data).await?;
Ok(file)
})
}
@ -516,7 +515,7 @@ struct FileRequestData {
impl FileRequestData {
/// The ID of the image request with this data.
fn request_id(&self) -> ImageRequestId {
ImageRequestId::File(self.file.path().expect("file has a path"))
ImageRequestId::File(self.file.path().expect("file should have a path"))
}
}
@ -535,13 +534,7 @@ impl IntoFuture for FileRequestData {
#[derive(Clone)]
enum ImageRequestData {
/// The data for a download request.
Download {
/// The data to download the image.
download_data: DownloadRequestData,
/// The data to load the image into a paintable, after it was
/// downloaded.
file_data: Option<FileRequestData>,
},
Download(DownloadRequestData),
/// The data for a file request.
File(FileRequestData),
}
@ -550,27 +543,10 @@ impl ImageRequestData {
/// The ID of the image request with this data.
fn request_id(&self) -> ImageRequestId {
match self {
ImageRequestData::Download { download_data, .. } => download_data.request_id(),
ImageRequestData::Download(download_data) => download_data.request_id(),
ImageRequestData::File(file_data) => file_data.request_id(),
}
}
/// The data for the next request with this image request data.
fn into_next_request_data(self) -> DownloadOrFileRequestData {
match self {
Self::Download {
download_data,
file_data,
} => {
if let Some(file_data) = file_data {
file_data.into()
} else {
download_data.into()
}
}
Self::File(file_data) => file_data.into(),
}
}
}
impl IntoFuture for ImageRequestData {
@ -579,8 +555,8 @@ impl IntoFuture for ImageRequestData {
fn into_future(self) -> Self::IntoFuture {
Box::pin(async move {
let file_data = match self.into_next_request_data() {
DownloadOrFileRequestData::Download(download_data) => {
let file_data = match self {
Self::Download(download_data) => {
let dimensions = download_data.dimensions;
// Download the image to a file.
@ -592,11 +568,11 @@ impl IntoFuture for ImageRequestData {
}
}
}
DownloadOrFileRequestData::File(file_data) => file_data,
Self::File(file_data) => file_data,
};
// Load the image from the file.
match file_data.clone().await {
match file_data.await {
Ok(image) => Ok(image),
Err(error) => {
warn!("Could not load image from file: {error}");
@ -608,36 +584,12 @@ impl IntoFuture for ImageRequestData {
}
impl From<DownloadRequestData> for ImageRequestData {
fn from(download_data: DownloadRequestData) -> Self {
Self::Download {
download_data,
file_data: None,
}
}
}
impl From<FileRequestData> for ImageRequestData {
fn from(value: FileRequestData) -> Self {
Self::File(value)
}
}
/// The data of a download request or a file request.
#[derive(Clone)]
enum DownloadOrFileRequestData {
/// The data for a download request.
Download(DownloadRequestData),
/// The data for a file request.
File(FileRequestData),
}
impl From<DownloadRequestData> for DownloadOrFileRequestData {
fn from(download_data: DownloadRequestData) -> Self {
Self::Download(download_data)
}
}
impl From<FileRequestData> for DownloadOrFileRequestData {
impl From<FileRequestData> for ImageRequestData {
fn from(value: FileRequestData) -> Self {
Self::File(value)
}

Loading…
Cancel
Save