event.rs 45.3 KB
Newer Older
Sebastian Dröge's avatar
Sebastian Dröge committed
1 2 3 4 5 6 7 8 9 10 11
// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ffi;
use miniobject::*;
use structure::*;
12
use GenericFormattedValue;
Sebastian Dröge's avatar
Sebastian Dröge committed
13 14 15

use std::ptr;
use std::mem;
16
use std::cmp;
17
use std::fmt;
Sebastian Dröge's avatar
Sebastian Dröge committed
18
use std::ffi::CStr;
19
use std::ops::Deref;
Sebastian Dröge's avatar
Sebastian Dröge committed
20 21

use glib;
22
use glib::value::ToSendValue;
23
use glib::translate::{from_glib, from_glib_full, FromGlib, ToGlib, ToGlibPtr};
24

25
#[cfg(any(feature = "v1_10", feature = "dox"))]
26
use glib::translate::FromGlibPtrContainer;
Sebastian Dröge's avatar
Sebastian Dröge committed
27

28 29
use EventType;

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Seqnum(pub u32);
pub const SEQNUM_INVALID: Seqnum = Seqnum(0);

impl ToGlib for Seqnum {
    type GlibType = u32;

    fn to_glib(&self) -> u32 {
        self.0
    }
}

impl FromGlib<u32> for Seqnum {
    fn from_glib(val: u32) -> Seqnum {
        skip_assert_initialized!();
        Seqnum(val)
    }
}

impl Into<u32> for Seqnum {
    fn into(self) -> u32 {
        self.0
    }
}

impl From<u32> for Seqnum {
    fn from(v: u32) -> Seqnum {
        Seqnum(v)
    }
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct GroupId(pub u32);
pub const GROUP_ID_INVALID: GroupId = GroupId(0);

impl ToGlib for GroupId {
    type GlibType = u32;

    fn to_glib(&self) -> u32 {
        self.0
    }
}

impl Into<u32> for GroupId {
    fn into(self) -> u32 {
        self.0
    }
}

impl From<u32> for GroupId {
    fn from(v: u32) -> GroupId {
        GroupId(v)
    }
}

impl FromGlib<u32> for GroupId {
    fn from_glib(val: u32) -> GroupId {
        skip_assert_initialized!();
        GroupId(val)
    }
}

Sebastian Dröge's avatar
Sebastian Dröge committed
92 93 94 95 96
#[repr(C)]
pub struct EventRef(ffi::GstEvent);

pub type Event = GstRc<EventRef>;

97 98 99
unsafe impl Sync for EventRef {}
unsafe impl Send for EventRef {}

Sebastian Dröge's avatar
Sebastian Dröge committed
100 101 102 103
unsafe impl MiniObject for EventRef {
    type GstType = ffi::GstEvent;
}

104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
impl EventType {
    pub fn is_upstream(&self) -> bool {
        (self.to_glib() as u32) & (ffi::GST_EVENT_TYPE_UPSTREAM.bits()) != 0
    }

    pub fn is_downstream(&self) -> bool {
        (self.to_glib() as u32) & (ffi::GST_EVENT_TYPE_DOWNSTREAM.bits()) != 0
    }

    pub fn is_serialized(&self) -> bool {
        (self.to_glib() as u32) & (ffi::GST_EVENT_TYPE_SERIALIZED.bits()) != 0
    }

    pub fn is_sticky(&self) -> bool {
        (self.to_glib() as u32) & (ffi::GST_EVENT_TYPE_STICKY.bits()) != 0
    }

    pub fn is_sticky_multi(&self) -> bool {
        (self.to_glib() as u32) & (ffi::GST_EVENT_TYPE_STICKY_MULTI.bits()) != 0
    }
}

impl PartialOrd for EventType {
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        if !self.is_serialized() || !other.is_serialized() {
            return None;
        }

        let v1 = self.to_glib() as u32;
        let v2 = other.to_glib() as u32;

        let stream_start = ffi::GST_EVENT_STREAM_START as u32;
        let segment = ffi::GST_EVENT_SEGMENT as u32;
        let eos = ffi::GST_EVENT_EOS as u32;

        // Strictly ordered range between stream_start and segment,
        // and EOS is bigger than everything else
        if v1 >= stream_start && v1 <= segment || v2 >= stream_start && v2 <= segment {
            Some(v1.cmp(&v2))
        // If one is EOS, the other is definitely less or equal
        } else if v1 == eos || v2 == eos {
            if v1 == v2 {
                Some(cmp::Ordering::Equal)
            } else if v1 == eos {
                Some(cmp::Ordering::Greater)
            } else {
                Some(cmp::Ordering::Less)
            }
        } else {
            None
        }
    }
}

Sebastian Dröge's avatar
Sebastian Dröge committed
158
impl EventRef {
159 160
    pub fn get_seqnum(&self) -> Seqnum {
        unsafe { from_glib(ffi::gst_event_get_seqnum(self.as_mut_ptr())) }
Sebastian Dröge's avatar
Sebastian Dröge committed
161 162 163 164 165 166
    }

