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: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1190>
This commit is contained in:
Sebastian Dröge 2023-01-15 20:38:13 +02:00
parent ea136515cf
commit 003554876c
32 changed files with 602 additions and 541 deletions

View file

@ -46,7 +46,7 @@ fn main_loop() -> Result<(), Error> {
// server to require from clients. // server to require from clients.
let auth = gst_rtsp_server::RTSPAuth::new(); let auth = gst_rtsp_server::RTSPAuth::new();
let token = gst_rtsp_server::RTSPToken::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", &"user",
)]); )]);
let basic = gst_rtsp_server::RTSPAuth::make_basic("user", "password"); let basic = gst_rtsp_server::RTSPAuth::make_basic("user", "password");

View file

@ -86,7 +86,7 @@ fn example_main() -> Result<(), Error> {
.expect("typefinder \"have-type\" signal values[2]"); .expect("typefinder \"have-type\" signal values[2]");
let format_name = caps.structure(0).expect("Failed to get format name").name(); 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") "video/x-matroska" | "video/webm" => gst::ElementFactory::make("matroskademux")
.build() .build()
.expect("matroskademux missing"), .expect("matroskademux missing"),

View file

@ -541,7 +541,7 @@ impl App {
let src = gst::ElementFactory::make("videotestsrc").build()?; let src = gst::ElementFactory::make("videotestsrc").build()?;
let caps = gst_video::VideoCapsBuilder::new() 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) .format(gst_video::VideoFormat::Rgba)
.field("texture-target", "2D") .field("texture-target", "2D")
.build(); .build();

View file

@ -4,4 +4,4 @@ use gst::CapsFeatures;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
pub static CAPS_FEATURES_MEMORY_DMABUF: Lazy<CapsFeatures> = pub static CAPS_FEATURES_MEMORY_DMABUF: Lazy<CapsFeatures> =
Lazy::new(|| CapsFeatures::new(&[*crate::CAPS_FEATURE_MEMORY_DMABUF])); Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_DMABUF]));

View file

