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.
let auth = gst_rtsp_server::RTSPAuth::new();
let token = gst_rtsp_server::RTSPToken::new(&[(
*gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE,
gst_rtsp_server::RTSP_TOKEN_MEDIA_FACTORY_ROLE,
&"user",
)]);
let basic = gst_rtsp_server::RTSPAuth::make_basic("user", "password");

View file

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

View file

@ -541,7 +541,7 @@ impl App {
let src = gst::ElementFactory::make("videotestsrc").build()?;
let caps = gst_video::VideoCapsBuilder::new()
.features(&[&gst_gl::CAPS_FEATURE_MEMORY_GL_MEMORY])
.features([gst_gl::CAPS_FEATURE_MEMORY_GL_MEMORY])
.format(gst_video::VideoFormat::Rgba)
.field("texture-target", "2D")
.build();

View file

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

View file

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

View file

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

View file

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

View file

@ -4,4 +4,4 @@ use gst::CapsFeatures;
use once_cell::sync::Lazy;
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
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,
) -> Result<(), glib::BoolError> {
assert_initialized_main_thread!();
let codec_tag = T::tag_name();
let codec_tag = T::TAG_NAME;
unsafe {
glib::result_from_gboolean!(
ffi::gst_pb_utils_add_codec_description_to_tag_list(
taglist.as_mut_ptr(),
codec_tag.to_glib_none().0,
codec_tag.as_ptr(),
caps.as_ptr(),
),
"Failed to find codec description",

View file

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

View file

@ -1,5 +1,6 @@
use std::ops::{Bound::*, RangeBounds};
use glib::IntoGStr;
use gst::Caps;
use crate::VideoFormat;
@ -10,7 +11,7 @@ pub struct VideoCapsBuilder<T> {
impl VideoCapsBuilder<gst::caps::NoFeature> {
pub fn new() -> Self {
let builder = Caps::builder("video/x-raw");
let builder = Caps::builder(glib::gstr!("video/x-raw"));
let builder = VideoCapsBuilder { builder };
builder
.format_list(VideoFormat::iter_raw())
@ -25,7 +26,10 @@ impl VideoCapsBuilder<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 {
builder: self.builder.features(features),
}
@ -41,14 +45,14 @@ impl Default for VideoCapsBuilder<gst::caps::NoFeature> {
impl<T> VideoCapsBuilder<T> {
pub fn format(self, format: VideoFormat) -> Self {
Self {
builder: self.builder.field("format", format.to_str()),
builder: self.builder.field(glib::gstr!("format"), format.to_str()),
}
}
pub fn format_list(self, formats: impl IntoIterator<Item = VideoFormat>) -> Self {
Self {
builder: self.builder.field(
"format",
glib::gstr!("format"),
gst::List::new(formats.into_iter().map(|f| f.to_str())),
),
}
@ -56,7 +60,7 @@ impl<T> VideoCapsBuilder<T> {
pub fn width(self, width: i32) -> Self {
Self {
builder: self.builder.field("width", width),
builder: self.builder.field(glib::gstr!("width"), width),
}
}
@ -64,19 +68,21 @@ impl<T> VideoCapsBuilder<T> {
let (start, end) = range_bounds_i32_start_end(widths);
let gst_widths: gst::IntRange<i32> = gst::IntRange::new(start, end);
Self {
builder: self.builder.field("width", gst_widths),
builder: self.builder.field(glib::gstr!("width"), gst_widths),
}
}
pub fn width_list(self, widths: impl IntoIterator<Item = i32>) -> Self {
Self {
builder: self.builder.field("width", gst::List::new(widths)),
builder: self
.builder
.field(glib::gstr!("width"), gst::List::new(widths)),
}
}
pub fn height(self, height: i32) -> Self {
Self {
builder: self.builder.field("height", height),
builder: self.builder.field(glib::gstr!("height"), height),
}
}
@ -84,19 +90,21 @@ impl<T> VideoCapsBuilder<T> {
let (start, end) = range_bounds_i32_start_end(heights);
let gst_heights: gst::IntRange<i32> = gst::IntRange::new(start, end);
Self {
builder: self.builder.field("height", gst_heights),
builder: self.builder.field(glib::gstr!("height"), gst_heights),
}
}
pub fn height_list(self, heights: impl IntoIterator<Item = i32>) -> Self {
Self {
builder: self.builder.field("height", gst::List::new(heights)),
builder: self
.builder
.field(glib::gstr!("height"), gst::List::new(heights)),
}
}
pub fn framerate(self, framerate: gst::Fraction) -> Self {
Self {
builder: self.builder.field("framerate", framerate),
builder: self.builder.field(glib::gstr!("framerate"), framerate),
}
}
@ -120,13 +128,15 @@ impl<T> VideoCapsBuilder<T> {
assert!(start <= end);
let framerates: gst::FractionRange = gst::FractionRange::new(start, end);
Self {
builder: self.builder.field("framerate", framerates),
builder: self.builder.field(glib::gstr!("framerate"), framerates),
}
}
pub fn framerate_list(self, framerates: impl IntoIterator<Item = gst::Fraction>) -> 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.
use std::ffi::CStr;
use gst::CapsFeatures;
use once_cell::sync::Lazy;
#[cfg(any(feature = "v1_16", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
pub static CAPS_FEATURE_FORMAT_INTERLACED: Lazy<&'static str> = Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_CAPS_FEATURE_FORMAT_INTERLACED)
.to_str()
.unwrap()
});
pub static CAPS_FEATURE_FORMAT_INTERLACED: &glib::GStr =
unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_FORMAT_INTERLACED) };
#[cfg(any(feature = "v1_16", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
pub static CAPS_FEATURES_FORMAT_INTERLACED: Lazy<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> =
Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META)
.to_str()
.unwrap()
});
pub static CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: &glib::GStr = unsafe {
glib::GStr::from_utf8_with_nul_unchecked(
ffi::GST_CAPS_FEATURE_META_GST_VIDEO_AFFINE_TRANSFORMATION_META,
)
};
pub static CAPS_FEATURES_META_GST_VIDEO_AFFINE_TRANSFORMATION_META: Lazy<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> =
Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META)
.to_str()
.unwrap()
});
pub static CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: &glib::GStr = unsafe {
glib::GStr::from_utf8_with_nul_unchecked(
ffi::GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META,
)
};
pub static CAPS_FEATURES_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META: Lazy<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 {
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_META)
.to_str()
.unwrap()
});
pub static CAPS_FEATURE_META_GST_VIDEO_META: &glib::GStr =
unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_META) };
pub static CAPS_FEATURES_META_GST_VIDEO_META: Lazy<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> =
Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION)
.to_str()
.unwrap()
});
pub static CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION: &glib::GStr = unsafe {
glib::GStr::from_utf8_with_nul_unchecked(
ffi::GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
)
};
pub static CAPS_FEATURES_META_GST_VIDEO_OVERLAY_COMPOSITION: Lazy<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.
use std::{ffi::CStr, marker::PhantomData, mem};
use std::{marker::PhantomData, mem};
use glib::translate::*;
use once_cell::sync::Lazy;
pub static BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META: Lazy<&'static str> =
Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META)
.to_str()
.unwrap()
});
pub static BUFFER_POOL_OPTION_VIDEO_ALIGNMENT: Lazy<&'static str> = Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)
.to_str()
.unwrap()
});
pub static BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META: Lazy<&'static str> =
Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META)
.to_str()
.unwrap()
});
pub static BUFFER_POOL_OPTION_VIDEO_META: Lazy<&'static str> = Lazy::new(|| unsafe {
CStr::from_ptr(ffi::GST_BUFFER_POOL_OPTION_VIDEO_META)
.to_str()
.unwrap()
});
pub static BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META: &glib::GStr = unsafe {
glib::GStr::from_utf8_with_nul_unchecked(
ffi::GST_BUFFER_POOL_OPTION_VIDEO_AFFINE_TRANSFORMATION_META,
)
};
pub static BUFFER_POOL_OPTION_VIDEO_ALIGNMENT: &glib::GStr = unsafe {
glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_BUFFER_POOL_OPTION_VIDEO_ALIGNMENT)
};
pub static BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META: &glib::GStr = unsafe {
glib::GStr::from_utf8_with_nul_unchecked(
ffi::GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META,
)
};
pub static BUFFER_POOL_OPTION_VIDEO_META: &glib::GStr =
unsafe { glib::GStr::from_utf8_with_nul_unchecked(ffi::GST_BUFFER_POOL_OPTION_VIDEO_META) };
#[derive(Debug, Clone)]
#[doc(alias = "GstVideoAlignment")]

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -234,7 +234,7 @@ mod tutorial5 {
None => return,
};
if application.structure().map(|s| s.name()) == Some("tags-changed") {
if application.structure().map(|s| s.name().as_str()) == Some("tags-changed") {
let textbuf = streams_list
.buffer()
.expect("Couldn't get buffer from text_view");