    pub fn get_running_time_offset(&self) -> i64 {
        unsafe { ffi::gst_event_get_running_time_offset(self.as_mut_ptr()) }
    }

167 168 169
    pub fn set_running_time_offset(&mut self, offset: i64) {
        unsafe { ffi::gst_event_set_running_time_offset(self.as_mut_ptr(), offset) }
    }
Sebastian Dröge's avatar
Sebastian Dröge committed
170

171
    pub fn get_structure(&self) -> Option<&StructureRef> {
Sebastian Dröge's avatar
Sebastian Dröge committed
172 173
        unsafe {
            let structure = ffi::gst_event_get_structure(self.as_mut_ptr());
174 175 176 177 178
            if structure.is_null() {
                None
            } else {
                Some(StructureRef::from_glib_borrow(structure))
            }
Sebastian Dröge's avatar
Sebastian Dröge committed
179 180 181 182
        }
    }

    pub fn is_upstream(&self) -> bool {
183
        self.get_type().is_upstream()
Sebastian Dröge's avatar
Sebastian Dröge committed
184 185 186
    }

    pub fn is_downstream(&self) -> bool {
187
        self.get_type().is_downstream()
Sebastian Dröge's avatar
Sebastian Dröge committed
188 189 190
    }

    pub fn is_serialized(&self) -> bool {
191
        self.get_type().is_serialized()
Sebastian Dröge's avatar
Sebastian Dröge committed
192 193 194
    }

    pub fn is_sticky(&self) -> bool {
195
        self.get_type().is_sticky()
Sebastian Dröge's avatar
Sebastian Dröge committed
196 197 198
    }

    pub fn is_sticky_multi(&self) -> bool {
199 200 201 202 203
        self.get_type().is_sticky_multi()
    }

    pub fn get_type(&self) -> EventType {
        unsafe { from_glib((*self.as_ptr()).type_) }
Sebastian Dröge's avatar
Sebastian Dröge committed
204 205 206 207 208
    }

    pub fn view(&self) -> EventView {
        let type_ = unsafe { (*self.as_ptr()).type_ };

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
        match type_ {
            ffi::GST_EVENT_FLUSH_START => EventView::FlushStart(FlushStart(self)),
            ffi::GST_EVENT_FLUSH_STOP => EventView::FlushStop(FlushStop(self)),
            ffi::GST_EVENT_STREAM_START => EventView::StreamStart(StreamStart(self)),
            ffi::GST_EVENT_CAPS => EventView::Caps(Caps(self)),
            ffi::GST_EVENT_SEGMENT => EventView::Segment(Segment(self)),
            ffi::GST_EVENT_STREAM_COLLECTION => EventView::StreamCollection(StreamCollection(self)),
            ffi::GST_EVENT_TAG => EventView::Tag(Tag(self)),
            ffi::GST_EVENT_BUFFERSIZE => EventView::BufferSize(BufferSize(self)),
            ffi::GST_EVENT_SINK_MESSAGE => EventView::SinkMessage(SinkMessage(self)),
            ffi::GST_EVENT_STREAM_GROUP_DONE => EventView::StreamGroupDone(StreamGroupDone(self)),
            ffi::GST_EVENT_EOS => EventView::Eos(Eos(self)),
            ffi::GST_EVENT_TOC => EventView::Toc(Toc(self)),
            ffi::GST_EVENT_PROTECTION => EventView::Protection(Protection(self)),
            ffi::GST_EVENT_SEGMENT_DONE => EventView::SegmentDone(SegmentDone(self)),
            ffi::GST_EVENT_GAP => EventView::Gap(Gap(self)),
            ffi::GST_EVENT_QOS => EventView::Qos(Qos(self)),
            ffi::GST_EVENT_SEEK => EventView::Seek(Seek(self)),
            ffi::GST_EVENT_NAVIGATION => EventView::Navigation(Navigation(self)),
            ffi::GST_EVENT_LATENCY => EventView::Latency(Latency(self)),
            ffi::GST_EVENT_STEP => EventView::Step(Step(self)),
            ffi::GST_EVENT_RECONFIGURE => EventView::Reconfigure(Reconfigure(self)),
            ffi::GST_EVENT_TOC_SELECT => EventView::TocSelect(TocSelect(self)),
            ffi::GST_EVENT_SELECT_STREAMS => EventView::SelectStreams(SelectStreams(self)),
            ffi::GST_EVENT_CUSTOM_UPSTREAM => EventView::CustomUpstream(CustomUpstream(self)),
            ffi::GST_EVENT_CUSTOM_DOWNSTREAM => EventView::CustomDownstream(CustomDownstream(self)),
            ffi::GST_EVENT_CUSTOM_DOWNSTREAM_OOB => {
                EventView::CustomDownstreamOob(CustomDownstreamOob(self))
            }
            ffi::GST_EVENT_CUSTOM_DOWNSTREAM_STICKY => {
                EventView::CustomDownstreamSticky(CustomDownstreamSticky(self))
            }
            ffi::GST_EVENT_CUSTOM_BOTH => EventView::CustomBoth(CustomBoth(self)),
            ffi::GST_EVENT_CUSTOM_BOTH_OOB => EventView::CustomBothOob(CustomBothOob(self)),
            _ => EventView::Other,
Sebastian Dröge's avatar
Sebastian Dröge committed
244 245
        }
    }
246
}
Sebastian Dröge's avatar
Sebastian Dröge committed
247

