1use std::boxed::Box as Box_;
7use std::pin::Pin;
8
9use glib::prelude::*;
10use glib::signal::{SignalHandlerId, connect_raw};
11use glib::translate::*;
12
13use crate::{EncodedImage, MemoryFormat, NewFrame, SandboxSelector, ffi};
14
15glib::wrapper! {
16 #[doc(alias = "GlyCreator")]
17 pub struct Creator(Object<ffi::GlyCreator, ffi::GlyCreatorClass>);
18
19 match fn {
20 type_ => || ffi::gly_creator_get_type(),
21 }
22}
23
24impl Creator {
25 #[doc(alias = "gly_creator_new")]
26 pub fn new(mime_type: &str) -> Result<Creator, glib::Error> {
27 assert_initialized_main_thread!();
28 unsafe {
29 let mut error = std::ptr::null_mut();
30 let ret = ffi::gly_creator_new(mime_type.to_glib_none().0, &mut error);
31 if error.is_null() {
32 Ok(from_glib_full(ret))
33 } else {
34 Err(from_glib_full(error))
35 }
36 }
37 }
38
39 pub fn builder() -> CreatorBuilder {
47 CreatorBuilder::new()
48 }
49
50 #[doc(alias = "gly_creator_add_frame")]
51 pub fn add_frame(
52 &self,
53 width: u32,
54 height: u32,
55 memory_format: MemoryFormat,
56 texture: &glib::Bytes,
57 ) -> Result<NewFrame, glib::Error> {
58 unsafe {
59 let mut error = std::ptr::null_mut();
60 let ret = ffi::gly_creator_add_frame(
61 self.to_glib_none().0,
62 width,
63 height,
64 memory_format.into_glib(),
65 texture.to_glib_none().0,
66 &mut error,
67 );
68 if error.is_null() {
69 Ok(from_glib_full(ret))
70 } else {
71 Err(from_glib_full(error))
72 }
73 }
74 }
75
76 #[doc(alias = "gly_creator_add_frame_with_stride")]
77 pub fn add_frame_with_stride(
78 &self,
79 width: u32,
80 height: u32,
81 stride: u32,
82 memory_format: MemoryFormat,
83 texture: &glib::Bytes,
84 ) -> Result<NewFrame, glib::Error> {
85 unsafe {
86 let mut error = std::ptr::null_mut();
87 let ret = ffi::gly_creator_add_frame_with_stride(
88 self.to_glib_none().0,
89 width,
90 height,
91 stride,
92 memory_format.into_glib(),
93 texture.to_glib_none().0,
94 &mut error,
95 );
96 if error.is_null() {
97 Ok(from_glib_full(ret))
98 } else {
99 Err(from_glib_full(error))
100 }
101 }
102 }
103
104 #[doc(alias = "gly_creator_add_metadata_key_value")]
105 pub fn add_metadata_key_value(&self, key: &str, value: &str) -> bool {
106 unsafe {
107 from_glib(ffi::gly_creator_add_metadata_key_value(
108 self.to_glib_none().0,
109 key.to_glib_none().0,
110 value.to_glib_none().0,
111 ))
112 }
113 }
114
115 #[doc(alias = "gly_creator_create")]
116 pub fn create(&self) -> Result<Option<EncodedImage>, glib::Error> {
117 unsafe {
118 let mut error = std::ptr::null_mut();
119 let ret = ffi::gly_creator_create(self.to_glib_none().0, &mut error);
120 if error.is_null() {
121 Ok(from_glib_full(ret))
122 } else {
123 Err(from_glib_full(error))
124 }
125 }
126 }
127
128 #[doc(alias = "gly_creator_create_async")]
129 pub fn create_async<P: FnOnce(Result<EncodedImage, glib::Error>) + 'static>(
130 &self,
131 cancellable: Option<&impl IsA<gio::Cancellable>>,
132 callback: P,
133 ) {
134 let main_context = glib::MainContext::ref_thread_default();
135 let is_main_context_owner = main_context.is_owner();
136 let has_acquired_main_context = (!is_main_context_owner)
137 .then(|| main_context.acquire().ok())
138 .flatten();
139 assert!(
140 is_main_context_owner || has_acquired_main_context.is_some(),
141 "Async operations only allowed if the thread is owning the MainContext"
142 );
143
144 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
145 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
146 unsafe extern "C" fn create_async_trampoline<
147 P: FnOnce(Result<EncodedImage, glib::Error>) + 'static,
148 >(
149 _source_object: *mut glib::gobject_ffi::GObject,
150 res: *mut gio::ffi::GAsyncResult,
151 user_data: glib::ffi::gpointer,
152 ) {
153 unsafe {
154 let mut error = std::ptr::null_mut();
155 let ret = ffi::gly_creator_create_finish(_source_object as *mut _, res, &mut error);
156 let result = if error.is_null() {
157 Ok(from_glib_full(ret))
158 } else {
159 Err(from_glib_full(error))
160 };
161 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
162 Box_::from_raw(user_data as *mut _);
163 let callback: P = callback.into_inner();
164 callback(result);
165 }
166 }
167 let callback = create_async_trampoline::<P>;
168 unsafe {
169 ffi::gly_creator_create_async(
170 self.to_glib_none().0,
171 cancellable.map(|p| p.as_ref()).to_glib_none().0,
172 Some(callback),
173 Box_::into_raw(user_data) as *mut _,
174 );
175 }
176 }
177
178 pub fn create_future(
179 &self,
180 ) -> Pin<Box_<dyn std::future::Future<Output = Result<EncodedImage, glib::Error>> + 'static>>
181 {
182 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
183 obj.create_async(Some(cancellable), move |res| {
184 send.resolve(res);
185 });
186 }))
187 }
188
189 #[doc(alias = "gly_creator_set_encoding_compression")]
190 pub fn set_encoding_compression(&self, compression: u8) -> bool {
191 unsafe {
192 from_glib(ffi::gly_creator_set_encoding_compression(
193 self.to_glib_none().0,
194 compression,
195 ))
196 }
197 }
198
199 #[doc(alias = "gly_creator_set_encoding_quality")]
200 pub fn set_encoding_quality(&self, quality: u8) -> bool {
201 unsafe {
202 from_glib(ffi::gly_creator_set_encoding_quality(
203 self.to_glib_none().0,
204 quality,
205 ))
206 }
207 }
208
209 #[doc(alias = "gly_creator_set_sandbox_selector")]
210 #[doc(alias = "sandbox-selector")]
211 pub fn set_sandbox_selector(&self, sandbox_selector: SandboxSelector) -> bool {
212 unsafe {
213 from_glib(ffi::gly_creator_set_sandbox_selector(
214 self.to_glib_none().0,
215 sandbox_selector.into_glib(),
216 ))
217 }
218 }
219
220 #[doc(alias = "mime-type")]
221 pub fn mime_type(&self) -> Option<glib::GString> {
222 ObjectExt::property(self, "mime-type")
223 }
224
225 #[doc(alias = "sandbox-selector")]
226 pub fn sandbox_selector(&self) -> SandboxSelector {
227 ObjectExt::property(self, "sandbox-selector")
228 }
229
230 #[doc(alias = "sandbox-selector")]
231 pub fn connect_sandbox_selector_notify<F: Fn(&Self) + Send + Sync + 'static>(
232 &self,
233 f: F,
234 ) -> SignalHandlerId {
235 unsafe extern "C" fn notify_sandbox_selector_trampoline<
236 F: Fn(&Creator) + Send + Sync + 'static,
237 >(
238 this: *mut ffi::GlyCreator,
239 _param_spec: glib::ffi::gpointer,
240 f: glib::ffi::gpointer,
241 ) {
242 unsafe {
243 let f: &F = &*(f as *const F);
244 f(&from_glib_borrow(this))
245 }
246 }
247 unsafe {
248 let f: Box_<F> = Box_::new(f);
249 connect_raw(
250 self.as_ptr() as *mut _,
251 c"notify::sandbox-selector".as_ptr() as *const _,
252 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
253 notify_sandbox_selector_trampoline::<F> as *const (),
254 )),
255 Box_::into_raw(f),
256 )
257 }
258 }
259}
260
261#[must_use = "The builder must be built to be used"]
266pub struct CreatorBuilder {
267 builder: glib::object::ObjectBuilder<'static, Creator>,
268}
269
270impl CreatorBuilder {
271 fn new() -> Self {
272 Self {
273 builder: glib::object::Object::builder(),
274 }
275 }
276
277 pub fn mime_type(self, mime_type: impl Into<glib::GString>) -> Self {
278 Self {
279 builder: self.builder.property("mime-type", mime_type.into()),
280 }
281 }
282
283 pub fn sandbox_selector(self, sandbox_selector: SandboxSelector) -> Self {
284 Self {
285 builder: self.builder.property("sandbox-selector", sandbox_selector),
286 }
287 }
288
289 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
292 pub fn build(self) -> Creator {
293 assert_initialized_main_thread!();
294 self.builder.build()
295 }
296}
297
298unsafe impl Send for Creator {}
299unsafe impl Sync for Creator {}