@ -79,49 +79,52 @@ impl AudioConverterConfig {
} }
pub fn set_dither_method(&mut self, v: crate::AudioDitherMethod) { 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")] #[doc(alias = "get_dither_method")]
pub fn dither_method(&self) -> crate::AudioDitherMethod { pub fn dither_method(&self) -> crate::AudioDitherMethod {
self.0 self.0
.get_optional("GstAudioConverter.dither-method") .get_optional(glib::gstr!("GstAudioConverter.dither-method"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::AudioDitherMethod::None) .unwrap_or(crate::AudioDitherMethod::None)
} }
pub fn set_noise_shaping_method(&mut self, v: crate::AudioNoiseShapingMethod) { 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")] #[doc(alias = "get_noise_shaping_method")]
pub fn noise_shaping_method(&self) -> crate::AudioNoiseShapingMethod { pub fn noise_shaping_method(&self) -> crate::AudioNoiseShapingMethod {
self.0 self.0
.get_optional("GstAudioConverter.noise-shaping-method") .get_optional(glib::gstr!("GstAudioConverter.noise-shaping-method"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::AudioNoiseShapingMethod::None) .unwrap_or(crate::AudioNoiseShapingMethod::None)
} }
pub fn set_quantization(&mut self, v: u32) { 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")] #[doc(alias = "get_quantization")]
pub fn quantization(&self) -> u32 { pub fn quantization(&self) -> u32 {
self.0 self.0
.get_optional("GstAudioConverter.quantization") .get_optional(glib::gstr!("GstAudioConverter.quantization"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(1) .unwrap_or(1)
} }
pub fn set_resampler_method(&mut self, v: crate::AudioResamplerMethod) { 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")] #[doc(alias = "get_resampler_method")]
pub fn resampler_method(&self) -> crate::AudioResamplerMethod { pub fn resampler_method(&self) -> crate::AudioResamplerMethod {
self.0 self.0
.get_optional("GstAudioConverter.resampler-method") .get_optional(glib::gstr!("GstAudioConverter.resampler-method"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::AudioResamplerMethod::BlackmanNuttall) .unwrap_or(crate::AudioResamplerMethod::BlackmanNuttall)
} }
@ -133,13 +136,14 @@ impl AudioConverterConfig {
assert_eq!(val.len(), length); assert_eq!(val.len(), length);
gst::Array::from_values(val.iter().map(|val| val.to_send_value())).to_send_value() 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")] #[doc(alias = "get_mix_matrix")]
pub fn mix_matrix(&self) -> Vec<Vec<f32>> { pub fn mix_matrix(&self) -> Vec<Vec<f32>> {
self.0 self.0
.get_optional::<gst::Array>("GstAudioConverter.mix-matrix") .get_optional::<gst::Array>(glib::gstr!("GstAudioConverter.mix-matrix"))
.expect("Wrong type") .expect("Wrong type")
.map(|array| { .map(|array| {
array array
@ -162,7 +166,8 @@ impl AudioConverterConfig {
#[cfg(any(feature = "v1_22", feature = "dox"))] #[cfg(any(feature = "v1_22", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))]
pub fn set_dither_threshold(&mut self, v: u32) { 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"))] #[cfg(any(feature = "v1_22", feature = "dox"))]
@ -170,7 +175,7 @@ impl AudioConverterConfig {
#[doc(alias = "get_dither_threshold")] #[doc(alias = "get_dither_threshold")]
pub fn dither_threshold(&self) -> u32 { pub fn dither_threshold(&self) -> u32 {
self.0 self.0
.get_optional("GstAudioConverter.dither-threshold") .get_optional(glib::gstr!("GstAudioConverter.dither-threshold"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(20) .unwrap_or(20)
} }

View file

@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file. // 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 glib::translate::{from_glib, IntoGlib};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -112,18 +112,16 @@ impl crate::AudioFormat {
} }
#[doc(alias = "gst_audio_format_to_string")] #[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 { if self == Self::Unknown {
return "UNKNOWN"; return glib::gstr!("UNKNOWN");
} }
unsafe { unsafe {
CStr::from_ptr( glib::GStr::from_ptr(
ffi::gst_audio_format_to_string(self.into_glib()) ffi::gst_audio_format_to_string(self.into_glib())
.as_ref() .as_ref()
.expect("gst_audio_format_to_string returned NULL"), .expect("gst_audio_format_to_string returned NULL"),
) )
.to_str()
.expect("gst_audio_format_to_string returned an invalid string")
} }
} }

View file

@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file. // 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::{ use glib::{
translate::{from_glib, from_glib_none, FromGlib, IntoGlib, ToGlibPtr, ToGlibPtrMut}, translate::{from_glib, from_glib_none, FromGlib, IntoGlib, ToGlibPtr, ToGlibPtrMut},
@ -64,13 +64,13 @@ impl AudioFormatInfo {
} }
#[inline] #[inline]
pub fn name<'a>(&self) -> &'a str { pub fn name<'a>(&self) -> &'a glib::GStr {
unsafe { CStr::from_ptr(self.0.name).to_str().unwrap() } unsafe { glib::GStr::from_ptr(self.0.name) }
} }
#[inline] #[inline]
pub fn description<'a>(&self) -> &'a str { pub fn description<'a>(&self) -> &'a glib::GStr {
unsafe { CStr::from_ptr(self.0.description).to_str().unwrap() } unsafe { glib::GStr::from_ptr(self.0.description) }
} }
#[inline] #[inline]

View file

@ -2,6 +2,8 @@ use std::ops::{Bound::*, RangeBounds};
use gst::Caps; use gst::Caps;
use glib::IntoGStr;
use crate::{AudioFormat, AudioLayout}; use crate::{AudioFormat, AudioLayout};
pub struct AudioCapsBuilder<T> { pub struct AudioCapsBuilder<T> {
@ -10,7 +12,7 @@ pub struct AudioCapsBuilder<T> {
impl AudioCapsBuilder<gst::caps::NoFeature> { impl AudioCapsBuilder<gst::caps::NoFeature> {
pub fn new() -> Self { pub fn new() -> Self {
let builder = Caps::builder("audio/x-raw"); let builder = Caps::builder(glib::gstr!("audio/x-raw"));
let builder = AudioCapsBuilder { builder }; let builder = AudioCapsBuilder { builder };
builder builder
.rate_range(..) .rate_range(..)
@ -29,7 +31,10 @@ impl AudioCapsBuilder<gst::caps::NoFeature> {
} }
} }
pub fn features(self, features: &[&str]) -> AudioCapsBuilder<gst::caps::HasFeatures> { pub fn features(
self,
features: impl IntoIterator<Item = impl IntoGStr>,
) -> AudioCapsBuilder<gst::caps::HasFeatures> {
AudioCapsBuilder { AudioCapsBuilder {
builder: self.builder.features(features), builder: self.builder.features(features),
} }
@ -45,14 +50,14 @@ impl Default for AudioCapsBuilder<gst::caps::NoFeature> {
impl<T> AudioCapsBuilder<T> { impl<T> AudioCapsBuilder<T> {
pub fn format(self, format: AudioFormat) -> Self { pub fn format(self, format: AudioFormat) -> Self {
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<Item = AudioFormat>) -> Self { pub fn format_list(self, formats: impl IntoIterator<Item = AudioFormat>) -> Self {
Self { Self {
builder: self.builder.field( builder: self.builder.field(
"format", glib::gstr!("format"),
gst::List::new(formats.into_iter().map(|f| f.to_str())), gst::List::new(formats.into_iter().map(|f| f.to_str())),
), ),
} }
@ -60,7 +65,7 @@ impl<T> AudioCapsBuilder<T> {
pub fn rate(self, rate: i32) -> Self { pub fn rate(self, rate: i32) -> Self {
Self { Self {
builder: self.builder.field("rate", rate), builder: self.builder.field(glib::gstr!("rate"), rate),
} }
} }
@ -68,19 +73,21 @@ impl<T> AudioCapsBuilder<T> {
let (start, end) = range_bounds_i32_start_end(rates); let (start, end) = range_bounds_i32_start_end(rates);
let gst_rates = gst::IntRange::<i32>::new(start, end); let gst_rates = gst::IntRange::<i32>::new(start, end);
Self { 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<Item = i32>) -> Self { pub fn rate_list(self, rates: impl IntoIterator<Item = i32>) -> Self {
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 { pub fn channels(self, channels: i32) -> Self {
Self { Self {
builder: self.builder.field("channels", channels), builder: self.builder.field(glib::gstr!("channels"), channels),
} }
} }
@ -88,26 +95,30 @@ impl<T> AudioCapsBuilder<T> {
let (start, end) = range_bounds_i32_start_end(channels); let (start, end) = range_bounds_i32_start_end(channels);
let gst_channels: gst::IntRange<i32> = gst::IntRange::new(start, end); let gst_channels: gst::IntRange<i32> = gst::IntRange::new(start, end);
Self { 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<Item = i32>) -> Self { pub fn channels_list(self, channels: impl IntoIterator<Item = i32>) -> Self {
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 { pub fn layout(self, layout: AudioLayout) -> Self {
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<Item = AudioLayout>) -> Self { pub fn layout_list(self, layouts: impl IntoIterator<Item = AudioLayout>) -> Self {
Self { Self {
builder: self.builder.field( builder: self.builder.field(
"layout", glib::gstr!("layout"),
gst::List::new(layouts.into_iter().map(layout_str)), gst::List::new(layouts.into_iter().map(layout_str)),
), ),
} }
@ -122,11 +133,11 @@ impl<T> AudioCapsBuilder<T> {
} }
pub fn fallback_channel_mask(self) -> Self { pub fn fallback_channel_mask(self) -> Self {
let channels = self.builder.structure().get::<i32>("channels"); let channels = self.builder.structure().get::<i32>(glib::gstr!("channels"));
match channels { match channels {
Ok(channels) => Self { Ok(channels) => Self {
builder: self.builder.field( builder: self.builder.field(
"channel-mask", glib::gstr!("channel-mask"),
gst::Bitmask::new(crate::AudioChannelPosition::fallback_mask(channels as u32)), 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, i32) {
(start, end) (start, end)
} }
fn layout_str(layout: AudioLayout) -> &'static str { fn layout_str(layout: AudioLayout) -> &'static glib::GStr {
skip_assert_initialized!(); skip_assert_initialized!();
match layout { match layout {
crate::AudioLayout::Interleaved => "interleaved", crate::AudioLayout::Interleaved => glib::gstr!("interleaved"),
crate::AudioLayout::NonInterleaved => "non-interleaved", crate::AudioLayout::NonInterleaved => glib::gstr!("non-interleaved"),
crate::AudioLayout::__Unknown(_) => "unknown", crate::AudioLayout::__Unknown(_) => glib::gstr!("unknown"),
} }
} }

View file

@ -4,4 +4,4 @@ use gst::CapsFeatures;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
pub static CAPS_FEATURES_MEMORY_GL_MEMORY: Lazy<CapsFeatures> = pub static CAPS_FEATURES_MEMORY_GL_MEMORY: Lazy<CapsFeatures> =
Lazy::new(|| CapsFeatures::new(&[*crate::CAPS_FEATURE_MEMORY_GL_MEMORY])); Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_GL_MEMORY]));

View file

@ -1,4 +1,2 @@
use libc::c_char;
// See https://gitlab.gnome.org/GNOME/gobject-introspection/issues/238 // 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";

View file

@ -17,12 +17,12 @@ pub fn pb_utils_add_codec_description_to_tag_list_for_tag<'a, T: CodecTag<'a>>(
caps: &gst::CapsRef, caps: &gst::CapsRef,
) -> Result<(), glib::BoolError> { ) -> Result<(), glib::BoolError> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
let codec_tag = T::tag_name(); let codec_tag = T::TAG_NAME;
unsafe { unsafe {
glib::result_from_gboolean!( glib::result_from_gboolean!(
ffi::gst_pb_utils_add_codec_description_to_tag_list( ffi::gst_pb_utils_add_codec_description_to_tag_list(
taglist.as_mut_ptr(), taglist.as_mut_ptr(),
codec_tag.to_glib_none().0, codec_tag.as_ptr(),
caps.as_ptr(), caps.as_ptr(),
), ),
"Failed to find codec description", "Failed to find codec description",

View file

@ -53,67 +53,34 @@ mod rtsp_token;
pub mod subclass; pub mod subclass;
use std::ffi::CStr;
use once_cell::sync::Lazy;
pub use crate::{rtsp_context::*, rtsp_thread::*, rtsp_token::*}; pub use crate::{rtsp_context::*, rtsp_thread::*, rtsp_token::*};
pub static RTSP_ADDRESS_POOL_ANY_IPV4: Lazy<&'static str> = Lazy::new(|| unsafe { pub static RTSP_ADDRESS_POOL_ANY_IPV4: &glib::GStr =
CStr::from_ptr(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV4) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV4) };
.to_str() pub static RTSP_ADDRESS_POOL_ANY_IPV6: &glib::GStr =
.unwrap() unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV6) };
}); pub static RTSP_AUTH_CHECK_CONNECT: &glib::GStr =
pub static RTSP_ADDRESS_POOL_ANY_IPV6: Lazy<&'static str> = Lazy::new(|| unsafe { unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_CONNECT) };
CStr::from_ptr(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV6) pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS: &glib::GStr = unsafe {
.to_str() glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS)
.unwrap() };
}); pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT: &glib::GStr = unsafe {
pub static RTSP_AUTH_CHECK_CONNECT: Lazy<&'static str> = Lazy::new(|| unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT)
CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_CONNECT) };
.to_str() pub static RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS: &glib::GStr = unsafe {
.unwrap() glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS)
}); };
pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS: Lazy<&'static str> = Lazy::new(|| unsafe { pub static RTSP_AUTH_CHECK_URL: &glib::GStr =
CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_AUTH_CHECK_URL) };
.to_str() pub static RTSP_PERM_MEDIA_FACTORY_ACCESS: &glib::GStr =
.unwrap() unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_PERM_MEDIA_FACTORY_ACCESS) };
}); pub static RTSP_PERM_MEDIA_FACTORY_CONSTRUCT: &glib::GStr =
pub static RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT: Lazy<&'static str> = Lazy::new(|| unsafe { unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT) };
CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT) pub static RTSP_TOKEN_MEDIA_FACTORY_ROLE: &glib::GStr =
.to_str() unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE) };
.unwrap() pub static RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS: &glib::GStr = unsafe {
}); glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS)
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()
});
// Re-export all the traits in a prelude module, so that applications // Re-export all the traits in a prelude module, so that applications
// can always "use gst_rtsp_server::prelude::*" without getting conflicts // can always "use gst_rtsp_server::prelude::*" without getting conflicts

View file

@ -1,5 +1,6 @@
use std::ops::{Bound::*, RangeBounds}; use std::ops::{Bound::*, RangeBounds};
use glib::IntoGStr;
use gst::Caps; use gst::Caps;
use crate::VideoFormat; use crate::VideoFormat;
@ -10,7 +11,7 @@ pub struct VideoCapsBuilder<T> {
impl VideoCapsBuilder<gst::caps::NoFeature> { impl VideoCapsBuilder<gst::caps::NoFeature> {
pub fn new() -> Self { pub fn new() -> Self {
let builder = Caps::builder("video/x-raw"); let builder = Caps::builder(glib::gstr!("video/x-raw"));
let builder = VideoCapsBuilder { builder }; let builder = VideoCapsBuilder { builder };
builder builder
.format_list(VideoFormat::iter_raw()) .format_list(VideoFormat::iter_raw())
@ -25,7 +26,10 @@ impl VideoCapsBuilder<gst::caps::NoFeature> {
} }
} }
pub fn features(self, features: &[&str]) -> VideoCapsBuilder<gst::caps::HasFeatures> { pub fn features(
self,
features: impl IntoIterator<Item = impl IntoGStr>,
) -> VideoCapsBuilder<gst::caps::HasFeatures> {
VideoCapsBuilder { VideoCapsBuilder {
builder: self.builder.features(features), builder: self.builder.features(features),
} }
@ -41,14 +45,14 @@ impl Default for VideoCapsBuilder<gst::caps::NoFeature> {
impl<T> VideoCapsBuilder<T> { impl<T> VideoCapsBuilder<T> {
pub fn format(self, format: VideoFormat) -> Self { pub fn format(self, format: VideoFormat) -> Self {
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<Item = VideoFormat>) -> Self { pub fn format_list(self, formats: impl IntoIterator<Item = VideoFormat>) -> Self {
Self { Self {
builder: self.builder.field( builder: self.builder.field(
"format", glib::gstr!("format"),
gst::List::new(formats.into_iter().map(|f| f.to_str())), gst::List::new(formats.into_iter().map(|f| f.to_str())),
), ),
} }
@ -56,7 +60,7 @@ impl<T> VideoCapsBuilder<T> {
pub fn width(self, width: i32) -> Self { pub fn width(self, width: i32) -> Self {
Self { Self {
builder: self.builder.field("width", width), builder: self.builder.field(glib::gstr!("width"), width),
} }
} }
@ -64,19 +68,21 @@ impl<T> VideoCapsBuilder<T> {
let (start, end) = range_bounds_i32_start_end(widths); let (start, end) = range_bounds_i32_start_end(widths);
let gst_widths: gst::IntRange<i32> = gst::IntRange::new(start, end); let gst_widths: gst::IntRange<i32> = gst::IntRange::new(start, end);
Self { 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<Item = i32>) -> Self { pub fn width_list(self, widths: impl IntoIterator<Item = i32>) -> Self {
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 { pub fn height(self, height: i32) -> Self {
Self { Self {
builder: self.builder.field("height", height), builder: self.builder.field(glib::gstr!("height"), height),
} }
} }
@ -84,19 +90,21 @@ impl<T> VideoCapsBuilder<T> {
let (start, end) = range_bounds_i32_start_end(heights); let (start, end) = range_bounds_i32_start_end(heights);
let gst_heights: gst::IntRange<i32> = gst::IntRange::new(start, end); let gst_heights: gst::IntRange<i32> = gst::IntRange::new(start, end);
Self { 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<Item = i32>) -> Self { pub fn height_list(self, heights: impl IntoIterator<Item = i32>) -> Self {
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 { pub fn framerate(self, framerate: gst::Fraction) -> Self {
Self { Self {
builder: self.builder.field("framerate", framerate), builder: self.builder.field(glib::gstr!("framerate"), framerate),
} }
} }
@ -120,13 +128,15 @@ impl<T> VideoCapsBuilder<T> {
assert!(start <= end); assert!(start <= end);
let framerates: gst::FractionRange = gst::FractionRange::new(start, end); let framerates: gst::FractionRange = gst::FractionRange::new(start, end);
Self { Self {
builder: self.builder.field("framerate", framerates), builder: self.builder.field(glib::gstr!("framerate"), framerates),
} }
} }
pub fn framerate_list(self, framerates: impl IntoIterator<Item = gst::Fraction>) -> Self { pub fn framerate_list(self, framerates: impl IntoIterator<Item = gst::Fraction>) -> Self {
Self { Self {
builder: self.builder.field("framerate", gst::List::new(framerates)), builder: self
.builder
.field(glib::gstr!("framerate"), gst::List::new(framerates)),
} }
} }

View file

@ -1,53 +1,42 @@
// Take a look at the license at the top of the repository in the LICENSE file. // Take a look at the license at the top of the repository in the LICENSE file.
use std::ffi::CStr;
use gst::CapsFeatures; use gst::CapsFeatures;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
#[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg(any(feature = "v1_16", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
pub static CAPS_FEATURE_FORMAT_INTERLACED: Lazy<&'static str> = Lazy::new(|| unsafe { pub static CAPS_FEATURE_FORMAT_INTERLACED: &glib::GStr =
CStr::from_ptr(ffi::GST_CAPS_FEATURE_FORMAT_INTERLACED) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_FORMAT_INTERLACED) };
.to_str()
.unwrap()
});
#[cfg(any(feature = "v1_16", feature = "dox"))] #[cfg(any(feature = "v1_16", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
pub static CAPS_FEATURES_FORMAT_INTERLACED: Lazy<CapsFeatures> = pub static CAPS_FEATURES_FORMAT_INTERLACED: Lazy<CapsFeatures> =
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> = pub static CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: &glib::GStr = unsafe {
Lazy::new(|| unsafe { glib::GStr::from_utf8_with_nul_unchecked(
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META) ffi::GST_CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META,
.to_str() )
.unwrap() };
});
pub static CAPS_FEATURES_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: Lazy<CapsFeatures> = pub static CAPS_FEATURES_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: Lazy<CapsFeatures> =
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> = pub static CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: &glib::GStr = unsafe {
Lazy::new(|| unsafe { glib::GStr::from_utf8_with_nul_unchecked(
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META) ffi::GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META,
.to_str() )
.unwrap() };
});
pub static CAPS_FEATURES_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: Lazy<CapsFeatures> = pub static CAPS_FEATURES_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: Lazy<CapsFeatures> =
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 { pub static CAPS_FEATURE_META_GST_VIDEO_META: &glib::GStr =
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_META) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_META) };
.to_str()
.unwrap()
});
pub static CAPS_FEATURES_META_GST_VIDEO_META: Lazy<CapsFeatures> = pub static CAPS_FEATURES_META_GST_VIDEO_META: Lazy<CapsFeatures> =
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> = pub static CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION: &glib::GStr = unsafe {
Lazy::new(|| unsafe { glib::GStr::from_utf8_with_nul_unchecked(
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION) ffi::GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
.to_str() )
.unwrap() };
});
pub static CAPS_FEATURES_META_GST_VIDEO_OVERLAY_COMPOSITION: Lazy<CapsFeatures> = pub static CAPS_FEATURES_META_GST_VIDEO_OVERLAY_COMPOSITION: Lazy<CapsFeatures> =
Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION])); Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION]));

View file

@ -1,32 +1,24 @@
// Take a look at the license at the top of the repository in the LICENSE file. // 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 glib::translate::*;
use once_cell::sync::Lazy;
pub static BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META: Lazy<&'static str> = pub static BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META: &glib::GStr = unsafe {
Lazy::new(|| unsafe { glib::GStr::from_utf8_with_nul_unchecked(
CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META) ffi::GST_BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META,
.to_str() )
.unwrap() };
}); pub static BUFFER_POOL_OPTION_VIDEO_ALIGNMENT: &glib::GStr = unsafe {
pub static BUFFER_POOL_OPTION_VIDEO_ALIGNMENT: Lazy<&'static str> = Lazy::new(|| unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)
CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT) };
.to_str() pub static BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META: &glib::GStr = unsafe {
.unwrap() glib::GStr::from_utf8_with_nul_unchecked(
}); ffi::GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META,
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) pub static BUFFER_POOL_OPTION_VIDEO_META: &glib::GStr =
.to_str() unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_BUFFER_POOL_OPTION_VIDEO_META) };
.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()
});
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[doc(alias = "GstVideoAlignment")] #[doc(alias = "GstVideoAlignment")]

View file

@ -184,277 +184,287 @@ impl VideoConverterConfig {
} }
pub fn set_resampler_method(&mut self, v: crate::VideoResamplerMethod) { 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")] #[doc(alias = "get_resampler_method")]
pub fn resampler_method(&self) -> crate::VideoResamplerMethod { pub fn resampler_method(&self) -> crate::VideoResamplerMethod {
self.0 self.0
.get_optional("GstVideoConverter.resampler-method") .get_optional(glib::gstr!("GstVideoConverter.resampler-method"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoResamplerMethod::Cubic) .unwrap_or(crate::VideoResamplerMethod::Cubic)
} }
pub fn set_chroma_resampler_method(&mut self, v: crate::VideoResamplerMethod) { 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")] #[doc(alias = "get_chroma_resampler_method")]
pub fn chroma_resampler_method(&self) -> crate::VideoResamplerMethod { pub fn chroma_resampler_method(&self) -> crate::VideoResamplerMethod {
self.0 self.0
.get_optional("GstVideoConverter.chroma-resampler-method") .get_optional(glib::gstr!("GstVideoConverter.chroma-resampler-method"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoResamplerMethod::Linear) .unwrap_or(crate::VideoResamplerMethod::Linear)
} }
pub fn set_resampler_taps(&mut self, v: u32) { 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")] #[doc(alias = "get_resampler_taps")]
pub fn resampler_taps(&self) -> u32 { pub fn resampler_taps(&self) -> u32 {
self.0 self.0
.get_optional("GstVideoConverter.resampler-taps") .get_optional(glib::gstr!("GstVideoConverter.resampler-taps"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(0) .unwrap_or(0)
} }
pub fn set_dither_method(&mut self, v: crate::VideoDitherMethod) { 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")] #[doc(alias = "get_dither_method")]
pub fn dither_method(&self) -> crate::VideoDitherMethod { pub fn dither_method(&self) -> crate::VideoDitherMethod {
self.0 self.0
.get_optional("GstVideoConverter.dither-method") .get_optional(glib::gstr!("GstVideoConverter.dither-method"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoDitherMethod::Bayer) .unwrap_or(crate::VideoDitherMethod::Bayer)
} }
pub fn set_dither_quantization(&mut self, v: u32) { 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")] #[doc(alias = "get_dither_quantization")]
pub fn dither_quantization(&self) -> u32 { pub fn dither_quantization(&self) -> u32 {
self.0 self.0
.get_optional("GstVideoConverter.dither-quantization") .get_optional(glib::gstr!("GstVideoConverter.dither-quantization"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(1) .unwrap_or(1)
} }
pub fn set_src_x(&mut self, v: i32) { 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")] #[doc(alias = "get_src_x")]
pub fn src_x(&self) -> i32 { pub fn src_x(&self) -> i32 {
self.0 self.0
.get_optional("GstVideoConverter.src-x") .get_optional(glib::gstr!("GstVideoConverter.src-x"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(0) .unwrap_or(0)
} }
pub fn set_src_y(&mut self, v: i32) { 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")] #[doc(alias = "get_src_y")]
pub fn src_y(&self) -> i32 { pub fn src_y(&self) -> i32 {
self.0 self.0
.get_optional("GstVideoConverter.src-y") .get_optional(glib::gstr!("GstVideoConverter.src-y"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(0) .unwrap_or(0)
} }
pub fn set_src_width(&mut self, v: Option<i32>) { pub fn set_src_width(&mut self, v: Option<i32>) {
if let Some(v) = v { if let Some(v) = v {
self.0.set("GstVideoConverter.src-width", v); self.0.set(glib::gstr!("GstVideoConverter.src-width"), v);
} else { } else {
self.0.remove_field("GstVideoConverter.src-width"); self.0
.remove_field(glib::gstr!("GstVideoConverter.src-width"));
} }
} }
#[doc(alias = "get_src_width")] #[doc(alias = "get_src_width")]
pub fn src_width(&self) -> Option<i32> { pub fn src_width(&self) -> Option<i32> {
self.0 self.0
.get_optional("GstVideoConverter.src-width") .get_optional(glib::gstr!("GstVideoConverter.src-width"))
.expect("Wrong type") .expect("Wrong type")
} }
pub fn set_src_height(&mut self, v: Option<i32>) { pub fn set_src_height(&mut self, v: Option<i32>) {
if let Some(v) = v { if let Some(v) = v {
self.0.set("GstVideoConverter.src-height", v); self.0.set(glib::gstr!("GstVideoConverter.src-height"), v);
} else { } else {
self.0.remove_field("GstVideoConverter.src-height"); self.0
.remove_field(glib::gstr!("GstVideoConverter.src-height"));
} }
} }
#[doc(alias = "get_src_height")] #[doc(alias = "get_src_height")]
pub fn src_height(&self) -> Option<i32> { pub fn src_height(&self) -> Option<i32> {
self.0 self.0
.get_optional("GstVideoConverter.src-height") .get_optional(glib::gstr!("GstVideoConverter.src-height"))
.expect("Wrong type") .expect("Wrong type")
} }
pub fn set_dest_x(&mut self, v: i32) { 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")] #[doc(alias = "get_dest_x")]
pub fn dest_x(&self) -> i32 { pub fn dest_x(&self) -> i32 {
self.0 self.0
.get_optional("GstVideoConverter.dest-x") .get_optional(glib::gstr!("GstVideoConverter.dest-x"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(0) .unwrap_or(0)
} }
pub fn set_dest_y(&mut self, v: i32) { 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")] #[doc(alias = "get_dest_y")]
pub fn dest_y(&self) -> i32 { pub fn dest_y(&self) -> i32 {
self.0 self.0
.get_optional("GstVideoConverter.dest-y") .get_optional(glib::gstr!("GstVideoConverter.dest-y"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(0) .unwrap_or(0)
} }
pub fn set_dest_width(&mut self, v: Option<i32>) { pub fn set_dest_width(&mut self, v: Option<i32>) {
if let Some(v) = v { if let Some(v) = v {
self.0.set("GstVideoConverter.dest-width", v); self.0.set(glib::gstr!("GstVideoConverter.dest-width"), v);
} else { } else {
self.0.remove_field("GstVideoConverter.dest-width"); self.0
.remove_field(glib::gstr!("GstVideoConverter.dest-width"));
} }
} }
#[doc(alias = "get_dest_width")] #[doc(alias = "get_dest_width")]
pub fn dest_width(&self) -> Option<i32> { pub fn dest_width(&self) -> Option<i32> {
self.0 self.0
.get_optional("GstVideoConverter.dest-width") .get_optional(glib::gstr!("GstVideoConverter.dest-width"))
.expect("Wrong type") .expect("Wrong type")
} }
pub fn set_dest_height(&mut self, v: Option<i32>) { pub fn set_dest_height(&mut self, v: Option<i32>) {
if let Some(v) = v { if let Some(v) = v {
self.0.set("GstVideoConverter.dest-height", v); self.0.set(glib::gstr!("GstVideoConverter.dest-height"), v);
} else { } else {
self.0.remove_field("GstVideoConverter.dest-height"); self.0
.remove_field(glib::gstr!("GstVideoConverter.dest-height"));
} }
} }
#[doc(alias = "get_dest_height")] #[doc(alias = "get_dest_height")]
pub fn dest_height(&self) -> Option<i32> { pub fn dest_height(&self) -> Option<i32> {
self.0 self.0
.get_optional("GstVideoConverter.dest-height") .get_optional(glib::gstr!("GstVideoConverter.dest-height"))
.expect("Wrong type") .expect("Wrong type")
} }
pub fn set_fill_border(&mut self, v: bool) { 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")] #[doc(alias = "get_fill_border")]
pub fn fills_border(&self) -> bool { pub fn fills_border(&self) -> bool {
self.0 self.0
.get_optional("GstVideoConverter.fill-border") .get_optional(glib::gstr!("GstVideoConverter.fill-border"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(true) .unwrap_or(true)
} }
pub fn set_alpha_value(&mut self, v: f64) { 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")] #[doc(alias = "get_alpha_value")]
pub fn alpha_value(&self) -> f64 { pub fn alpha_value(&self) -> f64 {
self.0 self.0
.get_optional("GstVideoConverter.alpha-value") .get_optional(glib::gstr!("GstVideoConverter.alpha-value"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(1.0) .unwrap_or(1.0)
} }
pub fn set_alpha_mode(&mut self, v: crate::VideoAlphaMode) { 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")] #[doc(alias = "get_alpha_mode")]
pub fn alpha_mode(&self) -> crate::VideoAlphaMode { pub fn alpha_mode(&self) -> crate::VideoAlphaMode {
self.0 self.0
.get_optional("GstVideoConverter.alpha-mode") .get_optional(glib::gstr!("GstVideoConverter.alpha-mode"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoAlphaMode::Copy) .unwrap_or(crate::VideoAlphaMode::Copy)
} }
pub fn set_border_argb(&mut self, v: u32) { 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")] #[doc(alias = "get_border_argb")]
pub fn border_argb(&self) -> u32 { pub fn border_argb(&self) -> u32 {
self.0 self.0
.get_optional("GstVideoConverter.border-argb") .get_optional(glib::gstr!("GstVideoConverter.border-argb"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(0xff_00_00_00) .unwrap_or(0xff_00_00_00)
} }
pub fn set_chroma_mode(&mut self, v: crate::VideoChromaMode) { 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")] #[doc(alias = "get_chroma_mode")]
pub fn chroma_mode(&self) -> crate::VideoChromaMode { pub fn chroma_mode(&self) -> crate::VideoChromaMode {
self.0 self.0
.get_optional("GstVideoConverter.chroma-mode") .get_optional(glib::gstr!("GstVideoConverter.chroma-mode"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoChromaMode::Full) .unwrap_or(crate::VideoChromaMode::Full)
} }
pub fn set_matrix_mode(&mut self, v: crate::VideoMatrixMode) { 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")] #[doc(alias = "get_matrix_mode")]
pub fn matrix_mode(&self) -> crate::VideoMatrixMode { pub fn matrix_mode(&self) -> crate::VideoMatrixMode {
self.0 self.0
.get_optional("GstVideoConverter.matrix-mode") .get_optional(glib::gstr!("GstVideoConverter.matrix-mode"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoMatrixMode::Full) .unwrap_or(crate::VideoMatrixMode::Full)
} }
pub fn set_gamma_mode(&mut self, v: crate::VideoGammaMode) { 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")] #[doc(alias = "get_gamma_mode")]
pub fn gamma_mode(&self) -> crate::VideoGammaMode { pub fn gamma_mode(&self) -> crate::VideoGammaMode {
self.0 self.0
.get_optional("GstVideoConverter.gamma-mode") .get_optional(glib::gstr!("GstVideoConverter.gamma-mode"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoGammaMode::None) .unwrap_or(crate::VideoGammaMode::None)
} }
pub fn set_primaries_mode(&mut self, v: crate::VideoPrimariesMode) { 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")] #[doc(alias = "get_primaries_mode")]
pub fn primaries_mode(&self) -> crate::VideoPrimariesMode { pub fn primaries_mode(&self) -> crate::VideoPrimariesMode {
self.0 self.0
.get_optional("GstVideoConverter.primaries-mode") .get_optional(glib::gstr!("GstVideoConverter.primaries-mode"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(crate::VideoPrimariesMode::None) .unwrap_or(crate::VideoPrimariesMode::None)
} }
pub fn set_threads(&mut self, v: u32) { 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")] #[doc(alias = "get_threads")]
pub fn threads(&self) -> u32 { pub fn threads(&self) -> u32 {
self.0 self.0
.get_optional("GstVideoConverter.threads") .get_optional(glib::gstr!("GstVideoConverter.threads"))
.expect("Wrong type") .expect("Wrong type")
.unwrap_or(1) .unwrap_or(1)
} }

View file

@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file. // 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 glib::translate::{from_glib, FromGlib, IntoGlib};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -269,18 +269,16 @@ impl crate::VideoFormat {
} }
#[doc(alias = "gst_video_format_to_string")] #[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 { if self == Self::Unknown {
return "UNKNOWN"; return glib::gstr!("UNKNOWN");
} }
unsafe { unsafe {
CStr::from_ptr( glib::GStr::from_ptr(
ffi::gst_video_format_to_string(self.into_glib()) ffi::gst_video_format_to_string(self.into_glib())
.as_ref() .as_ref()
.expect("gst_video_format_to_string returned NULL"), .expect("gst_video_format_to_string returned NULL"),
) )
.to_str()
.expect("gst_video_format_to_string returned an invalid string")
} }
} }

View file

@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file. // 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}; use glib::translate::{from_glib, IntoGlib, ToGlibPtr};
@ -32,13 +32,13 @@ impl VideoFormatInfo {
} }
#[inline] #[inline]
pub fn name<'a>(&self) -> &'a str { pub fn name<'a>(&self) -> &'a glib::GStr {
unsafe { CStr::from_ptr(self.0.name).to_str().unwrap() } unsafe { glib::GStr::from_ptr(self.0.name) }
} }
#[inline] #[inline]
pub fn description<'a>(&self) -> &'a str { pub fn description<'a>(&self) -> &'a glib::GStr {
unsafe { CStr::from_ptr(self.0.description).to_str().unwrap() } unsafe { glib::GStr::from_ptr(self.0.description) }
} }
#[inline] #[inline]

View file

@ -5,7 +5,7 @@ use std::{fmt, marker::PhantomData, ptr, str};
use glib::{ use glib::{
translate::{from_glib, from_glib_full, FromGlibPtrFull, IntoGlib, IntoGlibPtr, ToGlibPtr}, translate::{from_glib, from_glib_full, FromGlibPtrFull, IntoGlib, IntoGlibPtr, ToGlibPtr},
value::ToSendValue, value::ToSendValue,
StaticType, IntoGStr, StaticType,
}; };
use crate::{caps_features::*, structure::*, CapsIntersectMode}; use crate::{caps_features::*, structure::*, CapsIntersectMode};
@ -14,7 +14,7 @@ mini_object_wrapper!(Caps, CapsRef, ffi::GstCaps, || { ffi::gst_caps_get_type()
impl Caps { impl Caps {
#[doc(alias = "gst_caps_new_simple")] #[doc(alias = "gst_caps_new_simple")]
pub fn builder(name: &str) -> Builder<NoFeature> { pub fn builder(name: impl IntoGStr) -> Builder<NoFeature> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
Builder::new(name) Builder::new(name)
} }
@ -50,7 +50,9 @@ impl Caps {
} }
#[doc(alias = "gst_caps_new_simple")] #[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!(); skip_assert_initialized!();
let mut caps = Caps::new_empty(); let mut caps = Caps::new_empty();
@ -61,9 +63,14 @@ impl Caps {
} }
#[doc(alias = "gst_caps_new_empty_simple")] #[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!(); 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")] #[doc(alias = "gst_caps_fixate")]
@ -142,8 +149,10 @@ impl str::FromStr for Caps {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { unsafe {
Option::<_>::from_glib_full(ffi::gst_caps_from_string(s.to_glib_none().0)) 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")) .ok_or_else(|| glib::bool_error!("Failed to parse caps from string"))
})
} }
} }
} }
@ -234,7 +243,23 @@ impl std::iter::Extend<Caps> for CapsRef {
} }
impl 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")] #[doc(alias = "gst_caps_set_simple")]
#[deprecated = "Use `CapsRef::set()`"]
pub fn set_simple(&mut self, values: &[(&str, &(dyn ToSendValue + Sync))]) { pub fn set_simple(&mut self, values: &[(&str, &(dyn ToSendValue + Sync))]) {
for &(name, value) in values { for &(name, value) in values {
let value = value.to_value(); let value = value.to_value();
@ -913,7 +938,7 @@ impl<T> fmt::Debug for Builder<T> {
} }
impl Builder<NoFeature> { impl Builder<NoFeature> {
fn new(name: &str) -> Builder<NoFeature> { fn new(name: impl IntoGStr) -> Builder<NoFeature> {
skip_assert_initialized!(); skip_assert_initialized!();
Builder { Builder {
s: crate::Structure::new_empty(name), s: crate::Structure::new_empty(name),
@ -922,7 +947,10 @@ impl Builder<NoFeature> {
} }
} }
pub fn features(self, features: &[&str]) -> Builder<HasFeatures> { pub fn features(
self,
features: impl IntoIterator<Item = impl IntoGStr>,
) -> Builder<HasFeatures> {
Builder { Builder {
s: self.s, s: self.s,
features: Some(CapsFeatures::new(features)), features: Some(CapsFeatures::new(features)),
@ -940,7 +968,7 @@ impl Builder<NoFeature> {
} }
impl<T> Builder<T> { impl<T> Builder<T> {
pub fn field(mut self, name: &str, value: impl Into<glib::Value> + Send) -> Self { pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
self.s.set(name, value); self.s.set(name, value);
self self
} }
@ -1058,6 +1086,7 @@ mod tests {
use crate::{Array, Fraction}; use crate::{Array, Fraction};
#[test] #[test]
#[allow(deprecated)]
fn test_simple() { fn test_simple() {
crate::init().unwrap(); crate::init().unwrap();
@ -1100,12 +1129,12 @@ mod tests {
{ {
let caps = caps.get_mut().unwrap(); 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 assert!(caps
.features(0) .features(0)
.unwrap() .unwrap()
.is_equal(CapsFeatures::new(&["foo:bla"]).as_ref())); .is_equal(CapsFeatures::new(["foo:bla"]).as_ref()));
} }
#[test] #[test]
@ -1132,7 +1161,7 @@ mod tests {
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", 12) .field("int", 12)
.features(&["foo:bla", "foo:baz"]) .features(["foo:bla", "foo:baz"])
.build(); .build();
assert_eq!(caps.to_string(), "foo/bar(foo:bla, foo:baz), int=(int)12"); 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_any_features(Structure::builder("audio/x-raw").build())
.structure_with_features( .structure_with_features(
Structure::builder("video/x-raw").build(), Structure::builder("video/x-raw").build(),
CapsFeatures::new(&["foo:bla", "foo:baz"]), CapsFeatures::new(["foo:bla", "foo:baz"]),
) )
.build(); .build();
assert_eq!( assert_eq!(
@ -1185,11 +1214,11 @@ mod tests {
fn test_builder_full_with_features() { fn test_builder_full_with_features() {
crate::init().unwrap(); 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(Structure::builder("audio/x-raw").build())
.structure_with_features( .structure_with_features(
Structure::builder("video/x-raw").build(), Structure::builder("video/x-raw").build(),
CapsFeatures::new(&["foo:baz"]), CapsFeatures::new(["foo:baz"]),
) )
.build(); .build();
assert_eq!( assert_eq!(
@ -1253,7 +1282,7 @@ mod tests {
.build(); .build();
assert_eq!(format!("{:?}", caps), "Caps(audio/x-raw(ANY))"); 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(
Structure::builder("audio/x-raw") Structure::builder("audio/x-raw")
.field( .field(

View file

@ -2,7 +2,6 @@
use std::{ use std::{
borrow::{Borrow, BorrowMut, ToOwned}, borrow::{Borrow, BorrowMut, ToOwned},
ffi::CStr,
fmt, fmt,
marker::PhantomData, marker::PhantomData,
mem, mem,
@ -10,7 +9,7 @@ use std::{
ptr, str, ptr, str,
}; };
use glib::{translate::*, StaticType}; use glib::{translate::*, IntoGStr, StaticType};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
#[doc(alias = "GstCapsFeatures")] #[doc(alias = "GstCapsFeatures")]
@ -21,7 +20,7 @@ unsafe impl Sync for CapsFeatures {}
impl CapsFeatures { impl CapsFeatures {
#[doc(alias = "gst_caps_features_new")] #[doc(alias = "gst_caps_features_new")]
pub fn new(features: &[&str]) -> Self { pub fn new(features: impl IntoIterator<Item = impl IntoGStr>) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
let mut f = Self::new_empty(); let mut f = Self::new_empty();
@ -33,12 +32,12 @@ impl CapsFeatures {
} }
#[doc(alias = "gst_caps_features_new_id")] #[doc(alias = "gst_caps_features_new_id")]
pub fn from_quarks(features: &[glib::Quark]) -> Self { pub fn from_quarks(features: impl IntoIterator<Item = glib::Quark>) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
let mut f = Self::new_empty(); let mut f = Self::new_empty();
for feature in features { for feature in features.into_iter() {
f.add_from_quark(*feature); f.add_from_quark(feature);
} }
f f
@ -140,7 +139,7 @@ impl str::FromStr for CapsFeatures {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { 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() { if ptr.is_null() {
return Err(glib::bool_error!( return Err(glib::bool_error!(
"Failed to parse caps features from string" "Failed to parse caps features from string"
@ -361,12 +360,14 @@ impl CapsFeaturesRef {
} }
#[doc(alias = "gst_caps_features_contains")] #[doc(alias = "gst_caps_features_contains")]
pub fn contains(&self, feature: &str) -> bool { pub fn contains(&self, feature: impl IntoGStr) -> bool {
unsafe { unsafe {
feature.run_with_gstr(|feature| {
from_glib(ffi::gst_caps_features_contains( from_glib(ffi::gst_caps_features_contains(
self.as_ptr(), self.as_ptr(),
feature.to_glib_none().0, feature.as_ptr(),
)) ))
})
} }
} }
@ -388,7 +389,7 @@ impl CapsFeaturesRef {
#[doc(alias = "get_nth")] #[doc(alias = "get_nth")]
#[doc(alias = "gst_caps_features_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() { if idx >= self.size() {
return None; return None;
} }
@ -399,7 +400,7 @@ impl CapsFeaturesRef {
return None; 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")] #[doc(alias = "gst_caps_features_add")]
pub fn add(&mut self, feature: &str) { pub fn add(&mut self, feature: impl IntoGStr) {
unsafe { ffi::gst_caps_features_add(self.as_mut_ptr(), feature.to_glib_none().0) } unsafe {
feature.run_with_gstr(|feature| {
ffi::gst_caps_features_add(self.as_mut_ptr(), feature.as_ptr())
})
}
} }
#[doc(alias = "gst_caps_features_remove")] #[doc(alias = "gst_caps_features_remove")]
pub fn remove(&mut self, feature: &str) { pub fn remove(&mut self, feature: impl IntoGStr) {
unsafe { ffi::gst_caps_features_remove(self.as_mut_ptr(), feature.to_glib_none().0) } 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")] #[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<T: IntoIterator<Item = &'a glib::GStr>>(&mut self, iter: T) {
iter.into_iter().for_each(|f| self.add(f));
}
}
impl std::iter::Extend<String> for CapsFeaturesRef { impl std::iter::Extend<String> for CapsFeaturesRef {
fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
iter.into_iter().for_each(|f| self.add(&f)); iter.into_iter().for_each(|f| self.add(&f));
} }
} }
impl std::iter::Extend<glib::GString> for CapsFeaturesRef {
fn extend<T: IntoIterator<Item = glib::GString>>(&mut self, iter: T) {
iter.into_iter().for_each(|f| self.add(&f));
}
}
impl std::iter::Extend<glib::Quark> for CapsFeaturesRef { impl std::iter::Extend<glib::Quark> for CapsFeaturesRef {
fn extend<T: IntoIterator<Item = glib::Quark>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = glib::Quark>>(&mut self, iter: T) {
iter.into_iter().for_each(|f| self.add_from_quark(f)); 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> { impl<'a> Iterator for Iter<'a> {
type Item = &'a str; type Item = &'a glib::GStr;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.n_features { if self.idx >= self.n_features {
@ -551,7 +572,7 @@ impl<'a> Iterator for Iter<'a> {
self.idx += 1; 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 = let feature =
ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), end as u32); ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), end as u32);
debug_assert!(!feature.is_null()); 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, self.n_features as u32 - 1,
); );
debug_assert!(!feature.is_null()); 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); ffi::gst_caps_features_get_nth(self.caps_features.as_ptr(), self.n_features as u32);
debug_assert!(!feature.is_null()); 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()); 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 { impl<'a> IntoIterator for &'a CapsFeaturesRef {
type IntoIter = Iter<'a>; type IntoIter = Iter<'a>;
type Item = &'a str; type Item = &'a glib::GStr;
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.iter() 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<T: IntoIterator<Item = &'a glib::GStr>>(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<String> for CapsFeatures { impl std::iter::FromIterator<String> for CapsFeatures {
fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
@ -670,6 +703,18 @@ impl std::iter::FromIterator<String> for CapsFeatures {
} }
} }
impl std::iter::FromIterator<glib::GString> for CapsFeatures {
fn from_iter<T: IntoIterator<Item = glib::GString>>(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<glib::Quark> for CapsFeatures { impl std::iter::FromIterator<glib::Quark> for CapsFeatures {
fn from_iter<T: IntoIterator<Item = glib::Quark>>(iter: T) -> Self { fn from_iter<T: IntoIterator<Item = glib::Quark>>(iter: T) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
@ -710,13 +755,10 @@ impl ToOwned for CapsFeaturesRef {
unsafe impl Sync for CapsFeaturesRef {} unsafe impl Sync for CapsFeaturesRef {}
unsafe impl Send for CapsFeaturesRef {} unsafe impl Send for CapsFeaturesRef {}
pub static CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: Lazy<&'static str> = Lazy::new(|| unsafe { pub static CAPS_FEATURE_MEMORY_SYSTEM_MEMORY: &glib::GStr =
CStr::from_ptr(ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY) };
.to_str()
.unwrap()
});
pub static CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: Lazy<CapsFeatures> = pub static CAPS_FEATURES_MEMORY_SYSTEM_MEMORY: Lazy<CapsFeatures> =
Lazy::new(|| CapsFeatures::new(&[*CAPS_FEATURE_MEMORY_SYSTEM_MEMORY])); Lazy::new(|| CapsFeatures::new([CAPS_FEATURE_MEMORY_SYSTEM_MEMORY]));
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -33,7 +33,7 @@ impl<'a> Serialize for CapsFeaturesForIterSe<'a> {
if size > 0 { if size > 0 {
let mut seq = serializer.serialize_seq(Some(size))?; let mut seq = serializer.serialize_seq(Some(size))?;
for feature in iter { for feature in iter {
seq.serialize_element(feature)?; seq.serialize_element(feature.as_str())?;
} }
seq.end() seq.end()
} else { } else {
@ -81,7 +81,7 @@ impl<'de> Visitor<'de> for CapsFeaturesSomeVisitor {
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> { fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut features = CapsFeatures::new_empty(); let mut features = CapsFeatures::new_empty();
while let Some(feature) = seq.next_element::<String>()? { while let Some(feature) = seq.next_element::<String>()? {
features.add(feature.as_ref()); features.add(feature.as_str());
} }
Ok(CapsFeaturesSome(features)) Ok(CapsFeaturesSome(features))
} }

View file

@ -262,7 +262,7 @@ mod tests {
.field("string", "bla") .field("string", "bla")
.field("fraction", Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", Array::new([1, 2])) .field("array", Array::new([1, 2]))
.features(&["foo:bar", "foo:baz"]) .features(["foo:bar", "foo:baz"])
.build(); .build();
let pretty_config = ron::ser::PrettyConfig::new().new_line("".to_string()); let pretty_config = ron::ser::PrettyConfig::new().new_line("".to_string());
@ -405,7 +405,7 @@ mod tests {
.as_ref() .as_ref()
); );
let f = caps.features(0).unwrap(); 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#" let caps_ron = r#"
Some([ Some([
@ -471,7 +471,7 @@ mod tests {
.field("string", "bla") .field("string", "bla")
.field("fraction", Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", Array::new([1, 2])) .field("array", Array::new([1, 2]))
.features(&["foo:bar", "foo:baz"]) .features(["foo:bar", "foo:baz"])
.build(); .build();
let caps_ser = ron::ser::to_string(&caps).unwrap(); let caps_ser = ron::ser::to_string(&caps).unwrap();
let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap(); let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();

View file

@ -41,36 +41,36 @@ impl DeviceProviderFactory {
#[doc(alias = "get_longname")] #[doc(alias = "get_longname")]
#[doc(alias = "gst_device_provider_factory_get_longname")] #[doc(alias = "gst_device_provider_factory_get_longname")]
pub fn longname(&self) -> &str { pub fn longname(&self) -> &str {
self.metadata(&ELEMENT_METADATA_LONGNAME).unwrap() self.metadata(ELEMENT_METADATA_LONGNAME).unwrap()
} }
#[doc(alias = "get_klass")] #[doc(alias = "get_klass")]
#[doc(alias = "gst_device_provider_factory_get_klass")] #[doc(alias = "gst_device_provider_factory_get_klass")]
pub fn klass(&self) -> &str { pub fn klass(&self) -> &str {
self.metadata(&ELEMENT_METADATA_KLASS).unwrap() self.metadata(ELEMENT_METADATA_KLASS).unwrap()
} }
#[doc(alias = "get_description")] #[doc(alias = "get_description")]
#[doc(alias = "gst_device_provider_factory_get_description")] #[doc(alias = "gst_device_provider_factory_get_description")]
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
self.metadata(&ELEMENT_METADATA_DESCRIPTION).unwrap() self.metadata(ELEMENT_METADATA_DESCRIPTION).unwrap()
} }
#[doc(alias = "get_author")] #[doc(alias = "get_author")]
#[doc(alias = "gst_device_provider_factory_get_author")] #[doc(alias = "gst_device_provider_factory_get_author")]
pub fn author(&self) -> &str { pub fn author(&self) -> &str {
self.metadata(&ELEMENT_METADATA_AUTHOR).unwrap() self.metadata(ELEMENT_METADATA_AUTHOR).unwrap()
} }
#[doc(alias = "get_documentation_uri")] #[doc(alias = "get_documentation_uri")]
#[doc(alias = "gst_device_provider_factory_get_documentation_uri")] #[doc(alias = "gst_device_provider_factory_get_documentation_uri")]
pub fn documentation_uri(&self) -> Option<&str> { 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 = "get_icon_name")]
#[doc(alias = "gst_device_provider_factory_get_icon_name")] #[doc(alias = "gst_device_provider_factory_get_icon_name")]
pub fn icon_name(&self) -> Option<&str> { pub fn icon_name(&self) -> Option<&str> {
self.metadata(&ELEMENT_METADATA_ICON_NAME) self.metadata(ELEMENT_METADATA_ICON_NAME)
} }
} }

View file

@ -3,7 +3,6 @@
use std::{ffi::CStr, future::Future, mem, num::NonZeroU64, pin::Pin}; use std::{ffi::CStr, future::Future, mem, num::NonZeroU64, pin::Pin};
use glib::translate::*; use glib::translate::*;
use once_cell::sync::Lazy;
use crate::{ use crate::{
format::{ format::{
@ -982,41 +981,23 @@ pub unsafe trait ElementClassExt {
unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {} unsafe impl<T: IsA<Element> + glib::object::IsClass> ElementClassExt for glib::object::Class<T> {}
#[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")] #[doc(alias = "GST_ELEMENT_METADATA_AUTHOR")]
pub static ELEMENT_METADATA_AUTHOR: Lazy<&'static str> = Lazy::new(|| unsafe { pub static ELEMENT_METADATA_AUTHOR: &glib::GStr =
CStr::from_ptr(ffi::GST_ELEMENT_METADATA_AUTHOR) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_AUTHOR) };
.to_str()
.unwrap()
});
#[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")] #[doc(alias = "GST_ELEMENT_METADATA_DESCRIPTION")]
pub static ELEMENT_METADATA_DESCRIPTION: Lazy<&'static str> = Lazy::new(|| unsafe { pub static ELEMENT_METADATA_DESCRIPTION: &glib::GStr =
CStr::from_ptr(ffi::GST_ELEMENT_METADATA_DESCRIPTION) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DESCRIPTION) };
.to_str()
.unwrap()
});
#[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")] #[doc(alias = "GST_ELEMENT_METADATA_DOC_URI")]
pub static ELEMENT_METADATA_DOC_URI: Lazy<&'static str> = Lazy::new(|| unsafe { pub static ELEMENT_METADATA_DOC_URI: &glib::GStr =
CStr::from_ptr(ffi::GST_ELEMENT_METADATA_DOC_URI) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_DOC_URI) };
.to_str()
.unwrap()
});
#[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")] #[doc(alias = "GST_ELEMENT_METADATA_ICON_NAME")]
pub static ELEMENT_METADATA_ICON_NAME: Lazy<&'static str> = Lazy::new(|| unsafe { pub static ELEMENT_METADATA_ICON_NAME: &glib::GStr =
CStr::from_ptr(ffi::GST_ELEMENT_METADATA_ICON_NAME) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_ICON_NAME) };
.to_str()
.unwrap()
});
#[doc(alias = "GST_ELEMENT_METADATA_KLASS")] #[doc(alias = "GST_ELEMENT_METADATA_KLASS")]
pub static ELEMENT_METADATA_KLASS: Lazy<&'static str> = Lazy::new(|| unsafe { pub static ELEMENT_METADATA_KLASS: &glib::GStr =
CStr::from_ptr(ffi::GST_ELEMENT_METADATA_KLASS) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_KLASS) };
.to_str()
.unwrap()
});
#[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")] #[doc(alias = "GST_ELEMENT_METADATA_LONGNAME")]
pub static ELEMENT_METADATA_LONGNAME: Lazy<&'static str> = Lazy::new(|| unsafe { pub static ELEMENT_METADATA_LONGNAME: &glib::GStr =
CStr::from_ptr(ffi::GST_ELEMENT_METADATA_LONGNAME) unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_ELEMENT_METADATA_LONGNAME) };
.to_str()
.unwrap()
});
#[doc(alias = "GST_ELEMENT_ERROR")] #[doc(alias = "GST_ELEMENT_ERROR")]
#[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")] #[doc(alias = "GST_ELEMENT_ERROR_WITH_DETAILS")]

View file

@ -140,37 +140,37 @@ impl ElementFactory {
#[doc(alias = "get_longname")] #[doc(alias = "get_longname")]
#[doc(alias = "gst_element_factory_get_longname")] #[doc(alias = "gst_element_factory_get_longname")]
pub fn longname(&self) -> &str { pub fn longname(&self) -> &str {
self.metadata(&ELEMENT_METADATA_LONGNAME).unwrap() self.metadata(ELEMENT_METADATA_LONGNAME).unwrap()
} }
#[doc(alias = "get_klass")] #[doc(alias = "get_klass")]
#[doc(alias = "gst_element_factory_get_klass")] #[doc(alias = "gst_element_factory_get_klass")]
pub fn klass(&self) -> &str { pub fn klass(&self) -> &str {
self.metadata(&ELEMENT_METADATA_KLASS).unwrap() self.metadata(ELEMENT_METADATA_KLASS).unwrap()
} }
#[doc(alias = "get_description")] #[doc(alias = "get_description")]
#[doc(alias = "gst_element_factory_get_description")] #[doc(alias = "gst_element_factory_get_description")]
pub fn description(&self) -> &str { pub fn description(&self) -> &str {
self.metadata(&ELEMENT_METADATA_DESCRIPTION).unwrap() self.metadata(ELEMENT_METADATA_DESCRIPTION).unwrap()
} }
#[doc(alias = "get_author")] #[doc(alias = "get_author")]
#[doc(alias = "gst_element_factory_get_author")] #[doc(alias = "gst_element_factory_get_author")]
pub fn author(&self) -> &str { pub fn author(&self) -> &str {
self.metadata(&ELEMENT_METADATA_AUTHOR).unwrap() self.metadata(ELEMENT_METADATA_AUTHOR).unwrap()
} }
#[doc(alias = "get_documentation_uri")] #[doc(alias = "get_documentation_uri")]
#[doc(alias = "gst_element_factory_get_documentation_uri")] #[doc(alias = "gst_element_factory_get_documentation_uri")]
pub fn documentation_uri(&self) -> Option<&str> { 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 = "get_icon_name")]
#[doc(alias = "gst_element_factory_get_icon_name")] #[doc(alias = "gst_element_factory_get_icon_name")]
pub fn icon_name(&self) -> Option<&str> { 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")] #[doc(alias = "gst_element_factory_can_sink_all_caps")]

View file

@ -1,6 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file. // 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}; use glib::{translate::*, StaticType};
@ -25,7 +25,7 @@ impl fmt::Debug for StaticCaps {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("StaticCaps") f.debug_struct("StaticCaps")
.field("str", &unsafe { .field("str", &unsafe {
CStr::from_ptr(self.0.as_ref().string).to_str() glib::GStr::from_ptr(self.0.as_ref().string)
}) })
.finish() .finish()
} }

View file

@ -2,7 +2,6 @@
use std::{ use std::{
borrow::{Borrow, BorrowMut, ToOwned}, borrow::{Borrow, BorrowMut, ToOwned},
ffi::CStr,
fmt, fmt,
marker::PhantomData, marker::PhantomData,
mem, mem,
@ -11,9 +10,10 @@ use std::{
}; };
use glib::{ use glib::{
prelude::*,
translate::*, translate::*,
value::{FromValue, SendValue, ToSendValue}, value::{FromValue, SendValue, ToSendValue},
StaticType, IntoGStr,
}; };
use crate::Fraction; use crate::Fraction;
@ -50,23 +50,24 @@ unsafe impl Sync for Structure {}
impl Structure { impl Structure {
#[doc(alias = "gst_structure_new")] #[doc(alias = "gst_structure_new")]
pub fn builder(name: &str) -> Builder { pub fn builder(name: impl IntoGStr) -> Builder {
skip_assert_initialized!(); skip_assert_initialized!();
Builder::new(name) Builder::new(name)
} }
#[doc(alias = "gst_structure_new_empty")] #[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!(); assert_initialized_main_thread!();
unsafe { 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()); debug_assert!(!ptr.is_null());
Structure(ptr::NonNull::new_unchecked(ptr)) Structure(ptr::NonNull::new_unchecked(ptr))
} }
} }
#[doc(alias = "gst_structure_new")] #[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!(); skip_assert_initialized!();
let mut structure = Structure::new_empty(name); let mut structure = Structure::new_empty(name);
@ -79,8 +80,8 @@ impl Structure {
#[allow(clippy::should_implement_trait)] #[allow(clippy::should_implement_trait)]
pub fn from_iter<'a>( pub fn from_iter<'a>(
name: &str, name: impl IntoGStr,
iter: impl IntoIterator<Item = (&'a str, SendValue)>, iter: impl IntoIterator<Item = (&'a glib::GStr, SendValue)>,
) -> Structure { ) -> Structure {
skip_assert_initialized!(); skip_assert_initialized!();
let mut structure = Structure::new_empty(name); let mut structure = Structure::new_empty(name);
@ -189,7 +190,8 @@ impl str::FromStr for Structure {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { 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() { if structure.is_null() {
Err(glib::bool_error!("Failed to parse structure from string")) Err(glib::bool_error!("Failed to parse structure from string"))
} else { } else {
@ -429,7 +431,7 @@ impl StructureRef {
#[doc(alias = "gst_structure_get")] #[doc(alias = "gst_structure_get")]
pub fn get<'a, T: FromValue<'a>>( pub fn get<'a, T: FromValue<'a>>(
&'a self, &'a self,
name: &str, name: impl IntoGStr,
) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>> ) -> Result<T, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>>
{ {
let name = glib::Quark::from_str(name); let name = glib::Quark::from_str(name);
@ -439,7 +441,7 @@ impl StructureRef {
#[doc(alias = "gst_structure_get")] #[doc(alias = "gst_structure_get")]
pub fn get_optional<'a, T: FromValue<'a>>( pub fn get_optional<'a, T: FromValue<'a>>(
&'a self, &'a self,
name: &str, name: impl IntoGStr,
) -> Result< ) -> Result<
Option<T>, Option<T>,
GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>, GetError<<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error>,
@ -450,7 +452,10 @@ impl StructureRef {
#[doc(alias = "get_value")] #[doc(alias = "get_value")]
#[doc(alias = "gst_structure_get_value")] #[doc(alias = "gst_structure_get_value")]
pub fn value(&self, name: &str) -> Result<&SendValue, GetError<std::convert::Infallible>> { pub fn value(
&self,
name: impl IntoGStr,
) -> Result<&SendValue, GetError<std::convert::Infallible>> {
let name = glib::Quark::from_str(name); let name = glib::Quark::from_str(name);
self.value_by_quark(name) self.value_by_quark(name)
} }
@ -502,19 +507,17 @@ impl StructureRef {
} }
#[doc(alias = "gst_structure_set")] #[doc(alias = "gst_structure_set")]
pub fn set(&mut self, name: &str, value: impl Into<glib::Value> + Send) { pub fn set(&mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) {
let value = glib::SendValue::from_owned(value); let value = glib::SendValue::from_owned(value);
self.set_value(name, value); self.set_value(name, value);
} }
#[doc(alias = "gst_structure_set_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 { unsafe {
ffi::gst_structure_take_value( name.run_with_gstr(|name| {
&mut self.0, ffi::gst_structure_take_value(&mut self.0, name.as_ptr(), &mut value.into_raw())
name.to_glib_none().0, });
&mut value.into_raw(),
);
} }
} }
@ -533,12 +536,8 @@ impl StructureRef {
#[doc(alias = "get_name")] #[doc(alias = "get_name")]
#[doc(alias = "gst_structure_get_name")] #[doc(alias = "gst_structure_get_name")]
pub fn name<'a>(&self) -> &'a str { pub fn name<'a>(&self) -> &'a glib::GStr {
unsafe { unsafe { glib::GStr::from_ptr(ffi::gst_structure_get_name(&self.0)) }
CStr::from_ptr(ffi::gst_structure_get_name(&self.0))
.to_str()
.unwrap()
}
} }
#[doc(alias = "gst_structure_get_name_id")] #[doc(alias = "gst_structure_get_name_id")]
@ -547,8 +546,10 @@ impl StructureRef {
} }
#[doc(alias = "gst_structure_set_name")] #[doc(alias = "gst_structure_set_name")]
pub fn set_name(&mut self, name: &str) { pub fn set_name(&mut self, name: impl IntoGStr) {
unsafe { ffi::gst_structure_set_name(&mut self.0, name.to_glib_none().0) } unsafe {
name.run_with_gstr(|name| ffi::gst_structure_set_name(&mut self.0, name.as_ptr()))
}
} }
#[doc(alias = "gst_structure_has_name")] #[doc(alias = "gst_structure_has_name")]
@ -557,23 +558,24 @@ impl StructureRef {
} }
#[doc(alias = "gst_structure_has_field")] #[doc(alias = "gst_structure_has_field")]
pub fn has_field(&self, field: &str) -> bool { pub fn has_field(&self, field: impl IntoGStr) -> bool {
unsafe { unsafe {
from_glib(ffi::gst_structure_has_field( field.run_with_gstr(|field| {
&self.0, from_glib(ffi::gst_structure_has_field(&self.0, field.as_ptr()))
field.to_glib_none().0, })
))
} }
} }
#[doc(alias = "gst_structure_has_field_typed")] #[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 { unsafe {
field.run_with_gstr(|field| {
from_glib(ffi::gst_structure_has_field_typed( from_glib(ffi::gst_structure_has_field_typed(
&self.0, &self.0,
field.to_glib_none().0, field.as_ptr(),
type_.into_glib(), type_.into_glib(),
)) ))
})
} }
} }
@ -594,15 +596,17 @@ impl StructureRef {
} }
#[doc(alias = "gst_structure_remove_field")] #[doc(alias = "gst_structure_remove_field")]
pub fn remove_field(&mut self, field: &str) { pub fn remove_field(&mut self, field: impl IntoGStr) {
unsafe { 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")] #[doc(alias = "gst_structure_remove_fields")]
pub fn remove_fields(&mut self, fields: &[&str]) { pub fn remove_fields(&mut self, fields: impl IntoIterator<Item = impl IntoGStr>) {
for f in fields { for f in fields.into_iter() {
self.remove_field(f) self.remove_field(f)
} }
} }
@ -624,7 +628,7 @@ impl StructureRef {
#[doc(alias = "get_nth_field_name")] #[doc(alias = "get_nth_field_name")]
#[doc(alias = "gst_structure_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() { if idx >= self.n_fields() {
return None; return None;
} }
@ -633,7 +637,7 @@ impl StructureRef {
let field_name = ffi::gst_structure_nth_field_name(&self.0, idx); let field_name = ffi::gst_structure_nth_field_name(&self.0, idx);
debug_assert!(!field_name.is_null()); 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")] #[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 { unsafe {
from_glib(ffi::gst_structure_fixate_field( name.run_with_gstr(|name| {
&mut self.0, from_glib(ffi::gst_structure_fixate_field(&mut self.0, name.as_ptr()))
name.to_glib_none().0, })
))
} }
} }
#[doc(alias = "gst_structure_fixate_field_boolean")] #[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 { unsafe {
name.run_with_gstr(|name| {
from_glib(ffi::gst_structure_fixate_field_boolean( from_glib(ffi::gst_structure_fixate_field_boolean(
&mut self.0, &mut self.0,
name.to_glib_none().0, name.as_ptr(),
target.into_glib(), target.into_glib(),
)) ))
})
} }
} }
#[doc(alias = "gst_structure_fixate_field_string")] #[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 { unsafe {
name.run_with_gstr(|name| {
target.run_with_gstr(|target| {
from_glib(ffi::gst_structure_fixate_field_string( from_glib(ffi::gst_structure_fixate_field_string(
&mut self.0, &mut self.0,
name.to_glib_none().0, name.as_ptr(),
target.to_glib_none().0, target.as_ptr(),
)) ))
})
})
} }
} }
#[doc(alias = "gst_structure_fixate_field_nearest_double")] #[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 { unsafe {
name.run_with_gstr(|name| {
from_glib(ffi::gst_structure_fixate_field_nearest_double( from_glib(ffi::gst_structure_fixate_field_nearest_double(
&mut self.0, &mut self.0,
name.to_glib_none().0, name.as_ptr(),
target, target,
)) ))
})
} }
} }
#[doc(alias = "gst_structure_fixate_field_nearest_fraction")] #[doc(alias = "gst_structure_fixate_field_nearest_fraction")]
pub fn fixate_field_nearest_fraction<T: Into<Fraction>>( pub fn fixate_field_nearest_fraction(
&mut self, &mut self,
name: &str, name: impl IntoGStr,
target: T, target: impl Into<Fraction>,
) -> bool { ) -> bool {
skip_assert_initialized!(); skip_assert_initialized!();
let target = target.into(); let target = target.into();
unsafe { unsafe {
name.run_with_gstr(|name| {
from_glib(ffi::gst_structure_fixate_field_nearest_fraction( from_glib(ffi::gst_structure_fixate_field_nearest_fraction(
&mut self.0, &mut self.0,
name.to_glib_none().0, name.as_ptr(),
target.numer(), target.numer(),
target.denom(), target.denom(),
)) ))
})
} }
} }
#[doc(alias = "gst_structure_fixate_field_nearest_int")] #[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 { unsafe {
name.run_with_gstr(|name| {
from_glib(ffi::gst_structure_fixate_field_nearest_int( from_glib(ffi::gst_structure_fixate_field_nearest_int(
&mut self.0, &mut self.0,
name.to_glib_none().0, name.as_ptr(),
target, target,
)) ))
})
} }
} }
@ -941,7 +956,7 @@ impl<'a> FieldIterator<'a> {
} }
impl<'a> Iterator for FieldIterator<'a> { impl<'a> Iterator for FieldIterator<'a> {
type Item = &'static str; type Item = &'static glib::GStr;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.n_fields { if self.idx >= self.n_fields {
@ -991,7 +1006,7 @@ impl<'a> Iter<'a> {
} }
impl<'a> Iterator for 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<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let f = self.iter.next()?; let f = self.iter.next()?;
@ -1041,7 +1056,7 @@ impl<'a> std::iter::FusedIterator for Iter<'a> {}
impl<'a> IntoIterator for &'a StructureRef { impl<'a> IntoIterator for &'a StructureRef {
type IntoIter = Iter<'a>; type IntoIter = Iter<'a>;
type Item = (&'static str, &'a SendValue); type Item = (&'static glib::GStr, &'a SendValue);
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.iter() 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<T: IntoIterator<Item = (&'a glib::GStr, SendValue)>>(&mut self, iter: T) {
iter.into_iter().for_each(|(f, v)| self.set_value(f, v));
}
}
impl std::iter::Extend<(String, SendValue)> for StructureRef { impl std::iter::Extend<(String, SendValue)> for StructureRef {
fn extend<T: IntoIterator<Item = (String, SendValue)>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = (String, SendValue)>>(&mut self, iter: T) {
iter.into_iter().for_each(|(f, v)| self.set_value(&f, v)); iter.into_iter().for_each(|(f, v)| self.set_value(&f, v));
} }
} }
impl std::iter::Extend<(glib::GString, SendValue)> for StructureRef {
fn extend<T: IntoIterator<Item = (glib::GString, SendValue)>>(&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 { impl std::iter::Extend<(glib::Quark, SendValue)> for StructureRef {
fn extend<T: IntoIterator<Item = (glib::Quark, SendValue)>>(&mut self, iter: T) { fn extend<T: IntoIterator<Item = (glib::Quark, SendValue)>>(&mut self, iter: T) {
iter.into_iter() iter.into_iter()
@ -1074,14 +1101,14 @@ pub struct Builder {
} }
impl Builder { impl Builder {
fn new(name: &str) -> Self { fn new(name: impl IntoGStr) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
Builder { Builder {
s: Structure::new_empty(name), s: Structure::new_empty(name),
} }
} }
pub fn field(mut self, name: &str, value: impl Into<glib::Value> + Send) -> Self { pub fn field(mut self, name: impl IntoGStr, value: impl Into<glib::Value> + Send) -> Self {
self.s.set(name, value); self.s.set(name, value);
self self
} }
@ -1097,6 +1124,7 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
#[allow(deprecated)]
fn new_set_get() { fn new_set_get() {
use glib::{value, Type}; use glib::{value, Type};

View file

@ -50,7 +50,7 @@ impl<'a> Serialize for StructureForIter<'a> {
impl Serialize for StructureRef { impl Serialize for StructureRef {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut tup = serializer.serialize_tuple(2)?; 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.serialize_element(&StructureForIter(self))?;
tup.end() tup.end()
} }
@ -141,7 +141,7 @@ impl<'de> Visitor<'de> for StructureVisitor {
let name = seq let name = seq
.next_element::<String>()? .next_element::<String>()?
.ok_or_else(|| de::Error::custom("Expected a name for the `Structure`"))?; .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()))? seq.next_element_seed(FieldsDe(structure.as_mut()))?
.ok_or_else(|| de::Error::custom("Expected a sequence of `Field`s"))?; .ok_or_else(|| de::Error::custom("Expected a sequence of `Field`s"))?;

View file

@ -720,7 +720,7 @@ mod tests {
assert_eq!(element.name(), "test"); assert_eq!(element.name(), "test");
assert_eq!( assert_eq!(
element.metadata(&crate::ELEMENT_METADATA_LONGNAME), element.metadata(crate::ELEMENT_METADATA_LONGNAME),
Some("Test Element") Some("Test Element")
); );

View file

@ -17,7 +17,7 @@ impl<O: IsA<TagSetter>> TagSetterExtManual for O {
ffi::gst_tag_setter_add_tag_value( ffi::gst_tag_setter_add_tag_value(
self.as_ref().to_glib_none().0, self.as_ref().to_glib_none().0,
mode.into_glib(), mode.into_glib(),
T::tag_name().to_glib_none().0, T::TAG_NAME.as_ptr(),
v.to_glib_none().0, v.to_glib_none().0,
); );
} }

View file

@ -1,19 +1,18 @@
// Take a look at the license at the top of the repository in the LICENSE file. // 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::{ use glib::{
translate::*, translate::*,
value::{FromValue, SendValue, ToSendValue, Value}, value::{FromValue, SendValue, ToSendValue, Value},
StaticType, IntoGStr, StaticType,
}; };
use once_cell::sync::Lazy;
use crate::{Sample, TagError, TagMergeMode, TagScope}; use crate::{Sample, TagError, TagMergeMode, TagScope};
pub trait Tag<'a> { pub trait Tag<'a> {
type TagType: StaticType + FromValue<'a> + ToSendValue + Send + Sync; type TagType: StaticType + FromValue<'a> + ToSendValue + Send + Sync;
fn tag_name<'b>() -> &'b str; const TAG_NAME: &'static glib::GStr;
} }
macro_rules! impl_tag( macro_rules! impl_tag(
@ -21,14 +20,8 @@ macro_rules! impl_tag(
pub enum $name {} pub enum $name {}
impl<'a> Tag<'a> for $name { impl<'a> Tag<'a> for $name {
type TagType = $t; type TagType = $t;
const TAG_NAME: &'static glib::GStr = unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::$gst_tag) };
fn tag_name<'b>() -> &'b str {
*$rust_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<T> TagValue<T> {
impl TagListRef { impl TagListRef {
#[doc(alias = "gst_tag_list_add")] #[doc(alias = "gst_tag_list_add")]
pub fn add<'a, T: Tag<'a>>(&mut self, value: &T::TagType, mode: TagMergeMode) { 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 = <T::TagType as ToSendValue>::to_send_value(value); let v = <T::TagType as ToSendValue>::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")] #[doc(alias = "gst_tag_list_add")]
pub fn add_generic( pub fn add_generic(
&mut self, &mut self,
tag_name: &str, tag_name: impl IntoGStr,
value: impl ToSendValue, value: impl ToSendValue,
mode: TagMergeMode, mode: TagMergeMode,
) -> Result<(), TagError> { ) -> Result<(), TagError> {
@ -381,14 +374,13 @@ impl TagListRef {
#[doc(alias = "gst_tag_list_add_value")] #[doc(alias = "gst_tag_list_add_value")]
pub fn add_value( pub fn add_value(
&mut self, &mut self,
tag_name: &str, tag_name: impl IntoGStr,
value: &glib::SendValue, value: &glib::SendValue,
mode: TagMergeMode, mode: TagMergeMode,
) -> Result<(), TagError> { ) -> Result<(), TagError> {
unsafe { 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()));
let tag_type: glib::Type = from_glib(ffi::gst_tag_get_type(tag_name.0));
if tag_type != value.type_() { if tag_type != value.type_() {
return Err(TagError::TypeMismatch); return Err(TagError::TypeMismatch);
} }
@ -396,35 +388,35 @@ impl TagListRef {
ffi::gst_tag_list_add_value( ffi::gst_tag_list_add_value(
self.as_mut_ptr(), self.as_mut_ptr(),
mode.into_glib(), mode.into_glib(),
tag_name.0, tag_name.as_ptr(),
value.to_glib_none().0, value.to_glib_none().0,
); );
}
Ok(()) Ok(())
})
}
} }
#[doc(alias = "gst_tag_list_remove_tag")] #[doc(alias = "gst_tag_list_remove_tag")]
pub fn remove<'a, T: Tag<'a>>(&mut self) { 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")] #[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 { unsafe {
let tag_name = tag_name.to_glib_none(); tag_name.run_with_gstr(|tag_name| {
ffi::gst_tag_list_remove_tag(self.as_mut_ptr(), tag_name.as_ptr());
ffi::gst_tag_list_remove_tag(self.as_mut_ptr(), tag_name.0); })
} }
} }
#[doc(alias = "gst_tag_list_get")] #[doc(alias = "gst_tag_list_get")]
pub fn get<'a, T: Tag<'a>>(&self) -> Option<TagValue<T::TagType>> { pub fn get<'a, T: Tag<'a>>(&self) -> Option<TagValue<T::TagType>> {
self.generic(T::tag_name()).map(|value| { self.generic(T::TAG_NAME).map(|value| {
if !value.is::<T::TagType>() { if !value.is::<T::TagType>() {
panic!( panic!(
"TagListRef::get type mismatch for tag {}: {}", "TagListRef::get type mismatch for tag {}: {}",
T::tag_name(), T::TAG_NAME,
value.type_() value.type_()
); );
} }
@ -434,23 +426,25 @@ impl TagListRef {
#[doc(alias = "gst_tag_list_get")] #[doc(alias = "gst_tag_list_get")]
#[doc(alias = "get_generic")] #[doc(alias = "get_generic")]
pub fn generic(&self, tag_name: &str) -> Option<SendValue> { pub fn generic(&self, tag_name: impl IntoGStr) -> Option<SendValue> {
unsafe { unsafe {
let mut value: mem::MaybeUninit<SendValue> = mem::MaybeUninit::zeroed(); let mut value: mem::MaybeUninit<SendValue> = mem::MaybeUninit::zeroed();
let found: bool = from_glib(ffi::gst_tag_list_copy_value( 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, (*value.as_mut_ptr()).to_glib_none_mut().0,
self.as_ptr(), self.as_ptr(),
tag_name.to_glib_none().0, tag_name.as_ptr(),
)); ))
});
if !found { if !found {
return None; None
} } else {
Some(value.assume_init()) Some(value.assume_init())
} }
} }
}
#[doc(alias = "gst_tag_list_n_tags")] #[doc(alias = "gst_tag_list_n_tags")]
pub fn n_tags(&self) -> u32 { pub fn n_tags(&self) -> u32 {
@ -458,7 +452,7 @@ impl TagListRef {
} }
#[doc(alias = "gst_tag_list_nth_tag_name")] #[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() { if idx >= self.n_tags() {
return None; return None;
} }
@ -466,18 +460,18 @@ impl TagListRef {
unsafe { unsafe {
let name = ffi::gst_tag_list_nth_tag_name(self.as_ptr(), idx); let name = ffi::gst_tag_list_nth_tag_name(self.as_ptr(), idx);
debug_assert!(!name.is_null()); 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 = "get_index")]
#[doc(alias = "gst_tag_list_get_index")] #[doc(alias = "gst_tag_list_get_index")]
pub fn index<'a, T: Tag<'a>>(&self, idx: u32) -> Option<&'a TagValue<T::TagType>> { pub fn index<'a, T: Tag<'a>>(&self, idx: u32) -> Option<&'a TagValue<T::TagType>> {
self.index_generic(T::tag_name(), idx).map(|value| { self.index_generic(T::TAG_NAME, idx).map(|value| {
if !value.is::<T::TagType>() { if !value.is::<T::TagType>() {
panic!( panic!(
"TagListRef::get_index type mismatch for tag {}: {}", "TagListRef::get_index type mismatch for tag {}: {}",
T::tag_name(), T::TAG_NAME,
value.type_() value.type_()
); );
} }
@ -487,36 +481,42 @@ impl TagListRef {
#[doc(alias = "get_index_generic")] #[doc(alias = "get_index_generic")]
#[doc(alias = "gst_tag_list_get_index")] #[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 { unsafe {
let value = let value = tag_name.run_with_gstr(|tag_name| {
ffi::gst_tag_list_get_value_index(self.as_ptr(), tag_name.to_glib_none().0, idx); ffi::gst_tag_list_get_value_index(self.as_ptr(), tag_name.as_ptr(), idx)
});
if value.is_null() { if value.is_null() {
return None; None
} } else {
Some(&*(value as *const SendValue)) Some(&*(value as *const SendValue))
} }
} }
}
#[doc(alias = "get_size")] #[doc(alias = "get_size")]
#[doc(alias = "gst_tag_list_get_tag_size")] #[doc(alias = "gst_tag_list_get_tag_size")]
pub fn size<'a, T: Tag<'a>>(&self) -> u32 { 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 = "get_size_by_name")]
#[doc(alias = "gst_tag_list_get_tag_size")] #[doc(alias = "gst_tag_list_get_tag_size")]
pub fn size_by_name(&self, tag_name: &str) -> u32 { pub fn size_by_name(&self, tag_name: impl IntoGStr) -> u32 {
unsafe { ffi::gst_tag_list_get_tag_size(self.as_ptr(), tag_name.to_glib_none().0) } 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> { pub fn iter_tag<'a, T: Tag<'a>>(&'a self) -> TagIter<'a, T> {
TagIter::new(self) 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) GenericTagIter::new(self, tag_name)
} }
@ -728,13 +728,13 @@ where
#[derive(Debug)] #[derive(Debug)]
pub struct GenericTagIter<'a> { pub struct GenericTagIter<'a> {
taglist: &'a TagListRef, taglist: &'a TagListRef,
name: &'a str, name: &'static glib::GStr,
idx: usize, idx: usize,
size: usize, size: usize,
} }
impl<'a> GenericTagIter<'a> { 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!(); skip_assert_initialized!();
GenericTagIter { GenericTagIter {
taglist, taglist,
@ -850,7 +850,7 @@ impl<'a> GenericIter<'a> {
} }
impl<'a> Iterator for 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<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.size { if self.idx >= self.size {
@ -944,7 +944,7 @@ impl<'a> Iter<'a> {
} }
impl<'a> Iterator for 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<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.size { if self.idx >= self.size {
@ -1019,50 +1019,50 @@ impl<'a> ExactSizeIterator for Iter<'a> {}
impl<'a> std::iter::FusedIterator for Iter<'a> {} impl<'a> std::iter::FusedIterator for Iter<'a> {}
#[doc(alias = "gst_tag_exists")] #[doc(alias = "gst_tag_exists")]
pub fn tag_exists(name: &str) -> bool { pub fn tag_exists(name: impl IntoGStr) -> bool {
skip_assert_initialized!(); 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")] #[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!(); 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")] #[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!(); skip_assert_initialized!();
unsafe { unsafe {
let ptr = ffi::gst_tag_get_nick(name.to_glib_none().0); let ptr = name.run_with_gstr(|name| ffi::gst_tag_get_nick(name.as_ptr()));
CStr::from_ptr(ptr).to_str().unwrap() glib::GStr::from_ptr(ptr)
} }
} }
#[doc(alias = "gst_tag_get_description")] #[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!(); skip_assert_initialized!();
unsafe { 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() { if ptr.is_null() {
None None
} else { } else {
Some(CStr::from_ptr(ptr).to_str().unwrap()) Some(glib::GStr::from_ptr(ptr))
} }
} }
} }
#[doc(alias = "gst_tag_get_flag")] #[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!(); 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> { pub trait CustomTag<'a>: Tag<'a> {
const FLAG: crate::TagFlag; const FLAG: crate::TagFlag;
const NICK: &'static str; const NICK: &'static glib::GStr;
const DESCRIPTION: &'static str; const DESCRIPTION: &'static glib::GStr;
fn merge_func(src: &Value) -> Value { fn merge_func(src: &Value) -> Value {
skip_assert_initialized!(); skip_assert_initialized!();
@ -1072,7 +1072,7 @@ pub trait CustomTag<'a>: Tag<'a> {
#[doc(alias = "gst_tag_register")] #[doc(alias = "gst_tag_register")]
pub fn register<T: for<'a> CustomTag<'a>>() { pub fn register<T: for<'a> CustomTag<'a>>() {
assert!(!tag_exists(T::tag_name())); assert!(!tag_exists(T::TAG_NAME));
unsafe extern "C" fn merge_func_trampoline<T: for<'a> CustomTag<'a>>( unsafe extern "C" fn merge_func_trampoline<T: for<'a> CustomTag<'a>>(
dest: *mut glib::gobject_ffi::GValue, dest: *mut glib::gobject_ffi::GValue,
@ -1083,11 +1083,11 @@ pub fn register<T: for<'a> CustomTag<'a>>() {
unsafe { unsafe {
ffi::gst_tag_register( ffi::gst_tag_register(
T::tag_name().to_glib_none().0, T::TAG_NAME.as_ptr(),
T::FLAG.into_glib(), T::FLAG.into_glib(),
T::TagType::static_type().into_glib(), T::TagType::static_type().into_glib(),
T::NICK.to_glib_none().0, T::NICK.as_ptr(),
T::DESCRIPTION.to_glib_none().0, T::DESCRIPTION.as_ptr(),
Some(merge_func_trampoline::<T>), Some(merge_func_trampoline::<T>),
) )
} }
@ -1186,21 +1186,25 @@ mod tests {
{ {
let tags = tags.get_mut().unwrap(); let tags = tags.get_mut().unwrap();
assert!(tags assert!(tags
.add_generic(&TAG_TITLE, "some title", TagMergeMode::Append) .add_generic(Title::TAG_NAME, "some title", TagMergeMode::Append)
.is_ok()); .is_ok());
assert!(tags assert!(tags
.add_generic(&TAG_TITLE, "second title", TagMergeMode::Append) .add_generic(Title::TAG_NAME, "second title", TagMergeMode::Append)
.is_ok()); .is_ok());
assert!(tags assert!(tags
.add_generic(&TAG_DURATION, ClockTime::SECOND * 120, TagMergeMode::Append) .add_generic(
Duration::TAG_NAME,
ClockTime::SECOND * 120,
TagMergeMode::Append
)
.is_ok()); .is_ok());
assert!(tags assert!(tags
.add_generic(&TAG_TITLE, "third title", TagMergeMode::Append) .add_generic(Title::TAG_NAME, "third title", TagMergeMode::Append)
.is_ok()); .is_ok());
assert_eq!( assert_eq!(
tags.add_generic( tags.add_generic(
&TAG_IMAGE, Image::TAG_NAME,
"`&[str] instead of `Sample`", "`&[str] instead of `Sample`",
TagMergeMode::Append TagMergeMode::Append
), ),
@ -1209,35 +1213,35 @@ mod tests {
} }
assert_eq!( assert_eq!(
tags.index_generic(&TAG_TITLE, 0).unwrap().get(), tags.index_generic(Title::TAG_NAME, 0).unwrap().get(),
Ok(Some("some title")) Ok(Some("some title"))
); );
assert_eq!( assert_eq!(
tags.index_generic(&TAG_TITLE, 1).unwrap().get(), tags.index_generic(Title::TAG_NAME, 1).unwrap().get(),
Ok(Some("second title")) Ok(Some("second title"))
); );
assert_eq!( assert_eq!(
tags.index_generic(&TAG_DURATION, 0).unwrap().get(), tags.index_generic(Duration::TAG_NAME, 0).unwrap().get(),
Ok(Some(ClockTime::SECOND * 120)) Ok(Some(ClockTime::SECOND * 120))
); );
assert_eq!( assert_eq!(
tags.index_generic(&TAG_TITLE, 2).unwrap().get(), tags.index_generic(Title::TAG_NAME, 2).unwrap().get(),
Ok(Some("third title")) Ok(Some("third title"))
); );
assert_eq!( assert_eq!(
tags.generic(&TAG_TITLE).unwrap().get(), tags.generic(Title::TAG_NAME).unwrap().get(),
Ok(Some("some title, second title, third title")) Ok(Some("some title, second title, third title"))
); );
assert_eq!(tags.n_tags(), 2); assert_eq!(tags.n_tags(), 2);
assert_eq!(tags.nth_tag_name(0), Some(*TAG_TITLE)); assert_eq!(tags.nth_tag_name(0), Some(Title::TAG_NAME));
assert_eq!(tags.size_by_name(&TAG_TITLE), 3); assert_eq!(tags.size_by_name(Title::TAG_NAME), 3);
assert_eq!(tags.nth_tag_name(1), Some(*TAG_DURATION)); assert_eq!(tags.nth_tag_name(1), Some(Duration::TAG_NAME));
assert_eq!(tags.size_by_name(&TAG_DURATION), 1); assert_eq!(tags.size_by_name(Duration::TAG_NAME), 1);
// GenericTagIter // 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))); assert_eq!(title_iter.size_hint(), (3, Some(3)));
let first_title = title_iter.next().unwrap(); let first_title = title_iter.next().unwrap();
assert_eq!(first_title.get(), Ok(Some("some title"))); 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))); assert_eq!(tag_list_iter.size_hint(), (2, Some(2)));
let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); 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(); let first_title = tag_iter.next().unwrap();
assert_eq!(first_title.get(), Ok(Some("some title"))); assert_eq!(first_title.get(), Ok(Some("some title")));
let second_title = tag_iter.next().unwrap(); let second_title = tag_iter.next().unwrap();
@ -1262,7 +1266,7 @@ mod tests {
assert!(tag_iter.next().is_none()); assert!(tag_iter.next().is_none());
let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); 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(); let first_duration = tag_iter.next().unwrap();
assert_eq!(first_duration.get(), Ok(Some(ClockTime::SECOND * 120))); assert_eq!(first_duration.get(), Ok(Some(ClockTime::SECOND * 120)));
assert!(tag_iter.next().is_none()); assert!(tag_iter.next().is_none());
@ -1272,14 +1276,14 @@ mod tests {
assert_eq!(tag_list_iter.size_hint(), (2, Some(2))); assert_eq!(tag_list_iter.size_hint(), (2, Some(2)));
let (tag_name, tag_value) = tag_list_iter.next().unwrap(); 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!( assert_eq!(
tag_value.get(), tag_value.get(),
Ok(Some("some title, second title, third title")) Ok(Some("some title, second title, third title"))
); );
let (tag_name, tag_value) = tag_list_iter.next().unwrap(); 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_eq!(tag_value.get(), Ok(Some(ClockTime::SECOND * 120)));
assert!(tag_iter.next().is_none()); assert!(tag_iter.next().is_none());
} }
@ -1292,15 +1296,14 @@ mod tests {
impl<'a> Tag<'a> for MyCustomTag { impl<'a> Tag<'a> for MyCustomTag {
type TagType = &'a str; type TagType = &'a str;
fn tag_name<'b>() -> &'b str { const TAG_NAME: &'static glib::GStr = glib::gstr!("my-custom-tag");
"my-custom-tag"
}
} }
impl<'a> CustomTag<'a> for MyCustomTag { impl<'a> CustomTag<'a> for MyCustomTag {
const FLAG: crate::TagFlag = crate::TagFlag::Meta; const FLAG: crate::TagFlag = crate::TagFlag::Meta;
const NICK: &'static str = "my custom tag"; const NICK: &'static glib::GStr = glib::gstr!("my custom tag");
const DESCRIPTION: &'static str = "My own custom tag type for testing"; const DESCRIPTION: &'static glib::GStr =
glib::gstr!("My own custom tag type for testing");
fn merge_func(src: &Value) -> Value { fn merge_func(src: &Value) -> Value {
skip_assert_initialized!(); skip_assert_initialized!();
@ -1310,17 +1313,17 @@ mod tests {
register::<MyCustomTag>(); register::<MyCustomTag>();
assert!(tag_exists(MyCustomTag::tag_name())); assert!(tag_exists(MyCustomTag::TAG_NAME));
assert_eq!( assert_eq!(
tag_get_type(MyCustomTag::tag_name()), tag_get_type(MyCustomTag::TAG_NAME),
<MyCustomTag as Tag>::TagType::static_type() <MyCustomTag as Tag>::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!( assert_eq!(
tag_get_description(MyCustomTag::tag_name()), tag_get_description(MyCustomTag::TAG_NAME),
Some(MyCustomTag::DESCRIPTION) 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(); let mut tags = TagList::new();
{ {

View file

@ -234,7 +234,7 @@ mod tutorial5 {
None => return, 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 let textbuf = streams_list
.buffer() .buffer()
.expect("Couldn't get buffer from text_view"); .expect("Couldn't get buffer from text_view");