248
impl GstRc<EventRef> {
249
    pub fn new_flush_start<'a>() -> FlushStartBuilder<'a> {
250
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
251 252 253
        FlushStartBuilder::new()
    }

254
    pub fn new_flush_stop<'a>(reset_time: bool) -> FlushStopBuilder<'a> {
255
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
256 257 258
        FlushStopBuilder::new(reset_time)
    }

Sebastian Dröge's avatar
Sebastian Dröge committed
259
    pub fn new_stream_start(stream_id: &str) -> StreamStartBuilder {
260
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
261 262 263
        StreamStartBuilder::new(stream_id)
    }

Sebastian Dröge's avatar
Sebastian Dröge committed
264
    pub fn new_caps(caps: &::Caps) -> CapsBuilder {
265
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
266 267 268
        CapsBuilder::new(caps)
    }

269
    pub fn new_segment<F: ::FormattedValue>(segment: &::FormattedSegment<F>) -> SegmentBuilder {
270
        assert_initialized_main_thread!();
271
        SegmentBuilder::new(segment.as_ref())
Sebastian Dröge's avatar
Sebastian Dröge committed
272 273
    }

274
    #[cfg(any(feature = "v1_10", feature = "dox"))]
275 276 277
    pub fn new_stream_collection(
        stream_collection: &::StreamCollection,
    ) -> StreamCollectionBuilder {
278
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
279 280 281
        StreamCollectionBuilder::new(stream_collection)
    }

282
    pub fn new_tag<'a>(tags: ::TagList) -> TagBuilder<'a> {
283
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
284 285 286
        TagBuilder::new(tags)
    }

287
    pub fn new_buffer_size<'a, V: Into<GenericFormattedValue>>(
288 289
        minsize: V,
        maxsize: V,
290
        async: bool,
291
    ) -> BufferSizeBuilder<'a> {
292
        assert_initialized_main_thread!();
293 294
        let minsize = minsize.into();
        let maxsize = maxsize.into();
295
        assert_eq!(minsize.get_format(), maxsize.get_format());
296 297

        BufferSizeBuilder::new(minsize, maxsize, async)
Sebastian Dröge's avatar
Sebastian Dröge committed
298 299 300
    }

    pub fn new_sink_message<'a>(name: &'a str, msg: &'a ::Message) -> SinkMessageBuilder<'a> {
301
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
302 303 304
        SinkMessageBuilder::new(name, msg)
    }

305
    #[cfg(any(feature = "v1_10", feature = "dox"))]
306
    pub fn new_stream_group_done<'a>(group_id: GroupId) -> StreamGroupDoneBuilder<'a> {
307
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
308 309 310
        StreamGroupDoneBuilder::new(group_id)
    }

311
    pub fn new_eos<'a>() -> EosBuilder<'a> {
312
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
313 314 315
        EosBuilder::new()
    }

Sebastian Dröge's avatar
Sebastian Dröge committed
316
    pub fn new_toc(toc: &::Toc, updated: bool) -> TocBuilder {
317
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
318 319 320
        TocBuilder::new(toc, updated)
    }

321
    pub fn new_protection<'a>(system_id: &'a str, data: &'a ::Buffer) -> ProtectionBuilder<'a> {
322
        assert_initialized_main_thread!();
323
        ProtectionBuilder::new(system_id, data)
Sebastian Dröge's avatar
Sebastian Dröge committed
324 325
    }

326 327 328
    pub fn new_segment_done<'a, V: Into<GenericFormattedValue>>(
        position: V,
    ) -> SegmentDoneBuilder<'a> {
329
        assert_initialized_main_thread!();
330 331
        let position = position.into();
        SegmentDoneBuilder::new(position)
Sebastian Dröge's avatar
Sebastian Dröge committed
332 333
    }

334
    pub fn new_gap<'a>(timestamp: ::ClockTime, duration: ::ClockTime) -> GapBuilder<'a> {
335
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
336 337 338
        GapBuilder::new(timestamp, duration)
    }

339 340 341 342
    pub fn new_qos<'a>(
        type_: ::QOSType,
        proportion: f64,
        diff: i64,
343
        timestamp: ::ClockTime,
344
    ) -> QosBuilder<'a> {
345
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
346 347 348
        QosBuilder::new(type_, proportion, diff, timestamp)
    }

349
    pub fn new_seek<'a, V: Into<GenericFormattedValue>>(
350 351 352
        rate: f64,
        flags: ::SeekFlags,
        start_type: ::SeekType,
353
        start: V,
354
        stop_type: ::SeekType,
355
        stop: V,
356
    ) -> SeekBuilder<'a> {
357
        assert_initialized_main_thread!();
358 359
        let start = start.into();
        let stop = stop.into();
360
        assert_eq!(start.get_format(), stop.get_format());
361 362

        SeekBuilder::new(rate, flags, start_type, start, stop_type, stop)
Sebastian Dröge's avatar
Sebastian Dröge committed
363 364
    }

365
    pub fn new_navigation<'a>(structure: ::Structure) -> NavigationBuilder<'a> {
366
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
367 368 369
        NavigationBuilder::new(structure)
    }

370
    pub fn new_latency<'a>(latency: ::ClockTime) -> LatencyBuilder<'a> {
371
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
372 373 374
        LatencyBuilder::new(latency)
    }

