1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{fmt, marker::PhantomData, mem};
4
5use glib::{translate::*, StaticType};
6
7use crate::{
8 format::{
9 CompatibleFormattedValue, FormattedValue, FormattedValueFullRange, FormattedValueIntrinsic,
10 FormattedValueNoneBuilder, NoneSignedBuilder, UnsignedIntoSigned,
11 },
12 Format, GenericFormattedValue, SeekFlags, SeekType,
13};
14
15pub type Segment = FormattedSegment<GenericFormattedValue>;
16
17glib::wrapper! {
18 #[doc(alias = "GstSegment")]
19 pub struct FormattedSegment<T: FormattedValueIntrinsic>(BoxedInline<ffi::GstSegment>);
20
21 match fn {
22 copy => |ptr| ffi::gst_segment_copy(ptr),
23 free => |ptr| ffi::gst_segment_free(ptr),
24 init => |_ptr| (),
25 copy_into => |dest, src| { *dest = *src; },
26 clear => |_ptr| (),
27 }
28}
29
30impl Segment {
31 #[inline]
32 pub fn reset_with_format(&mut self, format: Format) {
33 unsafe {
34 ffi::gst_segment_init(self.to_glib_none_mut().0, format.into_glib());
35 }
36 }
37
38 #[inline]
39 pub fn set_format(&mut self, format: Format) {
40 self.inner.format = format.into_glib();
41 }
42
43 #[inline]
44 pub fn downcast<T: FormattedValueIntrinsic>(self) -> Result<FormattedSegment<T>, Self> {
45 if T::default_format() == Format::Undefined || T::default_format() == self.format() {
46 Ok(FormattedSegment {
47 inner: self.inner,
48 phantom: PhantomData,
49 })
50 } else {
51 Err(self)
52 }
53 }
54
55 #[inline]
56 pub fn downcast_ref<T: FormattedValueIntrinsic>(&self) -> Option<&FormattedSegment<T>> {
57 if T::default_format() == Format::Undefined || T::default_format() == self.format() {
58 Some(unsafe {
59 &*(self as *const FormattedSegment<GenericFormattedValue>
60 as *const FormattedSegment<T>)
61 })
62 } else {
63 None
64 }
65 }
66
67 #[inline]
68 pub fn downcast_mut<T: FormattedValueIntrinsic>(&mut self) -> Option<&mut FormattedSegment<T>> {
69 if T::default_format() == Format::Undefined || T::default_format() == self.format() {
70 Some(unsafe {
71 &mut *(self as *mut FormattedSegment<GenericFormattedValue>
72 as *mut FormattedSegment<T>)
73 })
74 } else {
75 None
76 }
77 }
78}
79
80impl<T: FormattedValueIntrinsic> FormattedSegment<T> {
81 #[inline]
82 pub fn new() -> Self {
83 assert_initialized_main_thread!();
84 let segment = unsafe {
85 let mut segment = mem::MaybeUninit::uninit();
86 ffi::gst_segment_init(segment.as_mut_ptr(), T::default_format().into_glib());
87 segment.assume_init()
88 };
89 FormattedSegment {
90 inner: segment,
91 phantom: PhantomData,
92 }
93 }
94
95 #[inline]
96 pub fn upcast(self) -> Segment {
97 FormattedSegment {
98 inner: self.inner,
99 phantom: PhantomData,
100 }
101 }
102
103 #[inline]
104 pub fn upcast_ref(&self) -> &Segment {
105 unsafe {
106 &*(self as *const FormattedSegment<T> as *const FormattedSegment<GenericFormattedValue>)
107 }
108 }
109
110 #[inline]
111 pub fn reset(&mut self) {
112 unsafe {
113 ffi::gst_segment_init(&mut self.inner, T::default_format().into_glib());
114 }
115 }
116
117 #[doc(alias = "gst_segment_clip")]
118 pub fn clip(
119 &self,
120 start: impl CompatibleFormattedValue<T>,
121 stop: impl CompatibleFormattedValue<T>,
122 ) -> Option<(T::FullRange, T::FullRange)> {
123 let start = start.try_into_checked_explicit(self.format()).unwrap();
124 let stop = stop.try_into_checked_explicit(self.format()).unwrap();
125
126 unsafe {
127 let mut clip_start = mem::MaybeUninit::uninit();
128 let mut clip_stop = mem::MaybeUninit::uninit();
129 let ret = from_glib(ffi::gst_segment_clip(
130 &self.inner,
131 start.format().into_glib(),
132 start.into_raw_value() as u64,
133 stop.into_raw_value() as u64,
134 clip_start.as_mut_ptr(),
135 clip_stop.as_mut_ptr(),
136 ));
137 if ret {
138 Some((
139 T::FullRange::from_raw(self.format(), clip_start.assume_init() as i64),
140 T::FullRange::from_raw(self.format(), clip_stop.assume_init() as i64),
141 ))
142 } else {
143 None
144 }
145 }
146 }
147
148 #[allow(clippy::too_many_arguments)]
149 #[doc(alias = "gst_segment_do_seek")]
150 pub fn do_seek(
151 &mut self,
152 rate: f64,
153 flags: SeekFlags,
154 start_type: SeekType,
155 start: impl CompatibleFormattedValue<T>,
156 stop_type: SeekType,
157 stop: impl CompatibleFormattedValue<T>,
158 ) -> Option<bool> {
159 let start = start.try_into_checked_explicit(self.format()).unwrap();
160 let stop = stop.try_into_checked_explicit(self.format()).unwrap();
161
162 unsafe {
163 let mut update = mem::MaybeUninit::uninit();
164 let ret = from_glib(ffi::gst_segment_do_seek(
165 &mut self.inner,
166 rate,
167 self.format().into_glib(),
168 flags.into_glib(),
169 start_type.into_glib(),
170 start.into_raw_value() as u64,
171 stop_type.into_glib(),
172 stop.into_raw_value() as u64,
173 update.as_mut_ptr(),
174 ));
175 if ret {
176 Some(from_glib(update.assume_init()))
177 } else {
178 None
179 }
180 }
181 }
182
183 #[doc(alias = "gst_segment_offset_running_time")]
184 #[inline]
185 pub fn offset_running_time(&mut self, offset: i64) -> Result<(), glib::BoolError> {
186 unsafe {
187 glib::result_from_gboolean!(
188 ffi::gst_segment_offset_running_time(
189 &mut self.inner,
190 self.format().into_glib(),
191 offset,
192 ),
193 "Offset is not in the segment"
194 )
195 }
196 }
197
198 #[doc(alias = "gst_segment_set_running_time")]
199 #[inline]
200 pub fn set_running_time(
201 &mut self,
202 running_time: impl CompatibleFormattedValue<T>,
203 ) -> Result<(), glib::BoolError> {
204 let running_time = running_time
205 .try_into_checked_explicit(self.format())
206 .unwrap();
207
208 unsafe {
209 glib::result_from_gboolean!(
210 ffi::gst_segment_set_running_time(
211 &mut self.inner,
212 self.format().into_glib(),
213 running_time.into_raw_value() as u64,
214 ),
215 "Running time is not in the segment"
216 )
217 }
218 }
219
220 #[doc(alias = "get_flags")]
221 #[inline]
222 pub fn flags(&self) -> crate::SegmentFlags {
223 unsafe { from_glib(self.inner.flags) }
224 }
225
226 #[inline]
227 pub fn set_flags(&mut self, flags: crate::SegmentFlags) {
228 self.inner.flags = flags.into_glib();
229 }
230
231 #[doc(alias = "get_rate")]
232 #[inline]
233 pub fn rate(&self) -> f64 {
234 self.inner.rate
235 }
236
237 #[allow(clippy::float_cmp)]
238 #[inline]
239 pub fn set_rate(&mut self, rate: f64) {
240 assert_ne!(rate, 0.0);
241 self.inner.rate = rate;
242 }
243
244 #[doc(alias = "get_applied_rate")]
245 #[inline]
246 pub fn applied_rate(&self) -> f64 {
247 self.inner.applied_rate
248 }
249
250 #[allow(clippy::float_cmp)]
251 #[inline]
252 pub fn set_applied_rate(&mut self, applied_rate: f64) {
253 assert_ne!(applied_rate, 0.0);
254 self.inner.applied_rate = applied_rate;
255 }
256
257 #[doc(alias = "get_format")]
258 #[inline]
259 pub fn format(&self) -> Format {
260 unsafe { from_glib(self.inner.format) }
261 }
262
263 #[doc(alias = "get_base")]
264 #[inline]
265 pub fn base(&self) -> T::FullRange {
266 unsafe { T::FullRange::from_raw(self.format(), self.inner.base as i64) }
267 }
268
269 #[inline]
270 pub fn set_base(&mut self, base: impl CompatibleFormattedValue<T>) {
271 let base = base.try_into_checked_explicit(self.format()).unwrap();
272 self.inner.base = unsafe { base.into_raw_value() } as u64;
273 }
274
275 #[doc(alias = "get_offset")]
276 #[inline]
277 pub fn offset(&self) -> T::FullRange {
278 unsafe { T::FullRange::from_raw(self.format(), self.inner.offset as i64) }
279 }
280
281 #[inline]
282 pub fn set_offset(&mut self, offset: impl CompatibleFormattedValue<T>) {
283 let offset = offset.try_into_checked_explicit(self.format()).unwrap();
284 self.inner.offset = unsafe { offset.into_raw_value() } as u64;
285 }
286
287 #[doc(alias = "get_start")]
288 #[inline]
289 pub fn start(&self) -> T::FullRange {
290 unsafe { T::FullRange::from_raw(self.format(), self.inner.start as i64) }
291 }
292
293 #[inline]
294 pub fn set_start(&mut self, start: impl CompatibleFormattedValue<T>) {
295 let start = start.try_into_checked_explicit(self.format()).unwrap();
296 self.inner.start = unsafe { start.into_raw_value() } as u64;
297 }
298
299 #[doc(alias = "get_stop")]
300 #[inline]
301 pub fn stop(&self) -> T::FullRange {
302 unsafe { T::FullRange::from_raw(self.format(), self.inner.stop as i64) }
303 }
304
305 #[inline]
306 pub fn set_stop(&mut self, stop: impl CompatibleFormattedValue<T>) {
307 let stop = stop.try_into_checked_explicit(self.format()).unwrap();
308 self.inner.stop = unsafe { stop.into_raw_value() } as u64;
309 }
310
311 #[doc(alias = "get_time")]
312 #[inline]
313 pub fn time(&self) -> T::FullRange {
314 unsafe { T::FullRange::from_raw(self.format(), self.inner.time as i64) }
315 }
316
317 #[inline]
318 pub fn set_time(&mut self, time: impl CompatibleFormattedValue<T>) {
319 let time = time.try_into_checked_explicit(self.format()).unwrap();
320 self.inner.time = unsafe { time.into_raw_value() } as u64;
321 }
322
323 #[doc(alias = "get_position")]
324 #[inline]
325 pub fn position(&self) -> T::FullRange {
326 unsafe { T::FullRange::from_raw(self.format(), self.inner.position as i64) }
327 }
328
329 #[inline]
330 pub fn set_position(&mut self, position: impl CompatibleFormattedValue<T>) {
331 let position = position.try_into_checked_explicit(self.format()).unwrap();
332 self.inner.position = unsafe { position.into_raw_value() } as u64;
333 }
334
335 #[doc(alias = "get_duration")]
336 #[inline]
337 pub fn duration(&self) -> T::FullRange {
338 unsafe { T::FullRange::from_raw(self.format(), self.inner.duration as i64) }
339 }
340
341 #[inline]
342 pub fn set_duration(&mut self, duration: impl CompatibleFormattedValue<T>) {
343 let duration = duration.try_into_checked_explicit(self.format()).unwrap();
344 self.inner.duration = unsafe { duration.into_raw_value() } as u64;
345 }
346}
347
348impl<T: FormattedValueIntrinsic> PartialEq for FormattedSegment<T> {
349 #[inline]
350 #[doc(alias = "gst_segment_is_equal")]
351 fn eq(&self, other: &Self) -> bool {
352 unsafe { from_glib(val:ffi::gst_segment_is_equal(&self.inner, &other.inner)) }
353 }
354}
355
356impl<T> FormattedSegment<T>
357where
358 T: FormattedValueIntrinsic,
359 T::FullRange: FormattedValueNoneBuilder,
360{
361 #[doc(alias = "gst_segment_position_from_running_time")]
362 pub fn position_from_running_time(
363 &self,
364 running_time: impl CompatibleFormattedValue<T>,
365 ) -> T::FullRange {
366 let running_time = running_time
367 .try_into_checked_explicit(self.format())
368 .unwrap();
369 if running_time.is_none() {
370 return T::FullRange::none_for_format(self.format());
371 }
372
373 unsafe {
374 T::FullRange::from_raw(
375 self.format(),
376 ffi::gst_segment_position_from_running_time(
377 &self.inner,
378 self.format().into_glib(),
379 running_time.into_raw_value() as u64,
380 ) as i64,
381 )
382 }
383 }
384
385 #[doc(alias = "gst_segment_position_from_stream_time")]
386 pub fn position_from_stream_time(
387 &self,
388 stream_time: impl CompatibleFormattedValue<T>,
389 ) -> T::FullRange {
390 let stream_time = stream_time
391 .try_into_checked_explicit(self.format())
392 .unwrap();
393 if stream_time.is_none() {
394 return T::FullRange::none_for_format(self.format());
395 }
396
397 unsafe {
398 T::FullRange::from_raw(
399 self.format(),
400 ffi::gst_segment_position_from_stream_time(
401 &self.inner,
402 self.format().into_glib(),
403 stream_time.into_raw_value() as u64,
404 ) as i64,
405 )
406 }
407 }
408
409 #[doc(alias = "gst_segment_to_running_time")]
410 pub fn to_running_time(&self, position: impl CompatibleFormattedValue<T>) -> T::FullRange {
411 let position = position.try_into_checked_explicit(self.format()).unwrap();
412 if position.is_none() {
413 return T::FullRange::none_for_format(self.format());
414 }
415
416 unsafe {
417 T::FullRange::from_raw(
418 self.format(),
419 ffi::gst_segment_to_running_time(
420 &self.inner,
421 self.format().into_glib(),
422 position.into_raw_value() as u64,
423 ) as i64,
424 )
425 }
426 }
427
428 #[doc(alias = "gst_segment_to_stream_time")]
429 pub fn to_stream_time(&self, position: impl CompatibleFormattedValue<T>) -> T::FullRange {
430 let position = position.try_into_checked_explicit(self.format()).unwrap();
431 if position.is_none() {
432 return T::FullRange::none_for_format(self.format());
433 }
434
435 unsafe {
436 T::FullRange::from_raw(
437 self.format(),
438 ffi::gst_segment_to_stream_time(
439 &self.inner,
440 self.format().into_glib(),
441 position.into_raw_value() as u64,
442 ) as i64,
443 )
444 }
445 }
446}
447
448impl<T> FormattedSegment<T>
449where
450 T: FormattedValueIntrinsic,
451 T::FullRange: UnsignedIntoSigned,
452 T::FullRange: NoneSignedBuilder<Signed = <T::FullRange as UnsignedIntoSigned>::Signed>,
453{
454 #[doc(alias = "gst_segment_position_from_running_time_full")]
455 pub fn position_from_running_time_full(
456 &self,
457 running_time: impl CompatibleFormattedValue<T>,
458 ) -> <T::FullRange as UnsignedIntoSigned>::Signed {
459 let running_time = running_time
460 .try_into_checked_explicit(self.format())
461 .unwrap();
462 if running_time.is_none() {
463 return T::FullRange::none_signed_for_format(self.format());
464 }
465
466 unsafe {
467 let mut position = mem::MaybeUninit::uninit();
468 let sign = ffi::gst_segment_position_from_running_time_full(
469 &self.inner,
470 self.format().into_glib(),
471 running_time.into_raw_value() as u64,
472 position.as_mut_ptr(),
473 );
474
475 T::FullRange::from_raw(self.format(), position.assume_init() as i64).into_signed(sign)
476 }
477 }
478
479 #[doc(alias = "gst_segment_position_from_stream_time_full")]
480 pub fn position_from_stream_time_full(
481 &self,
482 stream_time: impl CompatibleFormattedValue<T>,
483 ) -> <T::FullRange as UnsignedIntoSigned>::Signed {
484 let stream_time = stream_time
485 .try_into_checked_explicit(self.format())
486 .unwrap();
487 if stream_time.is_none() {
488 return T::FullRange::none_signed_for_format(self.format());
489 }
490
491 unsafe {
492 let mut position = mem::MaybeUninit::uninit();
493 let sign = ffi::gst_segment_position_from_stream_time_full(
494 &self.inner,
495 self.format().into_glib(),
496 stream_time.into_raw_value() as u64,
497 position.as_mut_ptr(),
498 );
499
500 T::FullRange::from_raw(self.format(), position.assume_init() as i64).into_signed(sign)
501 }
502 }
503
504 #[doc(alias = "gst_segment_to_running_time_full")]
505 pub fn to_running_time_full(
506 &self,
507 position: impl CompatibleFormattedValue<T>,
508 ) -> <T::FullRange as UnsignedIntoSigned>::Signed {
509 let position = position.try_into_checked_explicit(self.format()).unwrap();
510 if position.is_none() {
511 return T::FullRange::none_signed_for_format(self.format());
512 }
513
514 unsafe {
515 let mut running_time = mem::MaybeUninit::uninit();
516 let sign = ffi::gst_segment_to_running_time_full(
517 &self.inner,
518 self.format().into_glib(),
519 position.into_raw_value() as u64,
520 running_time.as_mut_ptr(),
521 );
522
523 T::FullRange::from_raw(self.format(), running_time.assume_init() as i64)
524 .into_signed(sign)
525 }
526 }
527
528 #[doc(alias = "gst_segment_to_stream_time_full")]
529 pub fn to_stream_time_full(
530 &self,
531 position: impl CompatibleFormattedValue<T>,
532 ) -> <T::FullRange as UnsignedIntoSigned>::Signed {
533 let position = position.try_into_checked_explicit(self.format()).unwrap();
534 if position.is_none() {
535 return T::FullRange::none_signed_for_format(self.format());
536 }
537
538 unsafe {
539 let mut stream_time = mem::MaybeUninit::uninit();
540 let sign = ffi::gst_segment_to_stream_time_full(
541 &self.inner,
542 self.format().into_glib(),
543 position.into_raw_value() as u64,
544 stream_time.as_mut_ptr(),
545 );
546
547 T::FullRange::from_raw(self.format(), stream_time.assume_init() as i64)
548 .into_signed(sign)
549 }
550 }
551}
552
553impl<T: FormattedValueIntrinsic> Eq for FormattedSegment<T> {}
554
555unsafe impl<T: FormattedValueIntrinsic> Send for FormattedSegment<T> {}
556unsafe impl<T: FormattedValueIntrinsic> Sync for FormattedSegment<T> {}
557
558impl<T: FormattedValueIntrinsic> AsRef<Segment> for FormattedSegment<T> {
559 #[inline]
560 fn as_ref(&self) -> &Segment {
561 unsafe {
562 &*(self as *const FormattedSegment<T> as *const FormattedSegment<GenericFormattedValue>)
563 }
564 }
565}
566
567impl<T: FormattedValueIntrinsic> fmt::Debug for FormattedSegment<T> {
568 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
569 use crate::utils::Displayable;
570
571 let segment = self.as_ref();
572 match segment.format() {
573 Format::Undefined => f
574 .debug_struct("Segment")
575 .field("format", &Format::Undefined)
576 .finish(),
577 Format::Time => {
578 let segment = segment.downcast_ref::<crate::ClockTime>().unwrap();
579 f.debug_struct("Segment")
580 .field("format", &Format::Time)
581 .field("start", &segment.start().display())
582 .field("offset", &segment.offset().display())
583 .field("stop", &segment.stop().display())
584 .field("rate", &segment.rate())
585 .field("applied_rate", &segment.applied_rate())
586 .field("flags", &segment.flags())
587 .field("time", &segment.time().display())
588 .field("base", &segment.base().display())
589 .field("position", &segment.position().display())
590 .field("duration", &segment.duration().display())
591 .finish()
592 }
593 _ => f
594 .debug_struct("Segment")
595 .field("format", &segment.format())
596 .field("start", &segment.start())
597 .field("offset", &segment.offset())
598 .field("stop", &segment.stop())
599 .field("rate", &segment.rate())
600 .field("applied_rate", &segment.applied_rate())
601 .field("flags", &segment.flags())
602 .field("time", &segment.time())
603 .field("base", &segment.base())
604 .field("position", &segment.position())
605 .field("duration", &segment.duration())
606 .finish(),
607 }
608 }
609}
610
611impl<T: FormattedValueIntrinsic> Default for FormattedSegment<T> {
612 #[inline]
613 fn default() -> Self {
614 Self::new()
615 }
616}
617
618impl<T: FormattedValueIntrinsic> glib::types::StaticType for FormattedSegment<T> {
619 #[inline]
620 fn static_type() -> glib::types::Type {
621 unsafe { glib::translate::from_glib(val:ffi::gst_segment_get_type()) }
622 }
623}
624
625impl glib::value::ValueType for Segment {
626 type Type = Self;
627}
628
629#[doc(hidden)]
630unsafe impl<'a> glib::value::FromValue<'a> for Segment {
631 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
632
633 #[inline]
634 unsafe fn from_value(value: &'a glib::Value) -> Self {
635 skip_assert_initialized!();
636 from_glib_none(
637 ptr:glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstSegment
638 )
639 }
640}
641
642#[doc(hidden)]
643unsafe impl<'a> glib::value::FromValue<'a> for &'a Segment {
644 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
645
646 #[inline]
647 unsafe fn from_value(value: &'a glib::Value) -> Self {
648 skip_assert_initialized!();
649 Segment::from_glib_ptr_borrow(
650 ptr:glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const ffi::GstSegment
651 )
652 }
653}
654
655#[doc(hidden)]
656impl<T: FormattedValueIntrinsic> glib::value::ToValue for FormattedSegment<T> {
657 #[inline]
658 fn to_value(&self) -> glib::Value {
659 let mut value: Value = glib::Value::for_value_type::<Segment>();
660 unsafe {
661 glib::gobject_ffi::g_value_set_boxed(
662 value:value.to_glib_none_mut().0,
663 self.to_glib_none().0 as *mut _,
664 )
665 }
666 value
667 }
668
669 #[inline]
670 fn value_type(&self) -> glib::Type {
671 Self::static_type()
672 }
673}
674
675#[doc(hidden)]
676impl<T: FormattedValueIntrinsic> glib::value::ToValueOptional for FormattedSegment<T> {
677 #[inline]
678 fn to_value_optional(s: Option<&Self>) -> glib::Value {
679 skip_assert_initialized!();
680 let mut value: Value = glib::Value::for_value_type::<Segment>();
681 unsafe {
682 glib::gobject_ffi::g_value_set_boxed(
683 value:value.to_glib_none_mut().0,
684 v_boxed:s.to_glib_none().0 as *mut _,
685 )
686 }
687 value
688 }
689}
690
691impl<T: FormattedValueIntrinsic> From<FormattedSegment<T>> for glib::Value {
692 #[inline]
693 fn from(v: FormattedSegment<T>) -> glib::Value {
694 skip_assert_initialized!();
695 glib::value::ToValue::to_value(&v)
696 }
697}
698