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