375
    pub fn new_step<'a, V: Into<GenericFormattedValue>>(
376
        amount: V,
377 378 379
        rate: f64,
        flush: bool,
        intermediate: bool,
380
    ) -> StepBuilder<'a> {
381
        assert_initialized_main_thread!();
382
        StepBuilder::new(amount.into(), rate, flush, intermediate)
Sebastian Dröge's avatar
Sebastian Dröge committed
383 384
    }

385
    pub fn new_reconfigure<'a>() -> ReconfigureBuilder<'a> {
386
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
387 388 389
        ReconfigureBuilder::new()
    }

Sebastian Dröge's avatar
Sebastian Dröge committed
390
    pub fn new_toc_select(uid: &str) -> TocSelectBuilder {
391
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
392 393 394
        TocSelectBuilder::new(uid)
    }

395
    #[cfg(any(feature = "v1_10", feature = "dox"))]
Sebastian Dröge's avatar
Sebastian Dröge committed
396
    pub fn new_select_streams<'a>(streams: &'a [&'a str]) -> SelectStreamsBuilder<'a> {
397
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
398 399 400
        SelectStreamsBuilder::new(streams)
    }

401
    pub fn new_custom_upstream<'a>(structure: ::Structure) -> CustomUpstreamBuilder<'a> {
402
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
403 404 405
        CustomUpstreamBuilder::new(structure)
    }

406
    pub fn new_custom_downstream<'a>(structure: ::Structure) -> CustomDownstreamBuilder<'a> {
407
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
408 409 410
        CustomDownstreamBuilder::new(structure)
    }

411
    pub fn new_custom_downstream_oob<'a>(structure: ::Structure) -> CustomDownstreamOobBuilder<'a> {
412
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
413 414 415
        CustomDownstreamOobBuilder::new(structure)
    }

416 417 418
    pub fn new_custom_downstream_sticky<'a>(
        structure: ::Structure,
    ) -> CustomDownstreamStickyBuilder<'a> {
419
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
420 421 422
        CustomDownstreamStickyBuilder::new(structure)
    }

423
    pub fn new_custom_both<'a>(structure: ::Structure) -> CustomBothBuilder<'a> {
424
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
425 426 427
        CustomBothBuilder::new(structure)
    }

428
    pub fn new_custom_both_oob<'a>(structure: ::Structure) -> CustomBothOobBuilder<'a> {
429
        assert_initialized_main_thread!();
Sebastian Dröge's avatar
Sebastian Dröge committed
430 431 432 433
        CustomBothOobBuilder::new(structure)
    }
}

434
impl glib::types::StaticType for EventRef {
Sebastian Dröge's avatar
Sebastian Dröge committed
435 436 437 438 439
    fn static_type() -> glib::types::Type {
        unsafe { from_glib(ffi::gst_event_get_type()) }
    }
}

440 441 442
impl fmt::Debug for EventRef {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Event")
443
            .field("type", &unsafe {
444 445 446 447 448 449 450 451 452
                let type_ = ffi::gst_event_type_get_name((*self.as_ptr()).type_);
                CStr::from_ptr(type_).to_str().unwrap()
            })
            .field("seqnum", &self.get_seqnum())
            .field("structure", &self.get_structure())
            .finish()
    }
}

453 454 455 456 457 458 459 460 461 462 463
impl ToOwned for EventRef {
    type Owned = GstRc<EventRef>;

    fn to_owned(&self) -> GstRc<EventRef> {
        unsafe {
            from_glib_full(ffi::gst_mini_object_copy(self.as_ptr() as *const _)
                as *mut _)
        }
    }
}

