From 003554876c1397330a6a6bf2d97b13728c67b1cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 15 Jan 2023 20:38:13 +0200 Subject: [PATCH] Update various APIs to use `glib::GStr` Currently only covers what is needed to keep code compiling, plus everything caps/structure/tags related. This avoids unnecessary heap allocations for adding the NUL-terminator of C strings, and especially makes caps/structure handling as efficient as in C. Part-of: --- examples/src/bin/rtsp-server-record.rs | 2 +- examples/src/bin/transmux.rs | 2 +- examples/src/glupload.rs | 2 +- gstreamer-allocators/src/caps_features.rs | 2 +- gstreamer-audio/src/audio_converter.rs | 29 +-- gstreamer-audio/src/audio_format.rs | 10 +- gstreamer-audio/src/audio_format_info.rs | 10 +- gstreamer-audio/src/caps.rs | 47 +++-- gstreamer-gl/src/caps_features.rs | 2 +- gstreamer-gl/sys/src/manual.rs | 4 +- gstreamer-pbutils/src/functions.rs | 4 +- gstreamer-rtsp-server/src/lib.rs | 85 +++------ gstreamer-video/src/caps.rs | 36 ++-- gstreamer-video/src/caps_features.rs | 59 +++--- gstreamer-video/src/video_buffer_pool.rs | 40 ++-- gstreamer-video/src/video_converter.rs | 106 +++++----- gstreamer-video/src/video_format.rs | 10 +- gstreamer-video/src/video_format_info.rs | 10 +- gstreamer/src/caps.rs | 63 ++++-- gstreamer/src/caps_features.rs | 104 +++++++--- gstreamer/src/caps_features_serde.rs | 4 +- gstreamer/src/caps_serde.rs | 6 +- gstreamer/src/device_provider_factory.rs | 12 +- gstreamer/src/element.rs | 43 ++--- gstreamer/src/element_factory.rs | 12 +- gstreamer/src/static_caps.rs | 4 +- gstreamer/src/structure.rs | 202 +++++++++++--------- gstreamer/src/structure_serde.rs | 4 +- gstreamer/src/subclass/element.rs | 2 +- gstreamer/src/tag_setter.rs | 2 +- gstreamer/src/tags.rs | 223 +++++++++++----------- tutorials/src/bin/basic-tutorial-5.rs | 2 +- 32 files changed, 602 insertions(+), 541 deletions(-) diff --git a/examples/src/bin/rtsp-server-record.rs b/examples/src/bin/rtsp-server-record.rs index 3fb1321a1..669d2eeb8 100644 --- a/examples/src/bin/rtsp-server-record.rs +++ b/examples/src/bin/rtsp-server-record.rs @@ -46,7 +46,7 @@ fn main_loop() -> Result<(), Error> { // server to require from clients. let auth = gst_rtsp_server::RTSPAuth::new(); let token = gst_rtsp_server::RTSPToken::new(&[( - *gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE, + gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE, &"user", )]); let basic = gst_rtsp_server::RTSPAuth::make_basic("user", "password"); diff --git a/examples/src/bin/transmux.rs b/examples/src/bin/transmux.rs index f7c0ecf5f..a1127842d 100644 --- a/examples/src/bin/transmux.rs +++ b/examples/src/bin/transmux.rs @@ -86,7 +86,7 @@ fn example_main() -> Result<(), Error> { .expect("typefinder \"have-type\" signal values[2]"); let format_name = caps.structure(0).expect("Failed to get format name").name(); - let demuxer = match format_name { + let demuxer = match format_name.as_str() { "video/x-matroska" | "video/webm" => gst::ElementFactory::make("matroskademux") .build() .expect("matroskademux missing"), diff --git a/examples/src/glupload.rs b/examples/src/glupload.rs index ec80e5994..a5158fecb 100644 --- a/examples/src/glupload.rs +++ b/examples/src/glupload.rs @@ -541,7 +541,7 @@ impl App { let src = gst::ElementFactory::make("videotestsrc").build()?; let caps = gst_video::VideoCapsBuilder::new() - .features(&[&gst_gl::CAPS_FEATURE_MEMORY_GL_MEMORY]) + .features([gst_gl::CAPS_FEATURE_MEMORY_GL_MEMORY]) .format(gst_video::VideoFormat::Rgba) .field("texture-target", "2D") .build(); diff --git a/gstreamer-allocators/src/caps_features.rs b/gstreamer-allocators/src/caps_features.rs index 67eb19c2e..ee09a5e2d 100644 --- a/gstreamer-allocators/src/caps_features.rs +++ b/gstreamer-allocators/src/caps_features.rs @@ -4,4 +4,4 @@ use gst::CapsFeatures; use once_cell::sync::Lazy; pub static CAPS_FEATURES_MEMORY_DMABUF: Lazy = - Lazy::new(|| CapsFeatures::new(&[*crate::CAPS_FEATURE_MEMORY_DMABUF])); + Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_DMABUF])); diff --git a/gstreamer-audio/src/audio_converter.rs b/gstreamer-audio/src/audio_converter.rs index 065090403..c2cdb70bf 100644 --- a/gstreamer-audio/src/audio_converter.rs +++ b/gstreamer-audio/src/audio_converter.rs @@ -79,49 +79,52 @@ impl AudioConverterConfig { } pub fn set_dither_method(&mut self, v: crate::AudioDitherMethod) { - self.0.set("GstAudioConverter.dither-method", v); + self.0 + .set(glib::gstr!("GstAudioConverter.dither-method"), v); } #[doc(alias = "get_dither_method")] pub fn dither_method(&self) -> crate::AudioDitherMethod { self.0 - .get_optional("GstAudioConverter.dither-method") + .get_optional(glib::gstr!("GstAudioConverter.dither-method")) .expect("Wrong type") .unwrap_or(crate::AudioDitherMethod::None) } pub fn set_noise_shaping_method(&mut self, v: crate::AudioNoiseShapingMethod) { - self.0.set("GstAudioConverter.noise-shaping-method", v); + self.0 + .set(glib::gstr!("GstAudioConverter.noise-shaping-method"), v); } #[doc(alias = "get_noise_shaping_method")] pub fn noise_shaping_method(&self) -> crate::AudioNoiseShapingMethod { self.0 - .get_optional("GstAudioConverter.noise-shaping-method") + .get_optional(glib::gstr!("GstAudioConverter.noise-shaping-method")) .expect("Wrong type") .unwrap_or(crate::AudioNoiseShapingMethod::None) } pub fn set_quantization(&mut self, v: u32) { - self.0.set("GstAudioConverter.quantization", v); + self.0.set(glib::gstr!("GstAudioConverter.quantization"), v); } #[doc(alias = "get_quantization")] pub fn quantization(&self) -> u32 { self.0 - .get_optional("GstAudioConverter.quantization") + .get_optional(glib::gstr!("GstAudioConverter.quantization")) .expect("Wrong type") .unwrap_or(1) } pub fn set_resampler_method(&mut self, v: crate::AudioResamplerMethod) { - self.0.set("GstAudioConverter.resampler-method", v); + self.0 + .set(glib::gstr!("GstAudioConverter.resampler-method"), v); } #[doc(alias = "get_resampler_method")] pub fn resampler_method(&self) -> crate::AudioResamplerMethod { self.0 - .get_optional("GstAudioConverter.resampler-method") + .get_optional(glib::gstr!("GstAudioConverter.resampler-method")) .expect("Wrong type") .unwrap_or(crate::AudioResamplerMethod::BlackmanNuttall) } @@ -133,13 +136,14 @@ impl AudioConverterConfig { assert_eq!(val.len(), length); gst::Array::from_values(val.iter().map(|val| val.to_send_value())).to_send_value() })); - self.0.set("GstAudioConverter.mix-matrix", array); + self.0 + .set(glib::gstr!("GstAudioConverter.mix-matrix"), array); } #[doc(alias = "get_mix_matrix")] pub fn mix_matrix(&self) -> Vec> { self.0 - .get_optional::("GstAudioConverter.mix-matrix") + .get_optional::(glib::gstr!("GstAudioConverter.mix-matrix")) .expect("Wrong type") .map(|array| { array @@ -162,7 +166,8 @@ impl AudioConverterConfig { #[cfg(any(feature = "v1_22", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] pub fn set_dither_threshold(&mut self, v: u32) { - self.0.set("GstAudioConverter.dither-threshold", v); + self.0 + .set(glib::gstr!("GstAudioConverter.dither-threshold"), v); } #[cfg(any(feature = "v1_22", feature = "dox"))] @@ -170,7 +175,7 @@ impl AudioConverterConfig { #[doc(alias = "get_dither_threshold")] pub fn dither_threshold(&self) -> u32 { self.0 - .get_optional("GstAudioConverter.dither-threshold") + .get_optional(glib::gstr!("GstAudioConverter.dither-threshold")) .expect("Wrong type") .unwrap_or(20) } diff --git a/gstreamer-audio/src/audio_format.rs b/gstreamer-audio/src/audio_format.rs index 301d17233..62b130090 100644 --- a/gstreamer-audio/src/audio_format.rs +++ b/gstreamer-audio/src/audio_format.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{ffi::CStr, str}; +use std::str; use glib::translate::{from_glib, IntoGlib}; use once_cell::sync::Lazy; @@ -112,18 +112,16 @@ impl crate::AudioFormat { } #[doc(alias = "gst_audio_format_to_string")] - pub fn to_str<'a>(self) -> &'a str { + pub fn to_str<'a>(self) -> &'a glib::GStr { if self == Self::Unknown { - return "UNKNOWN"; + return glib::gstr!("UNKNOWN"); } unsafe { - CStr::from_ptr( + glib::GStr::from_ptr( ffi::gst_audio_format_to_string(self.into_glib()) .as_ref() .expect("gst_audio_format_to_string returned NULL"), ) - .to_str() - .expect("gst_audio_format_to_string returned an invalid string") } } diff --git a/gstreamer-audio/src/audio_format_info.rs b/gstreamer-audio/src/audio_format_info.rs index 99a591042..abad9f986 100644 --- a/gstreamer-audio/src/audio_format_info.rs +++ b/gstreamer-audio/src/audio_format_info.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{cmp::Ordering, ffi::CStr, fmt, marker::PhantomData, str}; +use std::{cmp::Ordering, fmt, marker::PhantomData, str}; use glib::{ translate::{from_glib, from_glib_none, FromGlib, IntoGlib, ToGlibPtr, ToGlibPtrMut}, @@ -64,13 +64,13 @@ impl AudioFormatInfo { } #[inline] - pub fn name<'a>(&self) -> &'a str { - unsafe { CStr::from_ptr(self.0.name).to_str().unwrap() } + pub fn name<'a>(&self) -> &'a glib::GStr { + unsafe { glib::GStr::from_ptr(self.0.name) } } #[inline] - pub fn description<'a>(&self) -> &'a str { - unsafe { CStr::from_ptr(self.0.description).to_str().unwrap() } + pub fn description<'a>(&self) -> &'a glib::GStr { + unsafe { glib::GStr::from_ptr(self.0.description) } } #[inline] diff --git a/gstreamer-audio/src/caps.rs b/gstreamer-audio/src/caps.rs index bf4b33094..0ecea2225 100644 --- a/gstreamer-audio/src/caps.rs +++ b/gstreamer-audio/src/caps.rs @@ -2,6 +2,8 @@ use std::ops::{Bound::*, RangeBounds}; use gst::Caps; +use glib::IntoGStr; + use crate::{AudioFormat, AudioLayout}; pub struct AudioCapsBuilder { @@ -10,7 +12,7 @@ pub struct AudioCapsBuilder { impl AudioCapsBuilder { pub fn new() -> Self { - let builder = Caps::builder("audio/x-raw"); + let builder = Caps::builder(glib::gstr!("audio/x-raw")); let builder = AudioCapsBuilder { builder }; builder .rate_range(..) @@ -29,7 +31,10 @@ impl AudioCapsBuilder { } } - pub fn features(self, features: &[&str]) -> AudioCapsBuilder { + pub fn features( + self, + features: impl IntoIterator, + ) -> AudioCapsBuilder { AudioCapsBuilder { builder: self.builder.features(features), } @@ -45,14 +50,14 @@ impl Default for AudioCapsBuilder { impl AudioCapsBuilder { pub fn format(self, format: AudioFormat) -> Self { Self { - builder: self.builder.field("format", format.to_str()), + builder: self.builder.field(glib::gstr!("format"), format.to_str()), } } pub fn format_list(self, formats: impl IntoIterator) -> Self { Self { builder: self.builder.field( - "format", + glib::gstr!("format"), gst::List::new(formats.into_iter().map(|f| f.to_str())), ), } @@ -60,7 +65,7 @@ impl AudioCapsBuilder { pub fn rate(self, rate: i32) -> Self { Self { - builder: self.builder.field("rate", rate), + builder: self.builder.field(glib::gstr!("rate"), rate), } } @@ -68,19 +73,21 @@ impl AudioCapsBuilder { let (start, end) = range_bounds_i32_start_end(rates); let gst_rates = gst::IntRange::::new(start, end); Self { - builder: self.builder.field("rate", gst_rates), + builder: self.builder.field(glib::gstr!("rate"), gst_rates), } } pub fn rate_list(self, rates: impl IntoIterator) -> Self { Self { - builder: self.builder.field("rate", gst::List::new(rates)), + builder: self + .builder + .field(glib::gstr!("rate"), gst::List::new(rates)), } } pub fn channels(self, channels: i32) -> Self { Self { - builder: self.builder.field("channels", channels), + builder: self.builder.field(glib::gstr!("channels"), channels), } } @@ -88,26 +95,30 @@ impl AudioCapsBuilder { let (start, end) = range_bounds_i32_start_end(channels); let gst_channels: gst::IntRange = gst::IntRange::new(start, end); Self { - builder: self.builder.field("channels", gst_channels), + builder: self.builder.field(glib::gstr!("channels"), gst_channels), } } pub fn channels_list(self, channels: impl IntoIterator) -> Self { Self { - builder: self.builder.field("channels", gst::List::new(channels)), + builder: self + .builder + .field(glib::gstr!("channels"), gst::List::new(channels)), } } pub fn layout(self, layout: AudioLayout) -> Self { Self { - builder: self.builder.field("layout", layout_str(layout)), + builder: self + .builder + .field(glib::gstr!("layout"), layout_str(layout)), } } pub fn layout_list(self, layouts: impl IntoIterator) -> Self { Self { builder: self.builder.field( - "layout", + glib::gstr!("layout"), gst::List::new(layouts.into_iter().map(layout_str)), ), } @@ -122,11 +133,11 @@ impl AudioCapsBuilder { } pub fn fallback_channel_mask(self) -> Self { - let channels = self.builder.structure().get::("channels"); + let channels = self.builder.structure().get::(glib::gstr!("channels")); match channels { Ok(channels) => Self { builder: self.builder.field( - "channel-mask", + glib::gstr!("channel-mask"), gst::Bitmask::new(crate::AudioChannelPosition::fallback_mask(channels as u32)), ), }, @@ -161,11 +172,11 @@ fn range_bounds_i32_start_end(range: impl RangeBounds) -> (i32, i32) { (start, end) } -fn layout_str(layout: AudioLayout) -> &'static str { +fn layout_str(layout: AudioLayout) -> &'static glib::GStr { skip_assert_initialized!(); match layout { - crate::AudioLayout::Interleaved => "interleaved", - crate::AudioLayout::NonInterleaved => "non-interleaved", - crate::AudioLayout::__Unknown(_) => "unknown", + crate::AudioLayout::Interleaved => glib::gstr!("interleaved"), + crate::AudioLayout::NonInterleaved => glib::gstr!("non-interleaved"), + crate::AudioLayout::__Unknown(_) => glib::gstr!("unknown"), } } diff --git a/gstreamer-gl/src/caps_features.rs b/gstreamer-gl/src/caps_features.rs index fc048637f..786d426aa 100644 --- a/gstreamer-gl/src/caps_features.rs +++ b/gstreamer-gl/src/caps_features.rs @@ -4,4 +4,4 @@ use gst::CapsFeatures; use once_cell::sync::Lazy; pub static CAPS_FEATURES_MEMORY_GL_MEMORY: Lazy = - Lazy::new(|| CapsFeatures::new(&[*crate::CAPS_FEATURE_MEMORY_GL_MEMORY])); + Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_GL_MEMORY])); diff --git a/gstreamer-gl/sys/src/manual.rs b/gstreamer-gl/sys/src/manual.rs index f0fb6c655..9d2cc0715 100644 --- a/gstreamer-gl/sys/src/manual.rs +++ b/gstreamer-gl/sys/src/manual.rs @@ -1,4 +1,2 @@ -use libc::c_char; - // See https://gitlab.gnome.org/GNOME/gobject-introspection/issues/238 -pub const GST_GL_COLOR_CONVERT_VIDEO_CAPS: *const c_char = b"video/x-raw(memory:GLMemory), format = (string) { RGBA, RGB, RGBx, BGR, BGRx, BGRA, xRGB, xBGR, ARGB, ABGR, Y444, I420, YV12, Y42B, Y41B, NV12, NV21, YUY2, UYVY, AYUV, GRAY8, GRAY16_LE, GRAY16_BE, RGB16, BGR16 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ], texture-target = (string) { 2D, rectangle, external-oes } ; video/x-raw(memory:GLMemory,meta:GstVideoOverlayComposition), format = (string) { RGBA, RGB, RGBx, BGR, BGRx, BGRA, xRGB, xBGR, ARGB, ABGR, Y444, I420, YV12, Y42B, Y41B, NV12, NV21, YUY2, UYVY, AYUV, GRAY8, GRAY16_LE, GRAY16_BE, RGB16, BGR16 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ], texture-target = (string) { 2D, rectangle, external-oes }\0" as *const u8 as *const c_char; +pub const GST_GL_COLOR_CONVERT_VIDEO_CAPS: &[u8] = b"video/x-raw(memory:GLMemory), format = (string) { RGBA, RGB, RGBx, BGR, BGRx, BGRA, xRGB, xBGR, ARGB, ABGR, Y444, I420, YV12, Y42B, Y41B, NV12, NV21, YUY2, UYVY, AYUV, GRAY8, GRAY16_LE, GRAY16_BE, RGB16, BGR16 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ], texture-target = (string) { 2D, rectangle, external-oes } ; video/x-raw(memory:GLMemory,meta:GstVideoOverlayComposition), format = (string) { RGBA, RGB, RGBx, BGR, BGRx, BGRA, xRGB, xBGR, ARGB, ABGR, Y444, I420, YV12, Y42B, Y41B, NV12, NV21, YUY2, UYVY, AYUV, GRAY8, GRAY16_LE, GRAY16_BE, RGB16, BGR16 }, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ], texture-target = (string) { 2D, rectangle, external-oes }\0"; diff --git a/gstreamer-pbutils/src/functions.rs b/gstreamer-pbutils/src/functions.rs index 5cd2fbcba..71338b456 100644 --- a/gstreamer-pbutils/src/functions.rs +++ b/gstreamer-pbutils/src/functions.rs @@ -17,12 +17,12 @@ pub fn pb_utils_add_codec_description_to_tag_list_for_tag<'a, T: CodecTag<'a>>( caps: &gst::CapsRef, ) -> Result<(), glib::BoolError> { assert_initialized_main_thread!(); - let codec_tag = T::tag_name(); + let codec_tag = T::TAG_NAME; unsafe { glib::result_from_gboolean!( ffi::gst_pb_utils_add_codec_description_to_tag_list( taglist.as_mut_ptr(), - codec_tag.to_glib_none().0, + codec_tag.as_ptr(), caps.as_ptr(), ), "Failed to find codec description", diff --git a/gstreamer-rtsp-server/src/lib.rs b/gstreamer-rtsp-server/src/lib.rs index 32ad4b01b..78301869e 100644 --- a/gstreamer-rtsp-server/src/lib.rs +++ b/gstreamer-rtsp-server/src/lib.rs @@ -53,67 +53,34 @@ mod rtsp_token; pub mod subclass; -use std::ffi::CStr; - -use once_cell::sync::Lazy; - pub use crate::{rtsp_context::*, rtsp_thread::*, rtsp_token::*}; -pub static RTSP_ADDRESS_POOL_ANY_IPV4: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV4) - .to_str() - .unwrap() -}); -pub static RTSP_ADDRESS_POOL_ANY_IPV6: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV6) - .to_str() - .unwrap() -}); -pub static RTSP_AUTH_CHECK_CONNECT: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_CONNECT) - .to_str() - .unwrap() -}); -pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS) - .to_str() - .unwrap() -}); -pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT) - .to_str() - .unwrap() -}); -pub static RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS) - .to_str() - .unwrap() -}); -pub static RTSP_AUTH_CHECK_URL: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_URL) - .to_str() - .unwrap() -}); -pub static RTSP_PERM_MEDIA_FACTORY_ACCESS: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_PERM_MEDIA_FACTORY_ACCESS) - .to_str() - .unwrap() -}); -pub static RTSP_PERM_MEDIA_FACTORY_CONSTRUCT: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT) - .to_str() - .unwrap() -}); -pub static RTSP_TOKEN_MEDIA_FACTORY_ROLE: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE) - .to_str() - .unwrap() -}); -pub static RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS) - .to_str() - .unwrap() -}); +pub static RTSP_ADDRESS_POOL_ANY_IPV4: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV4) }; +pub static RTSP_ADDRESS_POOL_ANY_IPV6: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV6) }; +pub static RTSP_AUTH_CHECK_CONNECT: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_CONNECT) }; +pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS) +}; +pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT) +}; +pub static RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS) +}; +pub static RTSP_AUTH_CHECK_URL: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_URL) }; +pub static RTSP_PERM_MEDIA_FACTORY_ACCESS: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_PERM_MEDIA_FACTORY_ACCESS) }; +pub static RTSP_PERM_MEDIA_FACTORY_CONSTRUCT: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT) }; +pub static RTSP_TOKEN_MEDIA_FACTORY_ROLE: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE) }; +pub static RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS) +}; // Re-export all the traits in a prelude module, so that applications // can always "use gst_rtsp_server::prelude::*" without getting conflicts diff --git a/gstreamer-video/src/caps.rs b/gstreamer-video/src/caps.rs index e9ed75c47..538af21a1 100644 --- a/gstreamer-video/src/caps.rs +++ b/gstreamer-video/src/caps.rs @@ -1,5 +1,6 @@ use std::ops::{Bound::*, RangeBounds}; +use glib::IntoGStr; use gst::Caps; use crate::VideoFormat; @@ -10,7 +11,7 @@ pub struct VideoCapsBuilder { impl VideoCapsBuilder { pub fn new() -> Self { - let builder = Caps::builder("video/x-raw"); + let builder = Caps::builder(glib::gstr!("video/x-raw")); let builder = VideoCapsBuilder { builder }; builder .format_list(VideoFormat::iter_raw()) @@ -25,7 +26,10 @@ impl VideoCapsBuilder { } } - pub fn features(self, features: &[&str]) -> VideoCapsBuilder { + pub fn features( + self, + features: impl IntoIterator, + ) -> VideoCapsBuilder { VideoCapsBuilder { builder: self.builder.features(features), } @@ -41,14 +45,14 @@ impl Default for VideoCapsBuilder { impl VideoCapsBuilder { pub fn format(self, format: VideoFormat) -> Self { Self { - builder: self.builder.field("format", format.to_str()), + builder: self.builder.field(glib::gstr!("format"), format.to_str()), } } pub fn format_list(self, formats: impl IntoIterator) -> Self { Self { builder: self.builder.field( - "format", + glib::gstr!("format"), gst::List::new(formats.into_iter().map(|f| f.to_str())), ), } @@ -56,7 +60,7 @@ impl VideoCapsBuilder { pub fn width(self, width: i32) -> Self { Self { - builder: self.builder.field("width", width), + builder: self.builder.field(glib::gstr!("width"), width), } } @@ -64,19 +68,21 @@ impl VideoCapsBuilder { let (start, end) = range_bounds_i32_start_end(widths); let gst_widths: gst::IntRange = gst::IntRange::new(start, end); Self { - builder: self.builder.field("width", gst_widths), + builder: self.builder.field(glib::gstr!("width"), gst_widths), } } pub fn width_list(self, widths: impl IntoIterator) -> Self { Self { - builder: self.builder.field("width", gst::List::new(widths)), + builder: self + .builder + .field(glib::gstr!("width"), gst::List::new(widths)), } } pub fn height(self, height: i32) -> Self { Self { - builder: self.builder.field("height", height), + builder: self.builder.field(glib::gstr!("height"), height), } } @@ -84,19 +90,21 @@ impl VideoCapsBuilder { let (start, end) = range_bounds_i32_start_end(heights); let gst_heights: gst::IntRange = gst::IntRange::new(start, end); Self { - builder: self.builder.field("height", gst_heights), + builder: self.builder.field(glib::gstr!("height"), gst_heights), } } pub fn height_list(self, heights: impl IntoIterator) -> Self { Self { - builder: self.builder.field("height", gst::List::new(heights)), + builder: self + .builder + .field(glib::gstr!("height"), gst::List::new(heights)), } } pub fn framerate(self, framerate: gst::Fraction) -> Self { Self { - builder: self.builder.field("framerate", framerate), + builder: self.builder.field(glib::gstr!("framerate"), framerate), } } @@ -120,13 +128,15 @@ impl VideoCapsBuilder { assert!(start <= end); let framerates: gst::FractionRange = gst::FractionRange::new(start, end); Self { - builder: self.builder.field("framerate", framerates), + builder: self.builder.field(glib::gstr!("framerate"), framerates), } } pub fn framerate_list(self, framerates: impl IntoIterator) -> Self { Self { - builder: self.builder.field("framerate", gst::List::new(framerates)), + builder: self + .builder + .field(glib::gstr!("framerate"), gst::List::new(framerates)), } } diff --git a/gstreamer-video/src/caps_features.rs b/gstreamer-video/src/caps_features.rs index 0b4918486..e5043393d 100644 --- a/gstreamer-video/src/caps_features.rs +++ b/gstreamer-video/src/caps_features.rs @@ -1,53 +1,42 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::ffi::CStr; - use gst::CapsFeatures; use once_cell::sync::Lazy; #[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] -pub static CAPS_FEATURE_FORMAT_INTERLACED: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_CAPS_FEATURE_FORMAT_INTERLACED) - .to_str() - .unwrap() -}); +pub static CAPS_FEATURE_FORMAT_INTERLACED: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_FORMAT_INTERLACED) }; #[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] pub static CAPS_FEATURES_FORMAT_INTERLACED: Lazy = - Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_FORMAT_INTERLACED])); + Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_FORMAT_INTERLACED])); -pub static CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: Lazy<&'static str> = - Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META) - .to_str() - .unwrap() - }); +pub static CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked( + ffi::GST_CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META, + ) +}; pub static CAPS_FEATURES_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: Lazy = - Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META])); + Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META])); -pub static CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: Lazy<&'static str> = - Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META) - .to_str() - .unwrap() - }); +pub static CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked( + ffi::GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, + ) +}; pub static CAPS_FEATURES_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: Lazy = - Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META])); + Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META])); -pub static CAPS_FEATURE_META_GST_VIDEO_META: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_META) - .to_str() - .unwrap() -}); +pub static CAPS_FEATURE_META_GST_VIDEO_META: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_META) }; pub static CAPS_FEATURES_META_GST_VIDEO_META: Lazy = - Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_META_GST_VIDEO_META])); + Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_META_GST_VIDEO_META])); -pub static CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION: Lazy<&'static str> = - Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION) - .to_str() - .unwrap() - }); +pub static CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked( + ffi::GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, + ) +}; pub static CAPS_FEATURES_META_GST_VIDEO_OVERLAY_COMPOSITION: Lazy = - Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION])); + Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION])); diff --git a/gstreamer-video/src/video_buffer_pool.rs b/gstreamer-video/src/video_buffer_pool.rs index 08d610f68..b0083bbc0 100644 --- a/gstreamer-video/src/video_buffer_pool.rs +++ b/gstreamer-video/src/video_buffer_pool.rs @@ -1,32 +1,24 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{ffi::CStr, marker::PhantomData, mem}; +use std::{marker::PhantomData, mem}; use glib::translate::*; -use once_cell::sync::Lazy; -pub static BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META: Lazy<&'static str> = - Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META) - .to_str() - .unwrap() - }); -pub static BUFFER_POOL_OPTION_VIDEO_ALIGNMENT: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT) - .to_str() - .unwrap() -}); -pub static BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META: Lazy<&'static str> = - Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META) - .to_str() - .unwrap() - }); -pub static BUFFER_POOL_OPTION_VIDEO_META: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_META) - .to_str() - .unwrap() -}); +pub static BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked( + ffi::GST_BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META, + ) +}; +pub static BUFFER_POOL_OPTION_VIDEO_ALIGNMENT: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT) +}; +pub static BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META: &glib::GStr = unsafe { + glib::GStr::from_utf8_with_nul_unchecked( + ffi::GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META, + ) +}; +pub static BUFFER_POOL_OPTION_VIDEO_META: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_BUFFER_POOL_OPTION_VIDEO_META) }; #[derive(Debug, Clone)] #[doc(alias = "GstVideoAlignment")] diff --git a/gstreamer-video/src/video_converter.rs b/gstreamer-video/src/video_converter.rs index ff6eb5c0c..685b95a2b 100644 --- a/gstreamer-video/src/video_converter.rs +++ b/gstreamer-video/src/video_converter.rs @@ -184,277 +184,287 @@ impl VideoConverterConfig { } pub fn set_resampler_method(&mut self, v: crate::VideoResamplerMethod) { - self.0.set("GstVideoConverter.resampler-method", v); + self.0 + .set(glib::gstr!("GstVideoConverter.resampler-method"), v); } #[doc(alias = "get_resampler_method")] pub fn resampler_method(&self) -> crate::VideoResamplerMethod { self.0 - .get_optional("GstVideoConverter.resampler-method") + .get_optional(glib::gstr!("GstVideoConverter.resampler-method")) .expect("Wrong type") .unwrap_or(crate::VideoResamplerMethod::Cubic) } pub fn set_chroma_resampler_method(&mut self, v: crate::VideoResamplerMethod) { - self.0.set("GstVideoConverter.chroma-resampler-method", v); + self.0 + .set(glib::gstr!("GstVideoConverter.chroma-resampler-method"), v); } #[doc(alias = "get_chroma_resampler_method")] pub fn chroma_resampler_method(&self) -> crate::VideoResamplerMethod { self.0 - .get_optional("GstVideoConverter.chroma-resampler-method") + .get_optional(glib::gstr!("GstVideoConverter.chroma-resampler-method")) .expect("Wrong type") .unwrap_or(crate::VideoResamplerMethod::Linear) } pub fn set_resampler_taps(&mut self, v: u32) { - self.0.set("GstVideoConverter.resampler-taps", v); + self.0 + .set(glib::gstr!("GstVideoConverter.resampler-taps"), v); } #[doc(alias = "get_resampler_taps")] pub fn resampler_taps(&self) -> u32 { self.0 - .get_optional("GstVideoConverter.resampler-taps") + .get_optional(glib::gstr!("GstVideoConverter.resampler-taps")) .expect("Wrong type") .unwrap_or(0) } pub fn set_dither_method(&mut self, v: crate::VideoDitherMethod) { - self.0.set("GstVideoConverter.dither-method", v); + self.0 + .set(glib::gstr!("GstVideoConverter.dither-method"), v); } #[doc(alias = "get_dither_method")] pub fn dither_method(&self) -> crate::VideoDitherMethod { self.0 - .get_optional("GstVideoConverter.dither-method") + .get_optional(glib::gstr!("GstVideoConverter.dither-method")) .expect("Wrong type") .unwrap_or(crate::VideoDitherMethod::Bayer) } pub fn set_dither_quantization(&mut self, v: u32) { - self.0.set("GstVideoConverter.dither-quantization", v); + self.0 + .set(glib::gstr!("GstVideoConverter.dither-quantization"), v); } #[doc(alias = "get_dither_quantization")] pub fn dither_quantization(&self) -> u32 { self.0 - .get_optional("GstVideoConverter.dither-quantization") + .get_optional(glib::gstr!("GstVideoConverter.dither-quantization")) .expect("Wrong type") .unwrap_or(1) } pub fn set_src_x(&mut self, v: i32) { - self.0.set("GstVideoConverter.src-x", v); + self.0.set(glib::gstr!("GstVideoConverter.src-x"), v); } #[doc(alias = "get_src_x")] pub fn src_x(&self) -> i32 { self.0 - .get_optional("GstVideoConverter.src-x") + .get_optional(glib::gstr!("GstVideoConverter.src-x")) .expect("Wrong type") .unwrap_or(0) } pub fn set_src_y(&mut self, v: i32) { - self.0.set("GstVideoConverter.src-y", v); + self.0.set(glib::gstr!("GstVideoConverter.src-y"), v); } #[doc(alias = "get_src_y")] pub fn src_y(&self) -> i32 { self.0 - .get_optional("GstVideoConverter.src-y") + .get_optional(glib::gstr!("GstVideoConverter.src-y")) .expect("Wrong type") .unwrap_or(0) } pub fn set_src_width(&mut self, v: Option) { if let Some(v) = v { - self.0.set("GstVideoConverter.src-width", v); + self.0.set(glib::gstr!("GstVideoConverter.src-width"), v); } else { - self.0.remove_field("GstVideoConverter.src-width"); + self.0 + .remove_field(glib::gstr!("GstVideoConverter.src-width")); } } #[doc(alias = "get_src_width")] pub fn src_width(&self) -> Option { self.0 - .get_optional("GstVideoConverter.src-width") + .get_optional(glib::gstr!("GstVideoConverter.src-width")) .expect("Wrong type") } pub fn set_src_height(&mut self, v: Option) { if let Some(v) = v { - self.0.set("GstVideoConverter.src-height", v); + self.0.set(glib::gstr!("GstVideoConverter.src-height"), v); } else { - self.0.remove_field("GstVideoConverter.src-height"); + self.0 + .remove_field(glib::gstr!("GstVideoConverter.src-height")); } } #[doc(alias = "get_src_height")] pub fn src_height(&self) -> Option { self.0 - .get_optional("GstVideoConverter.src-height") + .get_optional(glib::gstr!("GstVideoConverter.src-height")) .expect("Wrong type") } pub fn set_dest_x(&mut self, v: i32) { - self.0.set("GstVideoConverter.dest-x", v); + self.0.set(glib::gstr!("GstVideoConverter.dest-x"), v); } #[doc(alias = "get_dest_x")] pub fn dest_x(&self) -> i32 { self.0 - .get_optional("GstVideoConverter.dest-x") + .get_optional(glib::gstr!("GstVideoConverter.dest-x")) .expect("Wrong type") .unwrap_or(0) } pub fn set_dest_y(&mut self, v: i32) { - self.0.set("GstVideoConverter.dest-y", v); + self.0.set(glib::gstr!("GstVideoConverter.dest-y"), v); } #[doc(alias = "get_dest_y")] pub fn dest_y(&self) -> i32 { self.0 - .get_optional("GstVideoConverter.dest-y") + .get_optional(glib::gstr!("GstVideoConverter.dest-y")) .expect("Wrong type") .unwrap_or(0) } pub fn set_dest_width(&mut self, v: Option) { if let Some(v) = v { - self.0.set("GstVideoConverter.dest-width", v); + self.0.set(glib::gstr!("GstVideoConverter.dest-width"), v); } else { - self.0.remove_field("GstVideoConverter.dest-width"); + self.0 + .remove_field(glib::gstr!("GstVideoConverter.dest-width")); } } #[doc(alias = "get_dest_width")] pub fn dest_width(&self) -> Option { self.0 - .get_optional("GstVideoConverter.dest-width") + .get_optional(glib::gstr!("GstVideoConverter.dest-width")) .expect("Wrong type") } pub fn set_dest_height(&mut self, v: Option) { if let Some(v) = v { - self.0.set("GstVideoConverter.dest-height", v); + self.0.set(glib::gstr!("GstVideoConverter.dest-height"), v); } else { - self.0.remove_field("GstVideoConverter.dest-height"); + self.0 + .remove_field(glib::gstr!("GstVideoConverter.dest-height")); } } #[doc(alias = "get_dest_height")] pub fn dest_height(&self) -> Option { self.0 - .get_optional("GstVideoConverter.dest-height") + .get_optional(glib::gstr!("GstVideoConverter.dest-height")) .expect("Wrong type") } pub fn set_fill_border(&mut self, v: bool) { - self.0.set("GstVideoConverter.fill-border", v); + self.0.set(glib::gstr!("GstVideoConverter.fill-border"), v); } #[doc(alias = "get_fill_border")] pub fn fills_border(&self) -> bool { self.0 - .get_optional("GstVideoConverter.fill-border") + .get_optional(glib::gstr!("GstVideoConverter.fill-border")) .expect("Wrong type") .unwrap_or(true) } pub fn set_alpha_value(&mut self, v: f64) { - self.0.set("GstVideoConverter.alpha-value", v); + self.0.set(glib::gstr!("GstVideoConverter.alpha-value"), v); } #[doc(alias = "get_alpha_value")] pub fn alpha_value(&self) -> f64 { self.0 - .get_optional("GstVideoConverter.alpha-value") + .get_optional(glib::gstr!("GstVideoConverter.alpha-value")) .expect("Wrong type") .unwrap_or(1.0) } pub fn set_alpha_mode(&mut self, v: crate::VideoAlphaMode) { - self.0.set("GstVideoConverter.alpha-mode", v); + self.0.set(glib::gstr!("GstVideoConverter.alpha-mode"), v); } #[doc(alias = "get_alpha_mode")] pub fn alpha_mode(&self) -> crate::VideoAlphaMode { self.0 - .get_optional("GstVideoConverter.alpha-mode") + .get_optional(glib::gstr!("GstVideoConverter.alpha-mode")) .expect("Wrong type") .unwrap_or(crate::VideoAlphaMode::Copy) } pub fn set_border_argb(&mut self, v: u32) { - self.0.set("GstVideoConverter.border-argb", v); + self.0.set(glib::gstr!("GstVideoConverter.border-argb"), v); } #[doc(alias = "get_border_argb")] pub fn border_argb(&self) -> u32 { self.0 - .get_optional("GstVideoConverter.border-argb") + .get_optional(glib::gstr!("GstVideoConverter.border-argb")) .expect("Wrong type") .unwrap_or(0xff_00_00_00) } pub fn set_chroma_mode(&mut self, v: crate::VideoChromaMode) { - self.0.set("GstVideoConverter.chroma-mode", v); + self.0.set(glib::gstr!("GstVideoConverter.chroma-mode"), v); } #[doc(alias = "get_chroma_mode")] pub fn chroma_mode(&self) -> crate::VideoChromaMode { self.0 - .get_optional("GstVideoConverter.chroma-mode") + .get_optional(glib::gstr!("GstVideoConverter.chroma-mode")) .expect("Wrong type") .unwrap_or(crate::VideoChromaMode::Full) } pub fn set_matrix_mode(&mut self, v: crate::VideoMatrixMode) { - self.0.set("GstVideoConverter.matrix-mode", v); + self.0.set(glib::gstr!("GstVideoConverter.matrix-mode"), v); } #[doc(alias = "get_matrix_mode")] pub fn matrix_mode(&self) -> crate::VideoMatrixMode { self.0 - .get_optional("GstVideoConverter.matrix-mode") + .get_optional(glib::gstr!("GstVideoConverter.matrix-mode")) .expect("Wrong type") .unwrap_or(crate::VideoMatrixMode::Full) } pub fn set_gamma_mode(&mut self, v: crate::VideoGammaMode) { - self.0.set("GstVideoConverter.gamma-mode", v); + self.0.set(glib::gstr!("GstVideoConverter.gamma-mode"), v); } #[doc(alias = "get_gamma_mode")] pub fn gamma_mode(&self) -> crate::VideoGammaMode { self.0 - .get_optional("GstVideoConverter.gamma-mode") + .get_optional(glib::gstr!("GstVideoConverter.gamma-mode")) .expect("Wrong type") .unwrap_or(crate::VideoGammaMode::None) } pub fn set_primaries_mode(&mut self, v: crate::VideoPrimariesMode) { - self.0.set("GstVideoConverter.primaries-mode", v); + self.0 + .set(glib::gstr!("GstVideoConverter.primaries-mode"), v); } #[doc(alias = "get_primaries_mode")] pub fn primaries_mode(&self) -> crate::VideoPrimariesMode { self.0 - .get_optional("GstVideoConverter.primaries-mode") + .get_optional(glib::gstr!("GstVideoConverter.primaries-mode")) .expect("Wrong type") .unwrap_or(crate::VideoPrimariesMode::None) } pub fn set_threads(&mut self, v: u32) { - self.0.set("GstVideoConverter.threads", v); + self.0.set(glib::gstr!("GstVideoConverter.threads"), v); } #[doc(alias = "get_threads")] pub fn threads(&self) -> u32 { self.0 - .get_optional("GstVideoConverter.threads") + .get_optional(glib::gstr!("GstVideoConverter.threads")) .expect("Wrong type") .unwrap_or(1) } diff --git a/gstreamer-video/src/video_format.rs b/gstreamer-video/src/video_format.rs index 1110ad873..ef8d18beb 100644 --- a/gstreamer-video/src/video_format.rs +++ b/gstreamer-video/src/video_format.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{ffi::CStr, str}; +use std::str; use glib::translate::{from_glib, FromGlib, IntoGlib}; use once_cell::sync::Lazy; @@ -269,18 +269,16 @@ impl crate::VideoFormat { } #[doc(alias = "gst_video_format_to_string")] - pub fn to_str<'a>(self) -> &'a str { + pub fn to_str<'a>(self) -> &'a glib::GStr { if self == Self::Unknown { - return "UNKNOWN"; + return glib::gstr!("UNKNOWN"); } unsafe { - CStr::from_ptr( + glib::GStr::from_ptr( ffi::gst_video_format_to_string(self.into_glib()) .as_ref() .expect("gst_video_format_to_string returned NULL"), ) - .to_str() - .expect("gst_video_format_to_string returned an invalid string") } } diff --git a/gstreamer-video/src/video_format_info.rs b/gstreamer-video/src/video_format_info.rs index 4a13fd2e9..b69f9f2b9 100644 --- a/gstreamer-video/src/video_format_info.rs +++ b/gstreamer-video/src/video_format_info.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{cmp::Ordering, ffi::CStr, fmt, marker::PhantomData, str}; +use std::{cmp::Ordering, fmt, marker::PhantomData, str}; use glib::translate::{from_glib, IntoGlib, ToGlibPtr}; @@ -32,13 +32,13 @@ impl VideoFormatInfo { } #[inline] - pub fn name<'a>(&self) -> &'a str { - unsafe { CStr::from_ptr(self.0.name).to_str().unwrap() } + pub fn name<'a>(&self) -> &'a glib::GStr { + unsafe { glib::GStr::from_ptr(self.0.name) } } #[inline] - pub fn description<'a>(&self) -> &'a str { - unsafe { CStr::from_ptr(self.0.description).to_str().unwrap() } + pub fn description<'a>(&self) -> &'a glib::GStr { + unsafe { glib::GStr::from_ptr(self.0.description) } } #[inline] diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index aab365c7d..d1dcc2831 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -5,7 +5,7 @@ use std::{fmt, marker::PhantomData, ptr, str}; use glib::{ translate::{from_glib, from_glib_full, FromGlibPtrFull, IntoGlib, IntoGlibPtr, ToGlibPtr}, value::ToSendValue, - StaticType, + IntoGStr, StaticType, }; use crate::{caps_features::*, structure::*, CapsIntersectMode}; @@ -14,7 +14,7 @@ mini_object_wrapper!(Caps, CapsRef, ffi::GstCaps, || { ffi::gst_caps_get_type() impl Caps { #[doc(alias = "gst_caps_new_simple")] - pub fn builder(name: &str) -> Builder { + pub fn builder(name: impl IntoGStr) -> Builder { assert_initialized_main_thread!(); Builder::new(name) } @@ -50,7 +50,9 @@ impl Caps { } #[doc(alias = "gst_caps_new_simple")] - pub fn new_simple(name: &str, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Self { + #[deprecated = "Use `Caps::builder()` or `Caps::new_empty()`"] + #[allow(deprecated)] + pub fn new_simple(name: impl IntoGStr, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Self { skip_assert_initialized!(); let mut caps = Caps::new_empty(); @@ -61,9 +63,14 @@ impl Caps { } #[doc(alias = "gst_caps_new_empty_simple")] - pub fn new_empty_simple(name: &str) -> Self { + pub fn new_empty_simple(name: impl IntoGStr) -> Self { skip_assert_initialized!(); - Self::new_simple(name, &[]) + let mut caps = Caps::new_empty(); + + let structure = Structure::new_empty(name); + caps.get_mut().unwrap().append_structure(structure); + + caps } #[doc(alias = "gst_caps_fixate")] @@ -142,8 +149,10 @@ impl str::FromStr for Caps { fn from_str(s: &str) -> Result { assert_initialized_main_thread!(); unsafe { - Option::<_>::from_glib_full(ffi::gst_caps_from_string(s.to_glib_none().0)) - .ok_or_else(|| glib::bool_error!("Failed to parse caps from string")) + s.run_with_gstr(|s| { + Option::<_>::from_glib_full(ffi::gst_caps_from_string(s.as_ptr())) + .ok_or_else(|| glib::bool_error!("Failed to parse caps from string")) + }) } } } @@ -234,7 +243,23 @@ impl std::iter::Extend for CapsRef { } impl CapsRef { + #[doc(alias = "gst_caps_set_value")] + pub fn set(&mut self, name: impl IntoGStr, value: impl ToSendValue + Sync) { + let value = value.to_send_value(); + self.set_value(name, value); + } + + #[doc(alias = "gst_caps_set_value")] + pub fn set_value(&mut self, name: impl IntoGStr, value: glib::SendValue) { + unsafe { + name.run_with_gstr(|name| { + ffi::gst_caps_set_value(self.as_mut_ptr(), name.as_ptr(), value.to_glib_none().0) + }); + } + } + #[doc(alias = "gst_caps_set_simple")] + #[deprecated = "Use `CapsRef::set()`"] pub fn set_simple(&mut self, values: &[(&str, &(dyn ToSendValue + Sync))]) { for &(name, value) in values { let value = value.to_value(); @@ -913,7 +938,7 @@ impl fmt::Debug for Builder { } impl Builder { - fn new(name: &str) -> Builder { + fn new(name: impl IntoGStr) -> Builder { skip_assert_initialized!(); Builder { s: crate::Structure::new_empty(name), @@ -922,7 +947,10 @@ impl Builder { } } - pub fn features(self, features: &[&str]) -> Builder { + pub fn features( + self, + features: impl IntoIterator, + ) -> Builder { Builder { s: self.s, features: Some(CapsFeatures::new(features)), @@ -940,7 +968,7 @@ impl Builder { } impl Builder { - pub fn field(mut self, name: &str, value: impl Into + Send) -> Self { + pub fn field(mut self, name: impl IntoGStr, value: impl Into + Send) -> Self { self.s.set(name, value); self } @@ -1058,6 +1086,7 @@ mod tests { use crate::{Array, Fraction}; #[test] + #[allow(deprecated)] fn test_simple() { crate::init().unwrap(); @@ -1100,12 +1129,12 @@ mod tests { { let caps = caps.get_mut().unwrap(); - caps.set_features(0, Some(CapsFeatures::new(&["foo:bla"]))); + caps.set_features(0, Some(CapsFeatures::new(["foo:bla"]))); } assert!(caps .features(0) .unwrap() - .is_equal(CapsFeatures::new(&["foo:bla"]).as_ref())); + .is_equal(CapsFeatures::new(["foo:bla"]).as_ref())); } #[test] @@ -1132,7 +1161,7 @@ mod tests { let caps = Caps::builder("foo/bar") .field("int", 12) - .features(&["foo:bla", "foo:baz"]) + .features(["foo:bla", "foo:baz"]) .build(); assert_eq!(caps.to_string(), "foo/bar(foo:bla, foo:baz), int=(int)12"); } @@ -1172,7 +1201,7 @@ mod tests { .structure_with_any_features(Structure::builder("audio/x-raw").build()) .structure_with_features( Structure::builder("video/x-raw").build(), - CapsFeatures::new(&["foo:bla", "foo:baz"]), + CapsFeatures::new(["foo:bla", "foo:baz"]), ) .build(); assert_eq!( @@ -1185,11 +1214,11 @@ mod tests { fn test_builder_full_with_features() { crate::init().unwrap(); - let caps = Caps::builder_full_with_features(CapsFeatures::new(&["foo:bla"])) + let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla"])) .structure(Structure::builder("audio/x-raw").build()) .structure_with_features( Structure::builder("video/x-raw").build(), - CapsFeatures::new(&["foo:baz"]), + CapsFeatures::new(["foo:baz"]), ) .build(); assert_eq!( @@ -1253,7 +1282,7 @@ mod tests { .build(); assert_eq!(format!("{:?}", caps), "Caps(audio/x-raw(ANY))"); - let caps = Caps::builder_full_with_features(CapsFeatures::new(&["foo:bla"])) + let caps = Caps::builder_full_with_features(CapsFeatures::new(["foo:bla"])) .structure( Structure::builder("audio/x-raw") .field( diff --git a/gstreamer/src/caps_features.rs b/gstreamer/src/caps_features.rs index 7abad52f1..2477d9c62 100644 --- a/gstreamer/src/caps_features.rs +++ b/gstreamer/src/caps_features.rs @@ -2,7 +2,6 @@ use std::{ borrow::{Borrow, BorrowMut, ToOwned}, - ffi::CStr, fmt, marker::PhantomData, mem, @@ -10,7 +9,7 @@ use std::{ ptr, str, }; -use glib::{translate::*, StaticType}; +use glib::{translate::*, IntoGStr, StaticType}; use once_cell::sync::Lazy; #[doc(alias = "GstCapsFeatures")] @@ -21,7 +20,7 @@ unsafe impl Sync for CapsFeatures {} impl CapsFeatures { #[doc(alias = "gst_caps_features_new")] - pub fn new(features: &[&str]) -> Self { + pub fn new(features: impl IntoIterator) -> Self { skip_assert_initialized!(); let mut f = Self::new_empty(); @@ -33,12 +32,12 @@ impl CapsFeatures { } #[doc(alias = "gst_caps_features_new_id")] - pub fn from_quarks(features: &[glib::Quark]) -> Self { + pub fn from_quarks(features: impl IntoIterator) -> Self { skip_assert_initialized!(); let mut f = Self::new_empty(); - for feature in features { - f.add_from_quark(*feature); + for feature in features.into_iter() { + f.add_from_quark(feature); } f @@ -140,7 +139,7 @@ impl str::FromStr for CapsFeatures { fn from_str(s: &str) -> Result { assert_initialized_main_thread!(); unsafe { - let ptr = ffi::gst_caps_features_from_string(s.to_glib_none().0); + let ptr = s.run_with_gstr(|s| ffi::gst_caps_features_from_string(s.as_ptr())); if ptr.is_null() { return Err(glib::bool_error!( "Failed to parse caps features from string" @@ -361,12 +360,14 @@ impl CapsFeaturesRef { } #[doc(alias = "gst_caps_features_contains")] - pub fn contains(&self, feature: &str) -> bool { + pub fn contains(&self, feature: impl IntoGStr) -> bool { unsafe { - from_glib(ffi::gst_caps_features_contains( - self.as_ptr(), - feature.to_glib_none().0, - )) + feature.run_with_gstr(|feature| { + from_glib(ffi::gst_caps_features_contains( + self.as_ptr(), + feature.as_ptr(), + )) + }) } } @@ -388,7 +389,7 @@ impl CapsFeaturesRef { #[doc(alias = "get_nth")] #[doc(alias = "gst_caps_features_get_nth")] - pub fn nth(&self, idx: u32) -> Option<&str> { + pub fn nth(&self, idx: u32) -> Option<&glib::GStr> { if idx >= self.size() { return None; } @@ -399,7 +400,7 @@ impl CapsFeaturesRef { return None; } - Some(CStr::from_ptr(feature).to_str().unwrap()) + Some(glib::GStr::from_ptr(feature)) } } @@ -416,13 +417,21 @@ impl CapsFeaturesRef { } #[doc(alias = "gst_caps_features_add")] - pub fn add(&mut self, feature: &str) { - unsafe { ffi::gst_caps_features_add(self.as_mut_ptr(), feature.to_glib_none().0) } + pub fn add(&mut self, feature: impl IntoGStr) { + unsafe { + feature.run_with_gstr(|feature| { + ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ptr()) + }) + } } #[doc(alias = "gst_caps_features_remove")] - pub fn remove(&mut self, feature: &str) { - unsafe { ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.to_glib_none().0) } + pub fn remove(&mut self, feature: impl IntoGStr) { + unsafe { + feature.run_with_gstr(|feature| { + ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.as_ptr()) + }) + } } #[doc(alias = "gst_caps_features_add_id")] @@ -464,12 +473,24 @@ impl<'a> std::iter::Extend<&'a str> for CapsFeaturesRef { } } +impl<'a> std::iter::Extend<&'a glib::GStr> for CapsFeaturesRef { + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(|f| self.add(f)); + } +} + impl std::iter::Extend for CapsFeaturesRef { fn extend>(&mut self, iter: T) { iter.into_iter().for_each(|f| self.add(&f)); } } +impl std::iter::Extend for CapsFeaturesRef { + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(|f| self.add(&f)); + } +} + impl std::iter::Extend for CapsFeaturesRef { fn extend>(&mut self, iter: T) { iter.into_iter().for_each(|f| self.add_from_quark(f)); @@ -537,7 +558,7 @@ impl<'a> Iter<'a> { } impl<'a> Iterator for Iter<'a> { - type Item = &'a str; + type Item = &'a glib::GStr; fn next(&mut self) -> Option { if self.idx >= self.n_features { @@ -551,7 +572,7 @@ impl<'a> Iterator for Iter<'a> { self.idx += 1; - Some(CStr::from_ptr(feature).to_str().unwrap()) + Some(glib::GStr::from_ptr(feature)) } } @@ -577,7 +598,7 @@ impl<'a> Iterator for Iter<'a> { let feature = ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), end as u32); debug_assert!(!feature.is_null()); - Some(CStr::from_ptr(feature).to_str().unwrap()) + Some(glib::GStr::from_ptr(feature)) } } } @@ -592,7 +613,7 @@ impl<'a> Iterator for Iter<'a> { self.n_features as u32 - 1, ); debug_assert!(!feature.is_null()); - Some(CStr::from_ptr(feature).to_str().unwrap()) + Some(glib::GStr::from_ptr(feature)) } } } @@ -611,7 +632,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> { ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.n_features as u32); debug_assert!(!feature.is_null()); - Some(CStr::from_ptr(feature).to_str().unwrap()) + Some(glib::GStr::from_ptr(feature)) } } @@ -629,7 +650,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> { ); debug_assert!(!feature.is_null()); - Some(CStr::from_ptr(feature).to_str().unwrap()) + Some(glib::GStr::from_ptr(feature)) } } } @@ -641,7 +662,7 @@ impl<'a> std::iter::FusedIterator for Iter<'a> {} impl<'a> IntoIterator for &'a CapsFeaturesRef { type IntoIter = Iter<'a>; - type Item = &'a str; + type Item = &'a glib::GStr; fn into_iter(self) -> Self::IntoIter { self.iter() @@ -659,6 +680,18 @@ impl<'a> std::iter::FromIterator<&'a str> for CapsFeatures { } } +impl<'a> std::iter::FromIterator<&'a glib::GStr> for CapsFeatures { + fn from_iter>(iter: T) -> Self { + assert_initialized_main_thread!(); + + let mut features = CapsFeatures::new_empty(); + + iter.into_iter().for_each(|f| features.add(f)); + + features + } +} + impl std::iter::FromIterator for CapsFeatures { fn from_iter>(iter: T) -> Self { skip_assert_initialized!(); @@ -670,6 +703,18 @@ impl std::iter::FromIterator for CapsFeatures { } } +impl std::iter::FromIterator for CapsFeatures { + fn from_iter>(iter: T) -> Self { + assert_initialized_main_thread!(); + + let mut features = CapsFeatures::new_empty(); + + iter.into_iter().for_each(|f| features.add(&f)); + + features + } +} + impl std::iter::FromIterator for CapsFeatures { fn from_iter>(iter: T) -> Self { skip_assert_initialized!(); @@ -710,13 +755,10 @@ impl ToOwned for CapsFeaturesRef { unsafe impl Sync for CapsFeaturesRef {} unsafe impl Send for CapsFeaturesRef {} -pub static CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) - .to_str() - .unwrap() -}); +pub static CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) }; pub static CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: Lazy = - Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_MEMORY_SYSTEM_MEMORY])); + Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_MEMORY_SYSTEM_MEMORY])); #[cfg(test)] mod tests { diff --git a/gstreamer/src/caps_features_serde.rs b/gstreamer/src/caps_features_serde.rs index fb966ad52..2fb32e839 100644 --- a/gstreamer/src/caps_features_serde.rs +++ b/gstreamer/src/caps_features_serde.rs @@ -33,7 +33,7 @@ impl<'a> Serialize for CapsFeaturesForIterSe<'a> { if size > 0 { let mut seq = serializer.serialize_seq(Some(size))?; for feature in iter { - seq.serialize_element(feature)?; + seq.serialize_element(feature.as_str())?; } seq.end() } else { @@ -81,7 +81,7 @@ impl<'de> Visitor<'de> for CapsFeaturesSomeVisitor { fn visit_seq>(self, mut seq: A) -> Result { let mut features = CapsFeatures::new_empty(); while let Some(feature) = seq.next_element::()? { - features.add(feature.as_ref()); + features.add(feature.as_str()); } Ok(CapsFeaturesSome(features)) } diff --git a/gstreamer/src/caps_serde.rs b/gstreamer/src/caps_serde.rs index f3ef31c90..4e9f8d90a 100644 --- a/gstreamer/src/caps_serde.rs +++ b/gstreamer/src/caps_serde.rs @@ -262,7 +262,7 @@ mod tests { .field("string", "bla") .field("fraction", Fraction::new(1, 2)) .field("array", Array::new([1, 2])) - .features(&["foo:bar", "foo:baz"]) + .features(["foo:bar", "foo:baz"]) .build(); let pretty_config = ron::ser::PrettyConfig::new().new_line("".to_string()); @@ -405,7 +405,7 @@ mod tests { .as_ref() ); let f = caps.features(0).unwrap(); - assert!(f.is_equal(CapsFeatures::new(&["foo:bar", "foo:baz"]).as_ref())); + assert!(f.is_equal(CapsFeatures::new(["foo:bar", "foo:baz"]).as_ref())); let caps_ron = r#" Some([ @@ -471,7 +471,7 @@ mod tests { .field("string", "bla") .field("fraction", Fraction::new(1, 2)) .field("array", Array::new([1, 2])) - .features(&["foo:bar", "foo:baz"]) + .features(["foo:bar", "foo:baz"]) .build(); let caps_ser = ron::ser::to_string(&caps).unwrap(); let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap(); diff --git a/gstreamer/src/device_provider_factory.rs b/gstreamer/src/device_provider_factory.rs index 5c318e3bb..50dd2f7a9 100644 --- a/gstreamer/src/device_provider_factory.rs +++ b/gstreamer/src/device_provider_factory.rs @@ -41,36 +41,36 @@ impl DeviceProviderFactory { #[doc(alias = "get_longname")] #[doc(alias = "gst_device_provider_factory_get_longname")] pub fn longname(&self) -> &str { - self.metadata(&ELEMENT_METADATA_LONGNAME).unwrap() + self.metadata(ELEMENT_METADATA_LONGNAME).unwrap() } #[doc(alias = "get_klass")] #[doc(alias = "gst_device_provider_factory_get_klass")] pub fn klass(&self) -> &str { - self.metadata(&ELEMENT_METADATA_KLASS).unwrap() + self.metadata(ELEMENT_METADATA_KLASS).unwrap() } #[doc(alias = "get_description")] #[doc(alias = "gst_device_provider_factory_get_description")] pub fn description(&self) -> &str { - self.metadata(&ELEMENT_METADATA_DESCRIPTION).unwrap() + self.metadata(ELEMENT_METADATA_DESCRIPTION).unwrap() } #[doc(alias = "get_author")] #[doc(alias = "gst_device_provider_factory_get_author")] pub fn author(&self) -> &str { - self.metadata(&ELEMENT_METADATA_AUTHOR).unwrap() + self.metadata(ELEMENT_METADATA_AUTHOR).unwrap() } #[doc(alias = "get_documentation_uri")] #[doc(alias = "gst_device_provider_factory_get_documentation_uri")] pub fn documentation_uri(&self) -> Option<&str> { - self.metadata(&ELEMENT_METADATA_DOC_URI) + self.metadata(ELEMENT_METADATA_DOC_URI) } #[doc(alias = "get_icon_name")] #[doc(alias = "gst_device_provider_factory_get_icon_name")] pub fn icon_name(&self) -> Option<&str> { - self.metadata(&ELEMENT_METADATA_ICON_NAME) + self.metadata(ELEMENT_METADATA_ICON_NAME) } } diff --git a/gstreamer/src/element.rs b/gstreamer/src/element.rs index 8f3095b2a..ced33cfde 100644 --- a/gstreamer/src/element.rs +++ b/gstreamer/src/element.rs @@ -3,7 +3,6 @@ use std::{ffi::CStr, future::Future, mem, num::NonZeroU64, pin::Pin}; use glib::translate::*; -use once_cell::sync::Lazy; use crate::{ format::{ @@ -982,41 +981,23 @@ pub unsafe trait ElementClassExt { unsafe impl + glib::object::IsClass> ElementClassExt for glib::object::Class {} #[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")] -pub static ELEMENT_METADATA_AUTHOR: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_ELEMENT_METADATA_AUTHOR) - .to_str() - .unwrap() -}); +pub static ELEMENT_METADATA_AUTHOR: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) }; #[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")] -pub static ELEMENT_METADATA_DESCRIPTION: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_ELEMENT_METADATA_DESCRIPTION) - .to_str() - .unwrap() -}); +pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) }; #[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")] -pub static ELEMENT_METADATA_DOC_URI: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_ELEMENT_METADATA_DOC_URI) - .to_str() - .unwrap() -}); +pub static ELEMENT_METADATA_DOC_URI: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) }; #[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")] -pub static ELEMENT_METADATA_ICON_NAME: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_ELEMENT_METADATA_ICON_NAME) - .to_str() - .unwrap() -}); +pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) }; #[doc(alias = "GST_ELEMENT_METADATA_KLASS")] -pub static ELEMENT_METADATA_KLASS: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_ELEMENT_METADATA_KLASS) - .to_str() - .unwrap() -}); +pub static ELEMENT_METADATA_KLASS: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) }; #[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")] -pub static ELEMENT_METADATA_LONGNAME: Lazy<&'static str> = Lazy::new(|| unsafe { - CStr::from_ptr(ffi::GST_ELEMENT_METADATA_LONGNAME) - .to_str() - .unwrap() -}); +pub static ELEMENT_METADATA_LONGNAME: &glib::GStr = + unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) }; #[doc(alias = "GST_ELEMENT_ERROR")] #[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")] diff --git a/gstreamer/src/element_factory.rs b/gstreamer/src/element_factory.rs index 3f8784b81..f46a0aa24 100644 --- a/gstreamer/src/element_factory.rs +++ b/gstreamer/src/element_factory.rs @@ -140,37 +140,37 @@ impl ElementFactory { #[doc(alias = "get_longname")] #[doc(alias = "gst_element_factory_get_longname")] pub fn longname(&self) -> &str { - self.metadata(&ELEMENT_METADATA_LONGNAME).unwrap() + self.metadata(ELEMENT_METADATA_LONGNAME).unwrap() } #[doc(alias = "get_klass")] #[doc(alias = "gst_element_factory_get_klass")] pub fn klass(&self) -> &str { - self.metadata(&ELEMENT_METADATA_KLASS).unwrap() + self.metadata(ELEMENT_METADATA_KLASS).unwrap() } #[doc(alias = "get_description")] #[doc(alias = "gst_element_factory_get_description")] pub fn description(&self) -> &str { - self.metadata(&ELEMENT_METADATA_DESCRIPTION).unwrap() + self.metadata(ELEMENT_METADATA_DESCRIPTION).unwrap() } #[doc(alias = "get_author")] #[doc(alias = "gst_element_factory_get_author")] pub fn author(&self) -> &str { - self.metadata(&ELEMENT_METADATA_AUTHOR).unwrap() + self.metadata(ELEMENT_METADATA_AUTHOR).unwrap() } #[doc(alias = "get_documentation_uri")] #[doc(alias = "gst_element_factory_get_documentation_uri")] pub fn documentation_uri(&self) -> Option<&str> { - self.metadata(&ELEMENT_METADATA_DOC_URI) + self.metadata(ELEMENT_METADATA_DOC_URI) } #[doc(alias = "get_icon_name")] #[doc(alias = "gst_element_factory_get_icon_name")] pub fn icon_name(&self) -> Option<&str> { - self.metadata(&ELEMENT_METADATA_ICON_NAME) + self.metadata(ELEMENT_METADATA_ICON_NAME) } #[doc(alias = "gst_element_factory_can_sink_all_caps")] diff --git a/gstreamer/src/static_caps.rs b/gstreamer/src/static_caps.rs index 7919fb7a7..6b8745626 100644 --- a/gstreamer/src/static_caps.rs +++ b/gstreamer/src/static_caps.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{ffi::CStr, fmt, marker::PhantomData, ptr}; +use std::{fmt, marker::PhantomData, ptr}; use glib::{translate::*, StaticType}; @@ -25,7 +25,7 @@ impl fmt::Debug for StaticCaps { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("StaticCaps") .field("str", &unsafe { - CStr::from_ptr(self.0.as_ref().string).to_str() + glib::GStr::from_ptr(self.0.as_ref().string) }) .finish() } diff --git a/gstreamer/src/structure.rs b/gstreamer/src/structure.rs index 4deaac5bc..9f1197106 100644 --- a/gstreamer/src/structure.rs +++ b/gstreamer/src/structure.rs @@ -2,7 +2,6 @@ use std::{ borrow::{Borrow, BorrowMut, ToOwned}, - ffi::CStr, fmt, marker::PhantomData, mem, @@ -11,9 +10,10 @@ use std::{ }; use glib::{ + prelude::*, translate::*, value::{FromValue, SendValue, ToSendValue}, - StaticType, + IntoGStr, }; use crate::Fraction; @@ -50,23 +50,24 @@ unsafe impl Sync for Structure {} impl Structure { #[doc(alias = "gst_structure_new")] - pub fn builder(name: &str) -> Builder { + pub fn builder(name: impl IntoGStr) -> Builder { skip_assert_initialized!(); Builder::new(name) } #[doc(alias = "gst_structure_new_empty")] - pub fn new_empty(name: &str) -> Structure { + pub fn new_empty(name: impl IntoGStr) -> Structure { assert_initialized_main_thread!(); unsafe { - let ptr = ffi::gst_structure_new_empty(name.to_glib_none().0); + let ptr = name.run_with_gstr(|name| ffi::gst_structure_new_empty(name.as_ptr())); debug_assert!(!ptr.is_null()); Structure(ptr::NonNull::new_unchecked(ptr)) } } #[doc(alias = "gst_structure_new")] - pub fn new(name: &str, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Structure { + #[deprecated = "Use `Structure::builder()` or `Structure::new_empty()`"] + pub fn new(name: impl IntoGStr, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Structure { skip_assert_initialized!(); let mut structure = Structure::new_empty(name); @@ -79,8 +80,8 @@ impl Structure { #[allow(clippy::should_implement_trait)] pub fn from_iter<'a>( - name: &str, - iter: impl IntoIterator, + name: impl IntoGStr, + iter: impl IntoIterator, ) -> Structure { skip_assert_initialized!(); let mut structure = Structure::new_empty(name); @@ -189,7 +190,8 @@ impl str::FromStr for Structure { fn from_str(s: &str) -> Result { assert_initialized_main_thread!(); unsafe { - let structure = ffi::gst_structure_from_string(s.to_glib_none().0, ptr::null_mut()); + let structure = + s.run_with_gstr(|s| ffi::gst_structure_from_string(s.as_ptr(), ptr::null_mut())); if structure.is_null() { Err(glib::bool_error!("Failed to parse structure from string")) } else { @@ -429,7 +431,7 @@ impl StructureRef { #[doc(alias = "gst_structure_get")] pub fn get<'a, T: FromValue<'a>>( &'a self, - name: &str, + name: impl IntoGStr, ) -> Result>::Checker as glib::value::ValueTypeChecker>::Error>> { let name = glib::Quark::from_str(name); @@ -439,7 +441,7 @@ impl StructureRef { #[doc(alias = "gst_structure_get")] pub fn get_optional<'a, T: FromValue<'a>>( &'a self, - name: &str, + name: impl IntoGStr, ) -> Result< Option, GetError<<>::Checker as glib::value::ValueTypeChecker>::Error>, @@ -450,7 +452,10 @@ impl StructureRef { #[doc(alias = "get_value")] #[doc(alias = "gst_structure_get_value")] - pub fn value(&self, name: &str) -> Result<&SendValue, GetError> { + pub fn value( + &self, + name: impl IntoGStr, + ) -> Result<&SendValue, GetError> { let name = glib::Quark::from_str(name); self.value_by_quark(name) } @@ -502,19 +507,17 @@ impl StructureRef { } #[doc(alias = "gst_structure_set")] - pub fn set(&mut self, name: &str, value: impl Into + Send) { + pub fn set(&mut self, name: impl IntoGStr, value: impl Into + Send) { let value = glib::SendValue::from_owned(value); self.set_value(name, value); } #[doc(alias = "gst_structure_set_value")] - pub fn set_value(&mut self, name: &str, value: SendValue) { + pub fn set_value(&mut self, name: impl IntoGStr, value: SendValue) { unsafe { - ffi::gst_structure_take_value( - &mut self.0, - name.to_glib_none().0, - &mut value.into_raw(), - ); + name.run_with_gstr(|name| { + ffi::gst_structure_take_value(&mut self.0, name.as_ptr(), &mut value.into_raw()) + }); } } @@ -533,12 +536,8 @@ impl StructureRef { #[doc(alias = "get_name")] #[doc(alias = "gst_structure_get_name")] - pub fn name<'a>(&self) -> &'a str { - unsafe { - CStr::from_ptr(ffi::gst_structure_get_name(&self.0)) - .to_str() - .unwrap() - } + pub fn name<'a>(&self) -> &'a glib::GStr { + unsafe { glib::GStr::from_ptr(ffi::gst_structure_get_name(&self.0)) } } #[doc(alias = "gst_structure_get_name_id")] @@ -547,8 +546,10 @@ impl StructureRef { } #[doc(alias = "gst_structure_set_name")] - pub fn set_name(&mut self, name: &str) { - unsafe { ffi::gst_structure_set_name(&mut self.0, name.to_glib_none().0) } + pub fn set_name(&mut self, name: impl IntoGStr) { + unsafe { + name.run_with_gstr(|name| ffi::gst_structure_set_name(&mut self.0, name.as_ptr())) + } } #[doc(alias = "gst_structure_has_name")] @@ -557,23 +558,24 @@ impl StructureRef { } #[doc(alias = "gst_structure_has_field")] - pub fn has_field(&self, field: &str) -> bool { + pub fn has_field(&self, field: impl IntoGStr) -> bool { unsafe { - from_glib(ffi::gst_structure_has_field( - &self.0, - field.to_glib_none().0, - )) + field.run_with_gstr(|field| { + from_glib(ffi::gst_structure_has_field(&self.0, field.as_ptr())) + }) } } #[doc(alias = "gst_structure_has_field_typed")] - pub fn has_field_with_type(&self, field: &str, type_: glib::Type) -> bool { + pub fn has_field_with_type(&self, field: impl IntoGStr, type_: glib::Type) -> bool { unsafe { - from_glib(ffi::gst_structure_has_field_typed( - &self.0, - field.to_glib_none().0, - type_.into_glib(), - )) + field.run_with_gstr(|field| { + from_glib(ffi::gst_structure_has_field_typed( + &self.0, + field.as_ptr(), + type_.into_glib(), + )) + }) } } @@ -594,15 +596,17 @@ impl StructureRef { } #[doc(alias = "gst_structure_remove_field")] - pub fn remove_field(&mut self, field: &str) { + pub fn remove_field(&mut self, field: impl IntoGStr) { unsafe { - ffi::gst_structure_remove_field(&mut self.0, field.to_glib_none().0); + field.run_with_gstr(|field| { + ffi::gst_structure_remove_field(&mut self.0, field.as_ptr()) + }); } } #[doc(alias = "gst_structure_remove_fields")] - pub fn remove_fields(&mut self, fields: &[&str]) { - for f in fields { + pub fn remove_fields(&mut self, fields: impl IntoIterator) { + for f in fields.into_iter() { self.remove_field(f) } } @@ -624,7 +628,7 @@ impl StructureRef { #[doc(alias = "get_nth_field_name")] #[doc(alias = "gst_structure_nth_field_name")] - pub fn nth_field_name<'a>(&self, idx: u32) -> Option<&'a str> { + pub fn nth_field_name<'a>(&self, idx: u32) -> Option<&'a glib::GStr> { if idx >= self.n_fields() { return None; } @@ -633,7 +637,7 @@ impl StructureRef { let field_name = ffi::gst_structure_nth_field_name(&self.0, idx); debug_assert!(!field_name.is_null()); - Some(CStr::from_ptr(field_name).to_str().unwrap()) + Some(glib::GStr::from_ptr(field_name)) } } @@ -663,75 +667,86 @@ impl StructureRef { } #[doc(alias = "gst_structure_fixate_field")] - pub fn fixate_field(&mut self, name: &str) -> bool { + pub fn fixate_field(&mut self, name: impl IntoGStr) -> bool { unsafe { - from_glib(ffi::gst_structure_fixate_field( - &mut self.0, - name.to_glib_none().0, - )) + name.run_with_gstr(|name| { + from_glib(ffi::gst_structure_fixate_field(&mut self.0, name.as_ptr())) + }) } } #[doc(alias = "gst_structure_fixate_field_boolean")] - pub fn fixate_field_bool(&mut self, name: &str, target: bool) -> bool { + pub fn fixate_field_bool(&mut self, name: impl IntoGStr, target: bool) -> bool { unsafe { - from_glib(ffi::gst_structure_fixate_field_boolean( - &mut self.0, - name.to_glib_none().0, - target.into_glib(), - )) + name.run_with_gstr(|name| { + from_glib(ffi::gst_structure_fixate_field_boolean( + &mut self.0, + name.as_ptr(), + target.into_glib(), + )) + }) } } #[doc(alias = "gst_structure_fixate_field_string")] - pub fn fixate_field_str(&mut self, name: &str, target: &str) -> bool { + pub fn fixate_field_str(&mut self, name: impl IntoGStr, target: impl IntoGStr) -> bool { unsafe { - from_glib(ffi::gst_structure_fixate_field_string( - &mut self.0, - name.to_glib_none().0, - target.to_glib_none().0, - )) + name.run_with_gstr(|name| { + target.run_with_gstr(|target| { + from_glib(ffi::gst_structure_fixate_field_string( + &mut self.0, + name.as_ptr(), + target.as_ptr(), + )) + }) + }) } } #[doc(alias = "gst_structure_fixate_field_nearest_double")] - pub fn fixate_field_nearest_double(&mut self, name: &str, target: f64) -> bool { + pub fn fixate_field_nearest_double(&mut self, name: impl IntoGStr, target: f64) -> bool { unsafe { - from_glib(ffi::gst_structure_fixate_field_nearest_double( - &mut self.0, - name.to_glib_none().0, - target, - )) + name.run_with_gstr(|name| { + from_glib(ffi::gst_structure_fixate_field_nearest_double( + &mut self.0, + name.as_ptr(), + target, + )) + }) } } #[doc(alias = "gst_structure_fixate_field_nearest_fraction")] - pub fn fixate_field_nearest_fraction>( + pub fn fixate_field_nearest_fraction( &mut self, - name: &str, - target: T, + name: impl IntoGStr, + target: impl Into, ) -> bool { skip_assert_initialized!(); let target = target.into(); unsafe { - from_glib(ffi::gst_structure_fixate_field_nearest_fraction( - &mut self.0, - name.to_glib_none().0, - target.numer(), - target.denom(), - )) + name.run_with_gstr(|name| { + from_glib(ffi::gst_structure_fixate_field_nearest_fraction( + &mut self.0, + name.as_ptr(), + target.numer(), + target.denom(), + )) + }) } } #[doc(alias = "gst_structure_fixate_field_nearest_int")] - pub fn fixate_field_nearest_int(&mut self, name: &str, target: i32) -> bool { + pub fn fixate_field_nearest_int(&mut self, name: impl IntoGStr, target: i32) -> bool { unsafe { - from_glib(ffi::gst_structure_fixate_field_nearest_int( - &mut self.0, - name.to_glib_none().0, - target, - )) + name.run_with_gstr(|name| { + from_glib(ffi::gst_structure_fixate_field_nearest_int( + &mut self.0, + name.as_ptr(), + target, + )) + }) } } @@ -941,7 +956,7 @@ impl<'a> FieldIterator<'a> { } impl<'a> Iterator for FieldIterator<'a> { - type Item = &'static str; + type Item = &'static glib::GStr; fn next(&mut self) -> Option { if self.idx >= self.n_fields { @@ -991,7 +1006,7 @@ impl<'a> Iter<'a> { } impl<'a> Iterator for Iter<'a> { - type Item = (&'static str, &'a SendValue); + type Item = (&'static glib::GStr, &'a SendValue); fn next(&mut self) -> Option { let f = self.iter.next()?; @@ -1041,7 +1056,7 @@ impl<'a> std::iter::FusedIterator for Iter<'a> {} impl<'a> IntoIterator for &'a StructureRef { type IntoIter = Iter<'a>; - type Item = (&'static str, &'a SendValue); + type Item = (&'static glib::GStr, &'a SendValue); fn into_iter(self) -> Self::IntoIter { self.iter() @@ -1054,12 +1069,24 @@ impl<'a> std::iter::Extend<(&'a str, SendValue)> for StructureRef { } } +impl<'a> std::iter::Extend<(&'a glib::GStr, SendValue)> for StructureRef { + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(|(f, v)| self.set_value(f, v)); + } +} + impl std::iter::Extend<(String, SendValue)> for StructureRef { fn extend>(&mut self, iter: T) { iter.into_iter().for_each(|(f, v)| self.set_value(&f, v)); } } +impl std::iter::Extend<(glib::GString, SendValue)> for StructureRef { + fn extend>(&mut self, iter: T) { + iter.into_iter().for_each(|(f, v)| self.set_value(&f, v)); + } +} + impl std::iter::Extend<(glib::Quark, SendValue)> for StructureRef { fn extend>(&mut self, iter: T) { iter.into_iter() @@ -1074,14 +1101,14 @@ pub struct Builder { } impl Builder { - fn new(name: &str) -> Self { + fn new(name: impl IntoGStr) -> Self { skip_assert_initialized!(); Builder { s: Structure::new_empty(name), } } - pub fn field(mut self, name: &str, value: impl Into + Send) -> Self { + pub fn field(mut self, name: impl IntoGStr, value: impl Into + Send) -> Self { self.s.set(name, value); self } @@ -1097,6 +1124,7 @@ mod tests { use super::*; #[test] + #[allow(deprecated)] fn new_set_get() { use glib::{value, Type}; diff --git a/gstreamer/src/structure_serde.rs b/gstreamer/src/structure_serde.rs index 500c8bcc3..22deb50bd 100644 --- a/gstreamer/src/structure_serde.rs +++ b/gstreamer/src/structure_serde.rs @@ -50,7 +50,7 @@ impl<'a> Serialize for StructureForIter<'a> { impl Serialize for StructureRef { fn serialize(&self, serializer: S) -> Result { let mut tup = serializer.serialize_tuple(2)?; - tup.serialize_element(self.name())?; + tup.serialize_element(self.name().as_str())?; tup.serialize_element(&StructureForIter(self))?; tup.end() } @@ -141,7 +141,7 @@ impl<'de> Visitor<'de> for StructureVisitor { let name = seq .next_element::()? .ok_or_else(|| de::Error::custom("Expected a name for the `Structure`"))?; - let mut structure = Structure::new_empty(&name); + let mut structure = Structure::new_empty(name); seq.next_element_seed(FieldsDe(structure.as_mut()))? .ok_or_else(|| de::Error::custom("Expected a sequence of `Field`s"))?; diff --git a/gstreamer/src/subclass/element.rs b/gstreamer/src/subclass/element.rs index 0e4b213f2..5c9864acb 100644 --- a/gstreamer/src/subclass/element.rs +++ b/gstreamer/src/subclass/element.rs @@ -720,7 +720,7 @@ mod tests { assert_eq!(element.name(), "test"); assert_eq!( - element.metadata(&crate::ELEMENT_METADATA_LONGNAME), + element.metadata(crate::ELEMENT_METADATA_LONGNAME), Some("Test Element") ); diff --git a/gstreamer/src/tag_setter.rs b/gstreamer/src/tag_setter.rs index 1dc700194..8e31d5f37 100644 --- a/gstreamer/src/tag_setter.rs +++ b/gstreamer/src/tag_setter.rs @@ -17,7 +17,7 @@ impl> TagSetterExtManual for O { ffi::gst_tag_setter_add_tag_value( self.as_ref().to_glib_none().0, mode.into_glib(), - T::tag_name().to_glib_none().0, + T::TAG_NAME.as_ptr(), v.to_glib_none().0, ); } diff --git a/gstreamer/src/tags.rs b/gstreamer/src/tags.rs index 78c8ac408..541a7be53 100644 --- a/gstreamer/src/tags.rs +++ b/gstreamer/src/tags.rs @@ -1,19 +1,18 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{ffi::CStr, fmt, marker::PhantomData, mem}; +use std::{fmt, marker::PhantomData, mem}; use glib::{ translate::*, value::{FromValue, SendValue, ToSendValue, Value}, - StaticType, + IntoGStr, StaticType, }; -use once_cell::sync::Lazy; use crate::{Sample, TagError, TagMergeMode, TagScope}; pub trait Tag<'a> { type TagType: StaticType + FromValue<'a> + ToSendValue + Send + Sync; - fn tag_name<'b>() -> &'b str; + const TAG_NAME: &'static glib::GStr; } macro_rules! impl_tag( @@ -21,14 +20,8 @@ macro_rules! impl_tag( pub enum $name {} impl<'a> Tag<'a> for $name { type TagType = $t; - - fn tag_name<'b>() -> &'b str { - *$rust_tag - } + const TAG_NAME: &'static glib::GStr = unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::$gst_tag) }; } - - pub(crate) static $rust_tag: Lazy<&'static str> = Lazy::new(|| - unsafe { CStr::from_ptr(ffi::$gst_tag).to_str().unwrap() }); }; ); @@ -363,15 +356,15 @@ impl TagValue { impl TagListRef { #[doc(alias = "gst_tag_list_add")] pub fn add<'a, T: Tag<'a>>(&mut self, value: &T::TagType, mode: TagMergeMode) { - // result can be safely ignored here as `value`'s type is tied to `T::tag_name()` + // result can be safely ignored here as `value`'s type is tied to `T::TAG_NAME` let v = ::to_send_value(value); - let _res = self.add_value(T::tag_name(), &v, mode); + let _res = self.add_value(T::TAG_NAME, &v, mode); } #[doc(alias = "gst_tag_list_add")] pub fn add_generic( &mut self, - tag_name: &str, + tag_name: impl IntoGStr, value: impl ToSendValue, mode: TagMergeMode, ) -> Result<(), TagError> { @@ -381,50 +374,49 @@ impl TagListRef { #[doc(alias = "gst_tag_list_add_value")] pub fn add_value( &mut self, - tag_name: &str, + tag_name: impl IntoGStr, value: &glib::SendValue, mode: TagMergeMode, ) -> Result<(), TagError> { unsafe { - let tag_name = tag_name.to_glib_none(); + tag_name.run_with_gstr(|tag_name| { + let tag_type: glib::Type = from_glib(ffi::gst_tag_get_type(tag_name.as_ptr())); + if tag_type != value.type_() { + return Err(TagError::TypeMismatch); + } - let tag_type: glib::Type = from_glib(ffi::gst_tag_get_type(tag_name.0)); - if tag_type != value.type_() { - return Err(TagError::TypeMismatch); - } - - ffi::gst_tag_list_add_value( - self.as_mut_ptr(), - mode.into_glib(), - tag_name.0, - value.to_glib_none().0, - ); + ffi::gst_tag_list_add_value( + self.as_mut_ptr(), + mode.into_glib(), + tag_name.as_ptr(), + value.to_glib_none().0, + ); + Ok(()) + }) } - - Ok(()) } #[doc(alias = "gst_tag_list_remove_tag")] pub fn remove<'a, T: Tag<'a>>(&mut self) { - self.remove_generic(T::tag_name()); + self.remove_generic(T::TAG_NAME); } #[doc(alias = "gst_tag_list_remove_tag")] - pub fn remove_generic(&mut self, tag_name: &str) { + pub fn remove_generic(&mut self, tag_name: impl IntoGStr) { unsafe { - let tag_name = tag_name.to_glib_none(); - - ffi::gst_tag_list_remove_tag(self.as_mut_ptr(), tag_name.0); + tag_name.run_with_gstr(|tag_name| { + ffi::gst_tag_list_remove_tag(self.as_mut_ptr(), tag_name.as_ptr()); + }) } } #[doc(alias = "gst_tag_list_get")] pub fn get<'a, T: Tag<'a>>(&self) -> Option> { - self.generic(T::tag_name()).map(|value| { + self.generic(T::TAG_NAME).map(|value| { if !value.is::() { panic!( "TagListRef::get type mismatch for tag {}: {}", - T::tag_name(), + T::TAG_NAME, value.type_() ); } @@ -434,21 +426,23 @@ impl TagListRef { #[doc(alias = "gst_tag_list_get")] #[doc(alias = "get_generic")] - pub fn generic(&self, tag_name: &str) -> Option { + pub fn generic(&self, tag_name: impl IntoGStr) -> Option { unsafe { let mut value: mem::MaybeUninit = mem::MaybeUninit::zeroed(); - let found: bool = from_glib(ffi::gst_tag_list_copy_value( - (*value.as_mut_ptr()).to_glib_none_mut().0, - self.as_ptr(), - tag_name.to_glib_none().0, - )); + let found: bool = tag_name.run_with_gstr(|tag_name| { + from_glib(ffi::gst_tag_list_copy_value( + (*value.as_mut_ptr()).to_glib_none_mut().0, + self.as_ptr(), + tag_name.as_ptr(), + )) + }); if !found { - return None; + None + } else { + Some(value.assume_init()) } - - Some(value.assume_init()) } } @@ -458,7 +452,7 @@ impl TagListRef { } #[doc(alias = "gst_tag_list_nth_tag_name")] - pub fn nth_tag_name(&self, idx: u32) -> Option<&str> { + pub fn nth_tag_name(&self, idx: u32) -> Option<&glib::GStr> { if idx >= self.n_tags() { return None; } @@ -466,18 +460,18 @@ impl TagListRef { unsafe { let name = ffi::gst_tag_list_nth_tag_name(self.as_ptr(), idx); debug_assert!(!name.is_null()); - Some(CStr::from_ptr(name).to_str().unwrap()) + Some(glib::GStr::from_ptr(name)) } } #[doc(alias = "get_index")] #[doc(alias = "gst_tag_list_get_index")] pub fn index<'a, T: Tag<'a>>(&self, idx: u32) -> Option<&'a TagValue> { - self.index_generic(T::tag_name(), idx).map(|value| { + self.index_generic(T::TAG_NAME, idx).map(|value| { if !value.is::() { panic!( "TagListRef::get_index type mismatch for tag {}: {}", - T::tag_name(), + T::TAG_NAME, value.type_() ); } @@ -487,36 +481,42 @@ impl TagListRef { #[doc(alias = "get_index_generic")] #[doc(alias = "gst_tag_list_get_index")] - pub fn index_generic<'a>(&'a self, tag_name: &str, idx: u32) -> Option<&'a SendValue> { + pub fn index_generic(&self, tag_name: impl IntoGStr, idx: u32) -> Option<&SendValue> { unsafe { - let value = - ffi::gst_tag_list_get_value_index(self.as_ptr(), tag_name.to_glib_none().0, idx); + let value = tag_name.run_with_gstr(|tag_name| { + ffi::gst_tag_list_get_value_index(self.as_ptr(), tag_name.as_ptr(), idx) + }); if value.is_null() { - return None; + None + } else { + Some(&*(value as *const SendValue)) } - - Some(&*(value as *const SendValue)) } } #[doc(alias = "get_size")] #[doc(alias = "gst_tag_list_get_tag_size")] pub fn size<'a, T: Tag<'a>>(&self) -> u32 { - self.size_by_name(T::tag_name()) + self.size_by_name(T::TAG_NAME) } #[doc(alias = "get_size_by_name")] #[doc(alias = "gst_tag_list_get_tag_size")] - pub fn size_by_name(&self, tag_name: &str) -> u32 { - unsafe { ffi::gst_tag_list_get_tag_size(self.as_ptr(), tag_name.to_glib_none().0) } + pub fn size_by_name(&self, tag_name: impl IntoGStr) -> u32 { + unsafe { + tag_name.run_with_gstr(|tag_name| { + ffi::gst_tag_list_get_tag_size(self.as_ptr(), tag_name.as_ptr()) + }) + } } pub fn iter_tag<'a, T: Tag<'a>>(&'a self) -> TagIter<'a, T> { TagIter::new(self) } - pub fn iter_tag_generic<'a>(&'a self, tag_name: &'a str) -> GenericTagIter<'a> { + pub fn iter_tag_generic(&self, tag_name: impl IntoGStr) -> GenericTagIter { + let tag_name = glib::Quark::from_str(tag_name).as_str(); GenericTagIter::new(self, tag_name) } @@ -728,13 +728,13 @@ where #[derive(Debug)] pub struct GenericTagIter<'a> { taglist: &'a TagListRef, - name: &'a str, + name: &'static glib::GStr, idx: usize, size: usize, } impl<'a> GenericTagIter<'a> { - fn new(taglist: &'a TagListRef, name: &'a str) -> GenericTagIter<'a> { + fn new(taglist: &'a TagListRef, name: &'static glib::GStr) -> GenericTagIter<'a> { skip_assert_initialized!(); GenericTagIter { taglist, @@ -850,7 +850,7 @@ impl<'a> GenericIter<'a> { } impl<'a> Iterator for GenericIter<'a> { - type Item = (&'a str, GenericTagIter<'a>); + type Item = (&'a glib::GStr, GenericTagIter<'a>); fn next(&mut self) -> Option { if self.idx >= self.size { @@ -944,7 +944,7 @@ impl<'a> Iter<'a> { } impl<'a> Iterator for Iter<'a> { - type Item = (&'a str, glib::SendValue); + type Item = (&'a glib::GStr, glib::SendValue); fn next(&mut self) -> Option { if self.idx >= self.size { @@ -1019,50 +1019,50 @@ impl<'a> ExactSizeIterator for Iter<'a> {} impl<'a> std::iter::FusedIterator for Iter<'a> {} #[doc(alias = "gst_tag_exists")] -pub fn tag_exists(name: &str) -> bool { +pub fn tag_exists(name: impl IntoGStr) -> bool { skip_assert_initialized!(); - unsafe { from_glib(ffi::gst_tag_exists(name.to_glib_none().0)) } + unsafe { name.run_with_gstr(|name| from_glib(ffi::gst_tag_exists(name.as_ptr()))) } } #[doc(alias = "gst_tag_get_type")] -pub fn tag_get_type(name: &str) -> glib::Type { +pub fn tag_get_type(name: impl IntoGStr) -> glib::Type { skip_assert_initialized!(); - unsafe { from_glib(ffi::gst_tag_get_type(name.to_glib_none().0)) } + unsafe { name.run_with_gstr(|name| from_glib(ffi::gst_tag_get_type(name.as_ptr()))) } } #[doc(alias = "gst_tag_get_nick")] -pub fn tag_get_nick(name: &str) -> &str { +pub fn tag_get_nick<'b>(name: impl IntoGStr) -> &'b glib::GStr { skip_assert_initialized!(); unsafe { - let ptr = ffi::gst_tag_get_nick(name.to_glib_none().0); - CStr::from_ptr(ptr).to_str().unwrap() + let ptr = name.run_with_gstr(|name| ffi::gst_tag_get_nick(name.as_ptr())); + glib::GStr::from_ptr(ptr) } } #[doc(alias = "gst_tag_get_description")] -pub fn tag_get_description<'b>(name: &str) -> Option<&'b str> { +pub fn tag_get_description<'b>(name: impl IntoGStr) -> Option<&'b glib::GStr> { skip_assert_initialized!(); unsafe { - let ptr = ffi::gst_tag_get_description(name.to_glib_none().0); + let ptr = name.run_with_gstr(|name| ffi::gst_tag_get_description(name.as_ptr())); if ptr.is_null() { None } else { - Some(CStr::from_ptr(ptr).to_str().unwrap()) + Some(glib::GStr::from_ptr(ptr)) } } } #[doc(alias = "gst_tag_get_flag")] -pub fn tag_get_flag(name: &str) -> crate::TagFlag { +pub fn tag_get_flag(name: impl IntoGStr) -> crate::TagFlag { skip_assert_initialized!(); - unsafe { from_glib(ffi::gst_tag_get_flag(name.to_glib_none().0)) } + unsafe { name.run_with_gstr(|name| from_glib(ffi::gst_tag_get_flag(name.as_ptr()))) } } pub trait CustomTag<'a>: Tag<'a> { const FLAG: crate::TagFlag; - const NICK: &'static str; - const DESCRIPTION: &'static str; + const NICK: &'static glib::GStr; + const DESCRIPTION: &'static glib::GStr; fn merge_func(src: &Value) -> Value { skip_assert_initialized!(); @@ -1072,7 +1072,7 @@ pub trait CustomTag<'a>: Tag<'a> { #[doc(alias = "gst_tag_register")] pub fn register CustomTag<'a>>() { - assert!(!tag_exists(T::tag_name())); + assert!(!tag_exists(T::TAG_NAME)); unsafe extern "C" fn merge_func_trampoline CustomTag<'a>>( dest: *mut glib::gobject_ffi::GValue, @@ -1083,11 +1083,11 @@ pub fn register CustomTag<'a>>() { unsafe { ffi::gst_tag_register( - T::tag_name().to_glib_none().0, + T::TAG_NAME.as_ptr(), T::FLAG.into_glib(), T::TagType::static_type().into_glib(), - T::NICK.to_glib_none().0, - T::DESCRIPTION.to_glib_none().0, + T::NICK.as_ptr(), + T::DESCRIPTION.as_ptr(), Some(merge_func_trampoline::), ) } @@ -1186,21 +1186,25 @@ mod tests { { let tags = tags.get_mut().unwrap(); assert!(tags - .add_generic(&TAG_TITLE, "some title", TagMergeMode::Append) + .add_generic(Title::TAG_NAME, "some title", TagMergeMode::Append) .is_ok()); assert!(tags - .add_generic(&TAG_TITLE, "second title", TagMergeMode::Append) + .add_generic(Title::TAG_NAME, "second title", TagMergeMode::Append) .is_ok()); assert!(tags - .add_generic(&TAG_DURATION, ClockTime::SECOND * 120, TagMergeMode::Append) + .add_generic( + Duration::TAG_NAME, + ClockTime::SECOND * 120, + TagMergeMode::Append + ) .is_ok()); assert!(tags - .add_generic(&TAG_TITLE, "third title", TagMergeMode::Append) + .add_generic(Title::TAG_NAME, "third title", TagMergeMode::Append) .is_ok()); assert_eq!( tags.add_generic( - &TAG_IMAGE, + Image::TAG_NAME, "`&[str] instead of `Sample`", TagMergeMode::Append ), @@ -1209,35 +1213,35 @@ mod tests { } assert_eq!( - tags.index_generic(&TAG_TITLE, 0).unwrap().get(), + tags.index_generic(Title::TAG_NAME, 0).unwrap().get(), Ok(Some("some title")) ); assert_eq!( - tags.index_generic(&TAG_TITLE, 1).unwrap().get(), + tags.index_generic(Title::TAG_NAME, 1).unwrap().get(), Ok(Some("second title")) ); assert_eq!( - tags.index_generic(&TAG_DURATION, 0).unwrap().get(), + tags.index_generic(Duration::TAG_NAME, 0).unwrap().get(), Ok(Some(ClockTime::SECOND * 120)) ); assert_eq!( - tags.index_generic(&TAG_TITLE, 2).unwrap().get(), + tags.index_generic(Title::TAG_NAME, 2).unwrap().get(), Ok(Some("third title")) ); assert_eq!( - tags.generic(&TAG_TITLE).unwrap().get(), + tags.generic(Title::TAG_NAME).unwrap().get(), Ok(Some("some title, second title, third title")) ); assert_eq!(tags.n_tags(), 2); - assert_eq!(tags.nth_tag_name(0), Some(*TAG_TITLE)); - assert_eq!(tags.size_by_name(&TAG_TITLE), 3); - assert_eq!(tags.nth_tag_name(1), Some(*TAG_DURATION)); - assert_eq!(tags.size_by_name(&TAG_DURATION), 1); + assert_eq!(tags.nth_tag_name(0), Some(Title::TAG_NAME)); + assert_eq!(tags.size_by_name(Title::TAG_NAME), 3); + assert_eq!(tags.nth_tag_name(1), Some(Duration::TAG_NAME)); + assert_eq!(tags.size_by_name(Duration::TAG_NAME), 1); // GenericTagIter - let mut title_iter = tags.iter_tag_generic(&TAG_TITLE); + let mut title_iter = tags.iter_tag_generic(Title::TAG_NAME); assert_eq!(title_iter.size_hint(), (3, Some(3))); let first_title = title_iter.next().unwrap(); assert_eq!(first_title.get(), Ok(Some("some title"))); @@ -1252,7 +1256,7 @@ mod tests { assert_eq!(tag_list_iter.size_hint(), (2, Some(2))); let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); - assert_eq!(tag_name, *TAG_TITLE); + assert_eq!(tag_name, Title::TAG_NAME); let first_title = tag_iter.next().unwrap(); assert_eq!(first_title.get(), Ok(Some("some title"))); let second_title = tag_iter.next().unwrap(); @@ -1262,7 +1266,7 @@ mod tests { assert!(tag_iter.next().is_none()); let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); - assert_eq!(tag_name, *TAG_DURATION); + assert_eq!(tag_name, Duration::TAG_NAME); let first_duration = tag_iter.next().unwrap(); assert_eq!(first_duration.get(), Ok(Some(ClockTime::SECOND * 120))); assert!(tag_iter.next().is_none()); @@ -1272,14 +1276,14 @@ mod tests { assert_eq!(tag_list_iter.size_hint(), (2, Some(2))); let (tag_name, tag_value) = tag_list_iter.next().unwrap(); - assert_eq!(tag_name, *TAG_TITLE); + assert_eq!(tag_name, Title::TAG_NAME); assert_eq!( tag_value.get(), Ok(Some("some title, second title, third title")) ); let (tag_name, tag_value) = tag_list_iter.next().unwrap(); - assert_eq!(tag_name, *TAG_DURATION); + assert_eq!(tag_name, Duration::TAG_NAME); assert_eq!(tag_value.get(), Ok(Some(ClockTime::SECOND * 120))); assert!(tag_iter.next().is_none()); } @@ -1292,15 +1296,14 @@ mod tests { impl<'a> Tag<'a> for MyCustomTag { type TagType = &'a str; - fn tag_name<'b>() -> &'b str { - "my-custom-tag" - } + const TAG_NAME: &'static glib::GStr = glib::gstr!("my-custom-tag"); } impl<'a> CustomTag<'a> for MyCustomTag { const FLAG: crate::TagFlag = crate::TagFlag::Meta; - const NICK: &'static str = "my custom tag"; - const DESCRIPTION: &'static str = "My own custom tag type for testing"; + const NICK: &'static glib::GStr = glib::gstr!("my custom tag"); + const DESCRIPTION: &'static glib::GStr = + glib::gstr!("My own custom tag type for testing"); fn merge_func(src: &Value) -> Value { skip_assert_initialized!(); @@ -1310,17 +1313,17 @@ mod tests { register::(); - assert!(tag_exists(MyCustomTag::tag_name())); + assert!(tag_exists(MyCustomTag::TAG_NAME)); assert_eq!( - tag_get_type(MyCustomTag::tag_name()), + tag_get_type(MyCustomTag::TAG_NAME), ::TagType::static_type() ); - assert_eq!(tag_get_nick(MyCustomTag::tag_name()), MyCustomTag::NICK); + assert_eq!(tag_get_nick(MyCustomTag::TAG_NAME), MyCustomTag::NICK); assert_eq!( - tag_get_description(MyCustomTag::tag_name()), + tag_get_description(MyCustomTag::TAG_NAME), Some(MyCustomTag::DESCRIPTION) ); - assert_eq!(tag_get_flag(MyCustomTag::tag_name()), MyCustomTag::FLAG); + assert_eq!(tag_get_flag(MyCustomTag::TAG_NAME), MyCustomTag::FLAG); let mut tags = TagList::new(); { diff --git a/tutorials/src/bin/basic-tutorial-5.rs b/tutorials/src/bin/basic-tutorial-5.rs index c2b95b78b..008829bbe 100644 --- a/tutorials/src/bin/basic-tutorial-5.rs +++ b/tutorials/src/bin/basic-tutorial-5.rs @@ -234,7 +234,7 @@ mod tutorial5 { None => return, }; - if application.structure().map(|s| s.name()) == Some("tags-changed") { + if application.structure().map(|s| s.name().as_str()) == Some("tags-changed") { let textbuf = streams_list .buffer() .expect("Couldn't get buffer from text_view");