Sebastian Dröge's avatar
Sebastian Dröge committed
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
pub enum EventView<'a> {
    FlushStart(FlushStart<'a>),
    FlushStop(FlushStop<'a>),
    StreamStart(StreamStart<'a>),
    Caps(Caps<'a>),
    Segment(Segment<'a>),
    StreamCollection(StreamCollection<'a>),
    Tag(Tag<'a>),
    BufferSize(BufferSize<'a>),
    SinkMessage(SinkMessage<'a>),
    StreamGroupDone(StreamGroupDone<'a>),
    Eos(Eos<'a>),
    Toc(Toc<'a>),
    Protection(Protection<'a>),
    SegmentDone(SegmentDone<'a>),
    Gap(Gap<'a>),
    Qos(Qos<'a>),
    Seek(Seek<'a>),
    Navigation(Navigation<'a>),
    Latency(Latency<'a>),
    Step(Step<'a>),
    Reconfigure(Reconfigure<'a>),
    TocSelect(TocSelect<'a>),
    SelectStreams(SelectStreams<'a>),
    CustomUpstream(CustomUpstream<'a>),
    CustomDownstream(CustomDownstream<'a>),
    CustomDownstreamOob(CustomDownstreamOob<'a>),
    CustomDownstreamSticky(CustomDownstreamSticky<'a>),
    CustomBoth(CustomBoth<'a>),
    CustomBothOob(CustomBothOob<'a>),
    Other,
    __NonExhaustive,
}

498 499 500
macro_rules! declare_concrete_event(
    ($name:ident) => {
        pub struct $name<'a>(&'a EventRef);
Sebastian Dröge's avatar
Sebastian Dröge committed
501

502 503 504 505 506 507 508 509 510 511 512 513 514
        impl<'a> Deref for $name<'a> {
            type Target = EventRef;

            fn deref(&self) -> &Self::Target {
                self.0
            }
        }
    }
);

declare_concrete_event!(FlushStart);

declare_concrete_event!(FlushStop);
Sebastian Dröge's avatar
Sebastian Dröge committed
515 516 517 518 519
impl<'a> FlushStop<'a> {
    pub fn get_reset_time(&self) -> bool {
        unsafe {
            let mut reset_time = mem::uninitialized();

520
            ffi::gst_event_parse_flush_stop(self.as_mut_ptr(), &mut reset_time);
Sebastian Dröge's avatar
Sebastian Dröge committed
521 522 523 524 525 526

            from_glib(reset_time)
        }
    }
}

527
declare_concrete_event!(StreamStart);
Sebastian Dröge's avatar
Sebastian Dröge committed
528
impl<'a> StreamStart<'a> {
529
    pub fn get_stream_id(&self) -> &'a str {
Sebastian Dröge's avatar
Sebastian Dröge committed
530 531 532
        unsafe {
            let mut stream_id = ptr::null();

533
            ffi::gst_event_parse_stream_start(self.as_mut_ptr(), &mut stream_id);
534
            CStr::from_ptr(stream_id).to_str().unwrap()
Sebastian Dröge's avatar
Sebastian Dröge committed
535 536 537 538 539 540 541
        }
    }

    pub fn get_stream_flags(&self) -> ::StreamFlags {
        unsafe {
            let mut stream_flags = mem::uninitialized();

542
            ffi::gst_event_parse_stream_flags(self.as_mut_ptr(), &mut stream_flags);
Sebastian Dröge's avatar
Sebastian Dröge committed
543 544 545 546 547

            from_glib(stream_flags)
        }
    }

548
    pub fn get_group_id(&self) -> GroupId {
Sebastian Dröge's avatar
Sebastian Dröge committed
549 550 551
        unsafe {
            let mut group_id = mem::uninitialized();

552
            ffi::gst_event_parse_group_id(self.as_mut_ptr(), &mut group_id);
Sebastian Dröge's avatar
Sebastian Dröge committed
553

554
            from_glib(group_id)
Sebastian Dröge's avatar
Sebastian Dröge committed
555 556 557 558
        }
    }
}

559
declare_concrete_event!(Caps);
Sebastian Dröge's avatar
Sebastian Dröge committed
560 561 562 563 564
impl<'a> Caps<'a> {
    pub fn get_caps(&self) -> &'a ::CapsRef {
        unsafe {
            let mut caps = ptr::null_mut();

565
            ffi::gst_event_parse_caps(self.as_mut_ptr(), &mut caps);
Sebastian Dröge's avatar
Sebastian Dröge committed
566 567 568 569 570
            ::CapsRef::from_ptr(caps)
        }
    }
}

571
declare_concrete_event!(Segment);
Sebastian Dröge's avatar
Sebastian Dröge committed
572
impl<'a> Segment<'a> {
573
    pub fn get_segment(&self) -> &'a ::Segment {
Sebastian Dröge's avatar
Sebastian Dröge committed
574 575 576
        unsafe {
            let mut segment = ptr::null();

577
            ffi::gst_event_parse_segment(self.as_mut_ptr(), &mut segment);
578
            &*(segment as *mut ffi::GstSegment as *mut ::Segment)
Sebastian Dröge's avatar
Sebastian Dröge committed
579 580 581 582
        }
    }
}

583
declare_concrete_event!(StreamCollection);
Sebastian Dröge's avatar
Sebastian Dröge committed
584
impl<'a> StreamCollection<'a> {
585
    #[cfg(any(feature = "v1_10", feature = "dox"))]
Sebastian Dröge's avatar
Sebastian Dröge committed
586 587 588 589
    pub fn get_stream_collection(&self) -> ::StreamCollection {
        unsafe {
            let mut stream_collection = ptr::null_mut();

590
            ffi::gst_event_parse_stream_collection(self.as_mut_ptr(), &mut stream_collection);
Sebastian Dröge's avatar
Sebastian Dröge committed
591 592 593 594 595
            from_glib_full(stream_collection)
        }
    }
}

596
declare_concrete_event!(Tag);
Sebastian Dröge's avatar
Sebastian Dröge committed
597 598 599 600 601
impl<'a> Tag<'a> {
    pub fn get_tag(&self) -> &'a ::TagListRef {
        unsafe {
            let mut tags = ptr::null_mut();

602
            ffi::gst_event_parse_tag(self.as_mut_ptr(), &mut tags);
Sebastian Dröge's avatar
Sebastian Dröge committed
603 604 605 606 607
            ::TagListRef::from_ptr(tags)
        }
    }
}

608
declare_concrete_event!(BufferSize);
Sebastian Dröge's avatar
Sebastian Dröge committed
609
impl<'a> BufferSize<'a> {
610
    pub fn get(&self) -> (GenericFormattedValue, GenericFormattedValue, bool) {
Sebastian Dröge's avatar
Sebastian Dröge committed
611 612 613 614 615 616
        unsafe {
            let mut fmt = mem::uninitialized();
            let mut minsize = mem::uninitialized();
            let mut maxsize = mem::uninitialized();
            let mut async = mem::uninitialized();

617
            ffi::gst_event_parse_buffer_size(
618
                self.as_mut_ptr(),
619 620 621 622 623
                &mut fmt,
                &mut minsize,
                &mut maxsize,
                &mut async,
            );
624
            (
625 626
                GenericFormattedValue::new(from_glib(fmt), minsize),
                GenericFormattedValue::new(from_glib(fmt), maxsize),
627 628
                from_glib(async),
            )
Sebastian Dröge's avatar
Sebastian Dröge committed
629 630 631 632
        }
    }
}

633
declare_concrete_event!(SinkMessage);
Sebastian Dröge's avatar
Sebastian Dröge committed
634 635 636 637 638
impl<'a> SinkMessage<'a> {
    pub fn get_message(&self) -> ::Message {
        unsafe {
            let mut msg = ptr::null_mut();

639
            ffi::gst_event_parse_sink_message(self.as_mut_ptr(), &mut msg);
Sebastian Dröge's avatar
Sebastian Dröge committed
640 641 642 643 644
            from_glib_full(msg)
        }
    }
}

645
declare_concrete_event!(StreamGroupDone);
Sebastian Dröge's avatar
Sebastian Dröge committed
646
impl<'a> StreamGroupDone<'a> {
647
    #[cfg(any(feature = "v1_10", feature = "dox"))]
648
    pub fn get_group_id(&self) -> GroupId {
Sebastian Dröge's avatar
Sebastian Dröge committed
649 650 651
        unsafe {
            let mut group_id = mem::uninitialized();

652
            ffi::gst_event_parse_stream_group_done(self.as_mut_ptr(), &mut group_id);
Sebastian Dröge's avatar
Sebastian Dröge committed
653

654
            from_glib(group_id)
Sebastian Dröge's avatar
Sebastian Dröge committed
655 656 657 658
        }
    }
}

659
declare_concrete_event!(Eos);
Sebastian Dröge's avatar
Sebastian Dröge committed
660

661
declare_concrete_event!(Toc);
662 663 664 665 666 667
impl<'a> Toc<'a> {
    pub fn get_toc(&self) -> (&'a ::TocRef, bool) {
        unsafe {
            let mut toc = ptr::null_mut();
            let mut updated = mem::uninitialized();

668
            ffi::gst_event_parse_toc(self.as_mut_ptr(), &mut toc, &mut updated);
669 670 671 672
            (::TocRef::from_ptr(toc), from_glib(updated))
        }
    }
}
Sebastian Dröge's avatar
Sebastian Dröge committed
673

674
declare_concrete_event!(Protection);
Sebastian Dröge's avatar
Sebastian Dröge committed
675
impl<'a> Protection<'a> {
676
    pub fn get(&self) -> (&'a str, &'a ::BufferRef, Option<&'a str>) {
Sebastian Dröge's avatar
Sebastian Dröge committed
677 678 679 680 681
        unsafe {
            let mut system_id = ptr::null();
            let mut buffer = ptr::null_mut();
            let mut origin = ptr::null();

682
            ffi::gst_event_parse_protection(
683
                self.as_mut_ptr(),
684 685 686 687 688 689 690 691
                &mut system_id,
                &mut buffer,
                &mut origin,
            );

            (
                CStr::from_ptr(system_id).to_str().unwrap(),
                ::BufferRef::from_ptr(buffer),
692 693 694 695 696
                if origin.is_null() {
                    None
                } else {
                    Some(CStr::from_ptr(origin).to_str().unwrap())
                },
697
            )
Sebastian Dröge's avatar
Sebastian Dröge committed
698 699 700 701
        }
    }
}

702
declare_concrete_event!(SegmentDone);
Sebastian Dröge's avatar
Sebastian Dröge committed
703
impl<'a> SegmentDone<'a> {
704
    pub fn get(&self) -> GenericFormattedValue {
Sebastian Dröge's avatar
Sebastian Dröge committed
705 706 707 708
        unsafe {
            let mut fmt = mem::uninitialized();
            let mut position = mem::uninitialized();

709
            ffi::gst_event_parse_segment_done(self.as_mut_ptr(), &mut fmt, &mut position);
Sebastian Dröge's avatar
Sebastian Dröge committed
710

711
            GenericFormattedValue::new(from_glib(fmt), position)
Sebastian Dröge's avatar
Sebastian Dröge committed
712 713 714 715
        }
    }
}

716
declare_concrete_event!(Gap);
Sebastian Dröge's avatar
Sebastian Dröge committed
717
impl<'a> Gap<'a> {
718
    pub fn get(&self) -> (::ClockTime, ::ClockTime) {
Sebastian Dröge's avatar
Sebastian Dröge committed
719 720 721 722
        unsafe {
            let mut timestamp = mem::uninitialized();
            let mut duration = mem::uninitialized();

723
            ffi::gst_event_parse_gap(self.as_mut_ptr(), &mut timestamp, &mut duration);
Sebastian Dröge's avatar
Sebastian Dröge committed
724

725
            (from_glib(timestamp), from_glib(duration))
Sebastian Dröge's avatar
Sebastian Dröge committed
726 727 728 729
        }
    }
}

730
declare_concrete_event!(Qos);
Sebastian Dröge's avatar
Sebastian Dröge committed
731
impl<'a> Qos<'a> {
732
    pub fn get(&self) -> (::QOSType, f64, i64, ::ClockTime) {
Sebastian Dröge's avatar
Sebastian Dröge committed
733 734 735 736 737 738
        unsafe {
            let mut type_ = mem::uninitialized();
            let mut proportion = mem::uninitialized();
            let mut diff = mem::uninitialized();
            let mut timestamp = mem::uninitialized();

739
            ffi::gst_event_parse_qos(
740
                self.as_mut_ptr(),
741 742 743 744 745
                &mut type_,
                &mut proportion,
                &mut diff,
                &mut timestamp,
            );
Sebastian Dröge's avatar
Sebastian Dröge committed
746

747
            (from_glib(type_), proportion, diff, from_glib(timestamp))
Sebastian Dröge's avatar
Sebastian Dröge committed
748 749 750 751
        }
    }
}

752
declare_concrete_event!(Seek);
Sebastian Dröge's avatar
Sebastian Dröge committed
753
impl<'a> Seek<'a> {
754 755 756 757 758 759
    pub fn get(
        &self,
    ) -> (
        f64,
        ::SeekFlags,
        ::SeekType,
760
        GenericFormattedValue,
761
        ::SeekType,
762
        GenericFormattedValue,
763
    ) {
Sebastian Dröge's avatar
Sebastian Dröge committed
764 765 766 767 768 769 770 771 772
        unsafe {
            let mut rate = mem::uninitialized();
            let mut fmt = mem::uninitialized();
            let mut flags = mem::uninitialized();
            let mut start_type = mem::uninitialized();
            let mut start = mem::uninitialized();
            let mut stop_type = mem::uninitialized();
            let mut stop = mem::uninitialized();

773
            ffi::gst_event_parse_seek(
774
                self.as_mut_ptr(),
775 776 777 778 779 780 781 782 783 784 785 786 787
                &mut rate,
                &mut fmt,
                &mut flags,
                &mut start_type,
                &mut start,
                &mut stop_type,
                &mut stop,
            );

            (
                rate,
                from_glib(flags),
                from_glib(start_type),
788
                GenericFormattedValue::new(from_glib(fmt), start),
789
                from_glib(stop_type),
790
                GenericFormattedValue::new(from_glib(fmt), stop),
791
            )
Sebastian Dröge's avatar
Sebastian Dröge committed
792 793 794 795
        }
    }
}

796
declare_concrete_event!(Navigation);
Sebastian Dröge's avatar
Sebastian Dröge committed
797

798
declare_concrete_event!(Latency);
Sebastian Dröge's avatar
Sebastian Dröge committed
799
impl<'a> Latency<'a> {
800
    pub fn get_latency(&self) -> ::ClockTime {
Sebastian Dröge's avatar
Sebastian Dröge committed
801 802 803
        unsafe {
            let mut latency = mem::uninitialized();

804
            ffi::gst_event_parse_latency(self.as_mut_ptr(), &mut latency);
Sebastian Dröge's avatar
Sebastian Dröge committed
805

806
            from_glib(latency)
Sebastian Dröge's avatar
Sebastian Dröge committed
807 808 809 810
        }
    }
}

811
declare_concrete_event!(Step);
Sebastian Dröge's avatar
Sebastian Dröge committed
812
impl<'a> Step<'a> {
813
    pub fn get(&self) -> (GenericFormattedValue, f64, bool, bool) {
Sebastian Dröge's avatar
Sebastian Dröge committed
814 815 816 817 818 819 820
        unsafe {
            let mut fmt = mem::uninitialized();
            let mut amount = mem::uninitialized();
            let mut rate = mem::uninitialized();
            let mut flush = mem::uninitialized();
            let mut intermediate = mem::uninitialized();

821
            ffi::gst_event_parse_step(
822
                self.as_mut_ptr(),
823 824 825 826 827 828 829 830
                &mut fmt,
                &mut amount,
                &mut rate,
                &mut flush,
                &mut intermediate,
            );

            (
831
                GenericFormattedValue::new(from_glib(fmt), amount as i64),
832 833 834 835
                rate,
                from_glib(flush),
                from_glib(intermediate),
            )
Sebastian Dröge's avatar
Sebastian Dröge committed
836 837 838 839
        }
    }
}

840
declare_concrete_event!(Reconfigure);
Sebastian Dröge's avatar
Sebastian Dröge committed
841

842
declare_concrete_event!(TocSelect);
Sebastian Dröge's avatar
Sebastian Dröge committed
843 844 845 846 847
impl<'a> TocSelect<'a> {
    pub fn get_uid(&self) -> &'a str {
        unsafe {
            let mut uid = ptr::null_mut();

848
            ffi::gst_event_parse_toc_select(self.as_mut_ptr(), &mut uid);
Sebastian Dröge's avatar
Sebastian Dröge committed
849 850 851 852 853 854

            CStr::from_ptr(uid).to_str().unwrap()
        }
    }
}

855
declare_concrete_event!(SelectStreams);
Sebastian Dröge's avatar
Sebastian Dröge committed
856
impl<'a> SelectStreams<'a> {
857
    #[cfg(any(feature = "v1_10", feature = "dox"))]
Sebastian Dröge's avatar
Sebastian Dröge committed
858 859 860 861
    pub fn get_streams(&self) -> Vec<String> {
        unsafe {
            let mut streams = ptr::null_mut();

862
            ffi::gst_event_parse_select_streams(self.as_mut_ptr(), &mut streams);
Sebastian Dröge's avatar
Sebastian Dröge committed
863

Sebastian Dröge's avatar
Sebastian Dröge committed
864
            FromGlibPtrContainer::from_glib_full(streams)
Sebastian Dröge's avatar
Sebastian Dröge committed
865 866 867 868
        }
    }
}

869 870 871 872 873 874
declare_concrete_event!(CustomUpstream);
declare_concrete_event!(CustomDownstream);
declare_concrete_event!(CustomDownstreamOob);
declare_concrete_event!(CustomDownstreamSticky);
declare_concrete_event!(CustomBoth);
declare_concrete_event!(CustomBothOob);
Sebastian Dröge's avatar
Sebastian Dröge committed
875

876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
struct EventBuilder<'a> {
    seqnum: Option<Seqnum>,
    running_time_offset: Option<i64>,
    other_fields: Vec<(&'a str, &'a ToSendValue)>,
}

impl<'a> EventBuilder<'a> {
    fn new() -> Self {
        Self {
            seqnum: None,
            running_time_offset: None,
            other_fields: Vec::new()
        }
    }

    fn seqnum(self, seqnum: Seqnum) -> Self {
        Self {
            seqnum: Some(seqnum),
            .. self
        }
    }

    fn running_time_offset(self, running_time_offset: i64) -> Self {
        Self {
            running_time_offset: Some(running_time_offset),
            .. self
        }
    }

    fn other_fields(self, other_fields: &[(&'a str, &'a ToSendValue)]) -> Self {
        Self {
            other_fields: self.other_fields.iter().cloned()
                .chain(other_fields.iter().cloned())
                .collect(),
            .. self
        }
    }
}

Sebastian Dröge's avatar
Sebastian Dröge committed
915 916
macro_rules! event_builder_generic_impl {
    ($new_fn:expr) => {
917
        pub fn seqnum(self, seqnum: Seqnum) -> Self {
Sebastian Dröge's avatar
Sebastian Dröge committed
918
            Self {
919
                builder: self.builder.seqnum(seqnum),
Sebastian Dröge's avatar
Sebastian Dröge committed
920 921 922 923 924 925
                .. self
            }
        }

        pub fn running_time_offset(self, running_time_offset: i64) -> Self {
            Self {
926
                builder: self.builder.running_time_offset(running_time_offset),
Sebastian Dröge's avatar
Sebastian Dröge committed
927 928 929 930
                .. self
            }
        }

931
        pub fn other_fields(self, other_fields: &[(&'a str, &'a ToSendValue)]) -> Self {
932
            Self {
933
                builder: self.builder.other_fields(other_fields),
934 935 936 937
                .. self
            }
        }

Sebastian Dröge's avatar
Sebastian Dröge committed
938 939 940 941
        pub fn build(mut self) -> Event {
            assert_initialized_main_thread!();
            unsafe {
                let event = $new_fn(&mut self);
942
                if let Some(seqnum) = self.builder.seqnum {
943
                    ffi::gst_event_set_seqnum(event, seqnum.to_glib());
Sebastian Dröge's avatar
Sebastian Dröge committed
944 945
                }

946
                if let Some(running_time_offset) = self.builder.running_time_offset {
Sebastian Dröge's avatar
Sebastian Dröge committed
947 948 949
                    ffi::gst_event_set_running_time_offset(event, running_time_offset);
                }

950
                if !self.builder.other_fields.is_empty() {
951 952 953 954
                    let s = StructureRef::from_glib_borrow_mut(
                        ffi::gst_event_writable_structure(event)
                    );

955
                    for (k, v) in self.builder.other_fields {
956
                        s.set_value(k, v.to_send_value());
957 958 959
                    }
                }

Sebastian Dröge's avatar
Sebastian Dröge committed
960 961 962 963 964 965
                from_glib_full(event)
            }
        }
    }
}

966
pub struct FlushStartBuilder<'a> {
967
    builder: EventBuilder<'a>,
Sebastian Dröge's avatar
Sebastian Dröge committed
968
}
969
impl<'a> FlushStartBuilder<'a> {
970 971
    fn new() -> Self {
        skip_assert_initialized!();
Sebastian Dröge's avatar
Sebastian Dröge committed
972
        Self {
973
            builder: EventBuilder::new(),
Sebastian Dröge's avatar
Sebastian Dröge committed
974 975 976 977 978 979
        }
    }

    event_builder_generic_impl!(|_| ffi::gst_event_new_flush_start());
}

980
pub struct FlushStopBuilder<'a> {
981
    builder: EventBuilder<'a>,
982
    reset_time: bool,
Sebastian Dröge's avatar
Sebastian Dröge committed
983
}
984
impl<'a> FlushStopBuilder<'a> {
985 986
    fn new(reset_time: bool) -> Self {
        skip_assert_initialized!();
Sebastian Dröge's avatar
Sebastian Dröge committed
987
        Self {
988
            builder: EventBuilder::new(),
Sebastian Dröge's avatar
Sebastian Dröge committed